Service と Ingress を作成する

このドキュメントでは、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 の使用: クラスタノードのいずれかで実行されているクライアントが、portclusterIP にリクエストを送信します。この例では、10.96.14.249:60000 です。リクエストは、targetPort 上のメンバー Pod に転送されます。この例では、POD_IP_ADDRESS:50000 です。

  • kubernetes-port の使用: クラスタノードのいずれかで実行されているクライアントが、portclusterIP にリクエストを送信します。この例では、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-worldserviceName: hello-serviceservicePort: 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-kubernetesserviceName: hello-serviceservicePort: 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

手順は次のとおりです。

  1. ルート証明書と秘密鍵を作成します。この例では、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
    
  2. 証明書署名リクエストを作成します。

    openssl req -out server.csr -newkey rsa:2048 -nodes -keyout server.key -subj "/CN=altostrat.com/O=Example Org"
    
  3. 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 プロキシの秘密鍵
  4. サービス提供側の証明書と鍵を保持する 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-ingressmy-ingress-2 など)に置き換えます。

Service を削除します。

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete service hello-service

Deployment を削除します。

kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete deployment hello-deployment