このドキュメントでは、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-ingress
Deployment。これは上り(内向き)プロキシです。上り(内向き)プロキシは、Ingress オブジェクトで指定されたルールに従ってトラフィックを内部 Service に転送します。istio-ingress
Service。この Service は、istio-ingress
Deployment を公開します。istiod
Deployment。これは上り(内向き)コントローラです。上り(内向き)コントローラは、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-service
Service のメンバー Pod に転送します。hello-service
Service のドメイン: 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 を作成する
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