このドキュメントでは、Google Distributed Cloud のユーザー クラスタに Kubernetes Ingress オブジェクトを作成する方法について説明します。1 つの Ingress は 1 つ以上の Service オブジェクトに関連付けられます。それぞれの Service オブジェクトは、Pod のセットに関連付けられます。
始める前に
管理ワークステーションへの SSH 接続を確立します。
Deployment を作成する
Deployment のマニフェストを次に示します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-deployment
spec:
selector:
matchLabels:
greeting: hello
replicas: 3
template:
metadata:
labels:
greeting: hello
spec:
containers:
- name: hello-world
image: "gcr.io/google-samples/hello-app:2.0"
env:
- name: "PORT"
value: "50000"
- name: hello-kubernetes
image: "gcr.io/google-samples/node-hello:1.0"
env:
- name: "PORT"
value: "8080"
この演習を進めるにあたって、この Deployment のマニフェストについて次のことを理解しておくことが重要です。
Deployment に属する各 Pod には
greeting: helloラベルが付いています。各 Pod には 2 つのコンテナがあります。
envフィールドは、hello-appコンテナは TCP ポート 50000 でリッスンし、node-helloコンテナは TCP ポート 8080 でリッスンするように指定します。hello-appの場合、hello-app ソースコードを見るとPORT環境変数の効果がわかります。
このマニフェストを hello-deployment.yaml という名前のファイルにコピーして Deployment を作成します。
kubectl apply --kubeconfig USER_CLUSTER_KUBECONFIG -f hello-deployment.yaml
USER_CLUSTER_KUBECONFIG は、クラスタの kubeconfig ファイルのパスです。
Service を使用して Deployment を公開する
クライアントが Deployment の Pod にリクエストを安定して送信するには、Service を作成します。
Deployment をクラスタ内のクライアントに公開する Service のマニフェストは次のとおりです。
apiVersion: v1
kind: Service
metadata:
name: hello-service
spec:
type: ClusterIP
selector:
greeting: hello
ports:
- name: world-port
protocol: TCP
port: 60000
targetPort: 50000
- name: kubernetes-port
protocol: TCP
port: 60001
targetPort: 8080
マニフェストを hello-service.yaml という名前のファイルにコピーして、Service を作成します。
kubectl apply --kubeconfig USER_CLUSTER_KUBECONFIG -f hello-service.yaml
Service を表示します。
kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get service hello-service --output yaml
出力には、Service に対して指定された clusterIP の値が表示されます。例:
apiVersion: v1
kind: Service
metadata:
annotations:
...
spec:
clusterIP: 10.96.14.249
clusterIPs:
- 10.96.14.249
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- name: world-port
port: 60000
protocol: TCP
targetPort: 50000
- name: kubernetes-port
port: 60001
protocol: TCP
targetPort: 8080
selector:
greeting: hello
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
上述の出力では、ports フィールドは Kubernetes ServicePort オブジェクトの配列であり、1 つは world-port、もう 1 つは kubernetes-port という名前です。
クライアントが Service を呼び出す方法は次のとおりです。
world-portの使用: クラスタノードのいずれかで実行されているクライアントが、portのclusterIPにリクエストを送信します。この例では、10.96.14.249:60000 です。リクエストは、targetPort上のメンバー Pod に転送されます。この例では、POD_IP_ADDRESS:50000 です。kubernetes-portの使用: クラスタノードのいずれかで実行されているクライアントが、portのclusterIPにリクエストを送信します。この例では、10.96.14.249:60001 です。リクエストは、targetPort上のメンバー Pod に転送されます。この例では、POD_IP_ADDRESS:8080 です。
Ingress コンポーネント
Ingress に関連する一部のクラスタ コンポーネントは次のとおりです。
istio-ingressDeployment。これは上り(内向き)プロキシです。上り(内向き)プロキシは、Ingress オブジェクトで指定されたルールに従ってトラフィックを内部 Service に転送します。istio-ingressService。この Service は、istio-ingressDeployment を公開します。istiodDeployment。これは上り(内向き)コントローラです。上り(内向き)コントローラは、Ingress オブジェクトの作成を監視し、それに応じて Ingress プロキシを構成します。
Ingress を作成する
Ingress のマニフェストを次に示します。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- http:
paths:
- path: /greet-the-world
pathType: Exact
backend:
service:
name: hello-service
port:
number: 60000
- path: /greet-kubernetes
pathType: Exact
backend:
service:
name: hello-service
port:
number: 60001
このマニフェストを my-ingress.yaml という名前のファイルにコピーし、次のようにして Ingress を作成します。
kubectl apply --kubeconfig USER_CLUSTER_KUBECONFIG -f my-ingress.yaml
ユーザー クラスタを作成する場合は、クラスタ構成ファイルで loadbalancer.ingressVip の値を指定します。この IP アドレスは、クラスタ ロードバランサ上に構成されます。Ingress を作成すると、Ingress には、その外部 IP アドレスと同じ VIP が付与されます。
クライアントがユーザー クラスタの上り(内向き)VIP にリクエストを送信すると、そのリクエストはロードバランサに転送されます。ロードバランサは、istio-ingress Service を使用してユーザー クラスタで実行される Ingress プロキシにリクエストを転送します。Ingress プロキシは、リクエスト URL のパスに応じて、異なるバックエンドにリクエストを転送するように構成されています。
/greet-the-world パス
Ingress マニフェストで、パス /greet-the-world が serviceName: hello-service と servicePort: 60000 に関連付けられていることを示すルールを確認できます。hello-service Service の world-port セクションの port 値が 60000 であることを思い出してください。
- name: world-port
port: 60000
protocol: TCP
targetPort: 50000
Ingress サービスが、リクエストを clusterIP:50000 に転送します。その後、リクエストは、hello-service Service のメンバー Pod のいずれかに送信されます。送信された Pod 内のポート 50000 でリッスンするコンテナに、Hello World! メッセージが表示されます。
/greet-kubernetes パス
Ingress マニフェストで、パス /greet-kubernetes が serviceName: hello-service と servicePort: 60001 に関連付けられていることを示すルールを確認できます。hello-service Service の kubernetes-port セクションの port 値が 60001 であることを思い出してください。
- name: kubernetes-port
port: 60001
protocol: TCP
targetPort: 8080
Ingress サービスはリクエストを clusterIP: 8080 に転送します。その後、リクエストは、hello-service Service のメンバー Pod のいずれかに送信されます。送信された Pod 内のポート 8080 でリッスンするコンテナに、Hello Kubernetes! メッセージが表示されます。
Ingress をテストする
/greet-the-world パスを使用して Ingress をテストします。
curl USER_CLUSTER_INGRESS_VIP/greet-the-world
USER_CLUSTER_INGRESS_VIP は、Ingress の外部 IP アドレスに置き換えます。
出力には、Hello, world! メッセージが表示されます。
Hello, world! Version: 2.0.0 Hostname: ...
/greet-kubernetes パスを使用して Ingress をテストします。
curl USER_CLUSTER_INGRESS_VIP/greet-kubernetes
出力には、Hello, Kubernetes! メッセージが表示されます。
Hello Kubernetes!
Ingress 用に HTTPS を設定する
クライアントからの HTTPS リクエストを受け入れるには、Ingress プロキシは証明書を持っていなければなりません。これにより、適切な送信先であることをクライアントに示すことができます。このプロキシには、HTTPS handshake を実行するための秘密鍵も必要です。
以下の例では、次のエンティティを使用します。
Ingress プロキシ: HTTPS handshake に加わり、パケットを
hello-serviceService のメンバー Pod に転送します。hello-serviceService のドメイン: Example Org の altostrat.com
手順は次のとおりです。
ルート証明書と秘密鍵を作成します。この例では、Root CA Example Org の
root.ca.example.comのルート認証局を使用します。openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=Root CA Example Inc./CN=root.ca.example.com' -keyout root-ca.key -out root-ca.crt
証明書署名リクエストを作成します。
openssl req -out server.csr -newkey rsa:2048 -nodes -keyout server.key -subj "/CN=altostrat.com/O=Example Org"
Ingress プロキシのサービス証明書を作成します。
openssl x509 -req -days 365 -CA root-ca.crt -CAkey root-ca.key -set_serial 0 -in server.csr -out server.crt
これで、次の証明書と鍵が作成されました。
root-ca.crt: ルート CA の証明書root-ca.key: ルート CA の秘密鍵server.crt: Ingress プロキシの証明書を提供server.key: Ingress プロキシの秘密鍵
サービス提供側の証明書と鍵を保持する Kubernetes Secret を作成します。
kubectl create secret tls example-server-creds --key=server.key --cert=server.crt --namespace gke-system
生成された Secret の名前は
example-server-credsです。
Deployment と Service を作成する
このガイドの HTTP 部分で Deployment と Service を作成した場合は、そのままにしておきます。作成していない場合は、HTTP 用の手順に沿って作成します。
Ingress を作成する
HTTPS の Ingress の作成は HTTP の Ingress の作成に似ていますが、HTTPS の Ingress 仕様には、ホストと Secret を指定する tls セクションが含まれています。tls セクションの hosts は、rules セクションの host と明示的に一致させる必要があります。
バックエンド サービスが別の Namespace にある場合は、Ingress と同じ Namespace に ExternalName タイプの Service を作成し、トラフィックをバックエンド サービスに転送する必要があります。
HTTP の部分で Ingress をすでに作成している場合は、その Ingress を削除して続行します。
Ingress を削除します。
kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete ingress my-ingress
以前に作成した Service のトラフィックを処理するには、tls セクションを持つ新しい Ingress を作成します。これにより、クライアントと上り(内向き)プロキシ間の HTTPS が有効になります。
Ingress のマニフェストを次に示します。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress-2
spec:
tls:
- hosts:
- altostrat.com
secretName: example-server-creds
rules:
- host: altostrat.com
http:
paths:
- path: /greet-the-world
pathType: Exact
backend:
service:
name: hello-service
port:
number: 60000
- path: /greet-kubernetes
pathType: Exact
backend:
service:
name: hello-service
port:
number: 60001
このマニフェストを my-ingress-2.yaml という名前のファイルに保存して、Ingress を作成します。
kubectl apply --kubeconfig USER_CLUSTER_KUBECONFIG -f my-ingress-2.yaml
テストして確認します。
/greet-the-world パスをテストします。
curl -v --resolve altostrat.com:443:USER_CLUSTER_INGRESS_VIP https://altostrat.com/greet-the-world --cacert root-ca.crt
出力:
Hello, world! Version: 2.0.0 Hostname: hello-deployment-5ff7f68854-wqzp7
/greet-kubernetesパスをテストします。curl -v --resolve altostrat.com:443:USER_CLUSTER_INGRESS_VIP https://altostrat.com/greet-kubernetes --cacert root-ca.crt
出力:
Hello Kubernetes!
クリーンアップ
Ingress を削除します。
kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete ingress INGRESS_NAME
INGRESS_NAME は、Ingress の名前(my-ingress や my-ingress-2 など)に置き換えます。
Service を削除します。
kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete service hello-service
Deployment を削除します。
kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete deployment hello-deployment