マネージド Anthos Service Mesh の外部 HTTP(S) Load Balancing を構成する

概要

Cloud Load Balancing では、グローバル エニーキャスト ロード バランシング、Google マネージド証明書、Identity and Access Management、クラウド ファイアウォールまたは IDS など、さまざまなクラウド マネージド エッジ機能を使用できます。Anthos Service Mesh は、次のメッシュ Ingress モデルでこれらのエッジ機能をシームレスに統合できます。サービス メッシュ クラウド ゲートウェイは、Kubernetes Gateway API を介して Cloud Load Balancing と同時に Anthos Service Mesh Ingress ゲートウェイを構成する、統合された方法を提供します。

Anthos Service Mesh を使用した Cloud ロードバランサを示す図

以前のユーザーガイドであるエッジからメッシュへ: GKE Ingress によるサービス メッシュ アプリケーションの公開と比べると、サービス メッシュ クラウド ゲートウェイのこのモデルでは 1 つの Kubernetes Gateway リソースを介してデプロイできるようになり、クラウドとクラスタホスト型のロードバランシングを同時にデプロイするプロセスが簡素化されました。

プレビュー版の制限

この機能のプレビュー リリースには次の制限があります。

  • マルチクラスタ Gateway はサポート対象外
  • Autopilot クラスタはサポート対象外
  • 従来のアプリケーション ロードバランサのみがサポートされています。高度なロードバランサと内部 HTTP(S) ロードバランサはサポート対象外です。
  • 外部 HTTP(S) ロードバランサと Anthos Service Mesh Ingress ゲートウェイ間のトラフィックは、TLS を使用して暗号化されます。ただし、外部 HTTP(S) ロードバランサは、Anthos Service Mesh Ingress ゲートウェイから提供された証明書を検証しません。この制限は、Google Cloud HTTP(S) ロードバランサのユーザーすべてに適用されます。
  • Anthos Service Mesh GatewayClasses がクラスタから削除された場合、再インストールは自動的に行われません。ただし、これはこの機能のユーザビリティには影響しません。
  • ルート マッチング ロジックは Gateway API の仕様に準拠していないため、それに代わって HTTPRoute の順序で照合されます。これは、Gateway API の仕様に従って今後のバージョンで変更されます。

要件

  • 1.24 以降を実行している Google Kubernetes Engine(GKE)クラスタにインストールされたマネージド Anthos Service Mesh。その他の GKE Enterprise クラスタはサポートされていません。
  • Kubernetes Gateway API v1beta1 バージョンのみ。

前提条件

  • プロジェクトで次の API を有効にします。

    • compute.googleapis.com
    • container.googleapis.com
    • certificatemanager.googleapis.com
    • serviceusage.googleapis.com
    gcloud services enable \
       compute.googleapis.com \
       container.googleapis.com \
       certificatemanager.googleapis.com \
       serviceusage.googleapis.com
    

単一クラスタ メッシュ用のサービス メッシュ クラウド ゲートウェイをデプロイする

このセクションでは、グローバル外部 HTTP(S) ロードバランサ(従来)と Anthos Service Mesh Ingress ゲートウェイをデプロイする Kubernetes Gateway リソースのデプロイ方法について説明します。

マネージド Anthos Service Mesh を使用して Gateway API を有効にする

  1. クラスタで Gateway API を有効にします。GKE クラスタはバージョン 1.24 以降である必要があります。

  2. rapid または regular をリリース チャンネルとするマネージド Anthos Service Mesh をインストールします。

Gateway リソースをデプロイする

サービス メッシュ クラウド ゲートウェイをデプロイする場合、Kubernetes Gateway リソースを使用して、Cloud Load Balancing と Anthos Service Mesh Ingress ゲートウェイの両方を 1 つのステップでデプロイします。Kubernetes Gateway リソースは Istio Gateway リソースとは異なることに注意してください。

この違いの詳細については、Kubernetes Gateway と Istio Gateway をご覧ください。すべての Kubernetes Gateway には、その種類と固有の機能を示す GatewayClass があります。サービス メッシュ クラウド ゲートウェイには、Cloud Load Balancing と Anthos Service Mesh Ingress ゲートウェイの両方をデプロイする機能を備えた GatewayClass があります。

  1. 次の GatewayClass マニフェストを l7-gateway-class.yaml という名前のファイルに保存します。

    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: GatewayClass
    metadata:
      name: asm-l7-gxlb
    spec:
      controllerName: mesh.cloud.google.com/gateway
    
  2. クラスタに GatewayClass をデプロイします。

    kubectl apply -f l7-gateway-class.yaml
    
  3. インストール後に GatewayClass が存在することを確認します。

    kubectl get gatewayclasses.gateway.networking.k8s.io
    

    出力は次のようになります。

    NAME          CONTROLLER
    asm-l7-gxlb   mesh.cloud.google.com/gateway
    gke-l7-rilb   networking.gke.io/gateway
    gke-l7-gxlb   networking.gke.io/gateway
    

    リソースがすべてデプロイされるまでに数分かかることがあります。想定された出力が表示されない場合は、前提条件が正しく満たされていることを確認してください。

    次の GatewayClass も表示されます。

    gke-l7-gxlb   networking.gke.io/gateway
    

    これは、基盤となる Google Cloud グローバル外部 HTTP(S) ロードバランサをデプロイするために使用されます。

  4. サービス メッシュ クラウド ゲートウェイ専用の Namespace を作成します。

    kubectl create namespace istio-ingress
    
  5. 次の Gateway マニフェストを gateway.yaml という名前のファイルに保存します。

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: servicemesh-cloud-gw
      namespace: istio-ingress
    spec:
      gatewayClassName: asm-l7-gxlb
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          namespaces:
            from: All
    
  6. istio-ingress Namespace のクラスタに Gateway をデプロイします。

    kubectl apply -f gateway.yaml
    
  7. Kubernetes Gateway API オブジェクトが作成されていることを確認します。

    kubectl get gateways.gateway.networking.k8s.io -n istio-ingress
    

    出力は次のようになります。

    NAME                                CLASS         ADDRESS         READY   AGE
    asm-gw-gke-servicemesh-cloud-gw     gke-l7-gxlb   34.111.114.64   True    9m40s
    asm-gw-istio-servicemesh-cloud-gw   istio                                 9m44s
    servicemesh-cloud-gw                asm-l7-gxlb                           9m44s
    

この Kubernetes Gateway API オブジェクトがデプロイされると、次のことが起こります。

  • 外部 HTTP(S) ロードバランサがデプロイされ、構成されます。起動までに数分かかることがありますが、その場合、Gateway は IP アドレスを表示し、作成された Compute Engine ロードバランサのリソースの名前がアノテーションとして表示されます。
  • Anthos Service Mesh Ingress ゲートウェイの Deployment が istio-ingress Namespace に作成されます。これにより、Cloud Load Balancer からトラフィックを受信する Envoy プロキシ インスタンスが作成されます。
  • Cloud ロードバランサがすべてのトラフィックを暗号化し、Anthos Service Mesh Ingress ゲートウェイに転送します。

これで、インターネット トラフィックをメッシュで受け入れるために必要なインフラストラクチャがすべて整いました。これは最も簡単な Gateway のデプロイです。以降のセクションでは、本番環境で使用するために必要なポリシーと機能を追加します。

アプリとルーティングのデプロイ

アプリケーションを Anthos Service Mesh にデプロイして、Gateway 経由でインターネット トラフィックを受信する場合を例にして、機能について詳しく説明します。

  1. default Namespace にラベルを付けてサイドカー インジェクションを有効にします。

    kubectl label namespace default istio-injection=enabled istio.io/rev- --overwrite
    
  2. 次の Gateway マニフェストを whereami.yaml という名前のファイルに保存します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: whereami-v1
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: whereami-v1
      template:
        metadata:
          labels:
            app: whereami-v1
        spec:
          containers:
          - name: whereami
            image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.20
            ports:
              - containerPort: 8080
            env:
            - name: METADATA
              value: "whereami-v1"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: whereami-v1
    spec:
      selector:
        app: whereami-v1
      ports:
      - port: 8080
        targetPort: 8080
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: whereami-v2
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: whereami-v2
      template:
        metadata:
          labels:
            app: whereami-v2
        spec:
          containers:
          - name: whereami
            image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.20
            ports:
              - containerPort: 8080
            env:
            - name: METADATA
              value: "whereami-v2"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: whereami-v2
    spec:
      selector:
        app: whereami-v2
      ports:
      - port: 8080
        targetPort: 8080
    

    このマニフェストは、ID と位置を示す JSON を出力するシンプルなアプリケーション(whereami)の Service/whereami-v1Service/whereami-v2Deployment/whereami-v1Deployment/whereami-v2 を作成するものです。2 種類のバージョンをデプロイします。

  3. Service と Deployment を作成します。

    kubectl apply -f whereami.yaml
    

    準備が完了すると、クラスタ内で 4 つの whereami Pod が実行されます。

  4. 4 つの Pod すべてが稼働していることを確認します。

    kubectl get pods
    

    出力は次のようになります。

    whereami-v1-7c76d89d55-qg6vs       2/2     Running   0          28s
    whereami-v1-7c76d89d55-vx9nm       2/2     Running   0          28s
    whereami-v2-67f6b9c987-p9kqm       2/2     Running   0          27s
    whereami-v2-67f6b9c987-qhj76       2/2     Running   0          27s
    
  5. 次の HTTPRoute マニフェストを http-route.yaml という名前のファイルに保存します。

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: where-route
    spec:
     parentRefs:
     - kind: Gateway
       name: servicemesh-cloud-gw
       namespace: istio-ingress
     hostnames:
     - "where.example.com"
     rules:
     - matches:
       - headers:
         - name: version
           value: v2
       backendRefs:
       - name: whereami-v2
         port: 8080
     - backendRefs:
       - name: whereami-v1
         port: 8080
    
  6. クラスタに http-route.yaml をデプロイします。

    kubectl apply -f http-route.yaml
    

    この HTTPRoute は servicemesh-cloud-gw を参照します。つまり、これらのルーティング ルールを使用して基盤となる Anthos Service Mesh Ingress ゲートウェイを構成するように、サービス メッシュ クラウド ゲートウェイを構成します。HTTPRoute は Istio VirtualService と同じ機能を実行するために Kubernetes Gateway API を使用します。Gateway API は、多くの基盤となる実装を備えた OSS 仕様であるため、異なるロードバランサ(Anthos Service Mesh プロキシや Cloud Load Balancer など)の組み合わせでルーティングを定義するのに最適な API です。

  7. アプリケーションにトラフィックを送信できるように、Gateway から IP アドレスを取得します。

    VIP=$(kubectl get gateways.gateway.networking.k8s.io asm-gw-gke-servicemesh-cloud-gw -o=jsonpath="{.status.addresses[0].value}" -n istio-ingress)
    

    出力は IP アドレスです。

    echo $VIP
    
    34.111.61.135
    
  8. Gateway IP アドレスにトラフィックを送信して、この設定が正しく機能していることを確認します。version: v2 ヘッダーのあるリクエストとヘッダーなしのリクエストを 1 つずつ送信し、2 つのアプリケーション バージョンでルーティングが正しく行われていることを確認します。

    curl ${VIP} -H "host: where.example.com"
    
    {
      "cluster_name": "gke1",
      "host_header": "where.example.com",
      "metadata": "whereami-v1",
      "node_name": "gke-gke1-default-pool-9b3b5b18-hw5z.c.church-243723.internal",
      "pod_name": "whereami-v1-67d9c5d48b-zhr4l",
      "pod_name_emoji": "⚒",
      "project_id": "church-243723",
      "timestamp": "2021-02-08T18:55:01",
      "zone": "us-central1-a"
    }
    
    curl ${VIP} -H "host: where.example.com" -H "version: v2"
    
    {
      "cluster_name": "gke1",
      "host_header": "where.example.com",
      "metadata": "whereami-v2",
      "node_name": "gke-gke1-default-pool-9b3b5b18-hw5z.c.church-243723.internal",
      "pod_name": "whereami-v2-67d9c5d48b-zhr4l",
      "pod_name_emoji": "⚒",
      "project_id": "church-243723",
      "timestamp": "2021-02-08T18:55:01",
      "zone": "us-central1-a"
    }
    

本番環境ゲートウェイのデプロイ

前のセクションでは、サービス メッシュ クラウド ゲートウェイの非常にシンプルな例について説明しました。次の手順では、このシンプルな例を基にして本番環境に対応した設定を行い、上り(内向き)ルーティング機能の一部をクラウド ロードバランサに委任する利点について説明します。

次の例では、前のセクションの servicemesh-cloud-gw を使用して、より安全で管理しやすい Gateway を作成するために以下の機能を追加します。

  • 基盤となるインフラストラクチャが変更されても保持される静的 IP アドレスを持つ Gateway をデプロイします。
  • 自己署名証明書を使用して HTTPS トラフィックを受信するように Gateway を変換します。
  1. 静的外部 IP アドレスを作成します。静的 IP は、基盤となるインフラストラクチャが将来変更されることがあっても、IP アドレスを保持できるため便利です。

    gcloud compute addresses create whereami-ip \
        --global \
        --project PROJECT_ID
    
  2. where-example-com ドメインの自己署名証明書を作成します。

    openssl genrsa -out key.pem 2048
    cat <<EOF >ca.conf
    [req]
    default_bits              = 2048
    req_extensions            = extension_requirements
    distinguished_name        = dn_requirements
    prompt                    = no
    [extension_requirements]
    basicConstraints          = CA:FALSE
    keyUsage                  = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName            = @sans_list
    [dn_requirements]
    0.organizationName        = example
    commonName                = where.example.com
    [sans_list]
    DNS.1                     = where.example.com
    EOF
    
    openssl req -new -key key.pem \
        -out csr.pem \
        -config ca.conf
    
    openssl x509 -req \
        -signkey key.pem \
        -in csr.pem \
        -out cert.pem \
        -extfile ca.conf \
        -extensions extension_requirements \
        -days 365
    
    gcloud compute ssl-certificates create where-example-com \
        --certificate=cert.pem \
        --private-key=key.pem \
        --global \
        --project PROJECT_ID
    

    TLS 証明書はさまざまな方法で生成できます。コマンドラインで手動で生成することも、Google マネージド証明書を使用して生成することもできます。また、社内の公開鍵基盤(PKI)システムによって内部的に生成することも可能です。この例では、自己署名証明書を手動で生成します。通常、自己署名証明書は公開サービスでは使用されませんが、この証明書を使用すると、こうしたコンセプトをわかりやすく説明できます。

    Kubernetes Secret を使用して自己署名証明書を作成する方法の詳細については、ゲートウェイを保護するをご覧ください。

  3. gateway.yaml を次のマニフェストで更新します。

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: servicemesh-cloud-gw
      namespace: istio-ingress
    spec:
      gatewayClassName: asm-l7-gxlb
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          namespaces:
            from: All
      - name: https
        protocol: HTTPS
        port: 443
        allowedRoutes:
          namespaces:
            from: All
        tls:
          mode: Terminate
          options:
            networking.gke.io/pre-shared-certs: where-example-com
      addresses:
      - type: NamedAddress
        value: whereami-ip
    
  4. クラスタに Gateway を再度デプロイします。

    kubectl apply -f gateway.yaml
    
  5. 静的 IP の IP アドレスを取得します。

    VIP=$(gcloud compute addresses describe whereami-ip --global --format="value(address)")
    
  6. curl を使用して Gateway のドメインにアクセスします。このドメインに DNS は構成されていないため、--resolve オプションを使用して、ドメイン名を Gateway の IP アドレスに解決することを curl に通知します。

    curl https://where.example.com --resolve where.example.com:443:${VIP} --cacert cert.pem -v
    

    完了すると、出力は次のようになります。

    ...
    * TLSv1.2 (OUT), TLS handshake, Client hello (1):
    * TLSv1.2 (IN), TLS handshake, Server hello (2):
    * TLSv1.2 (IN), TLS handshake, Certificate (11):
    * TLSv1.2 (IN), TLS handshake, Server key exchange (12):
    * TLSv1.2 (IN), TLS handshake, Server finished (14):
    * TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
    * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
    * TLSv1.2 (OUT), TLS handshake, Finished (20):
    * TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
    * TLSv1.2 (IN), TLS handshake, Finished (20):
    * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
    * ALPN, server accepted to use h2
    * Server certificate:
    *  subject: O=example; CN=where.example.com
    *  start date: Apr 19 15:54:50 2021 GMT
    *  expire date: Apr 19 15:54:50 2022 GMT
    *  common name: where.example.com (matched)
    *  issuer: O=example; CN=where.example.com
    *  SSL certificate verify ok.
    ...
    {
      "cluster_name": "gke1",
      "host_header": "where.example.com",
      "metadata": "where-v1",
      "node_name": "gke-gw-default-pool-51ccbf30-yya8.c.agmsb-k8s.internal",
      "pod_name": "where-v1-84b47c7f58-tj5mn",
      "pod_name_emoji": "😍",
      "project_id": "agmsb-k8s",
      "timestamp": "2021-04-19T16:30:08",
      "zone": "us-west1-a"
    }
    

詳細出力には、次の例のように、TLS handshake が成功した後のアプリケーションからのレスポンスが含まれます。これにより、Gateway で TLS が正しく終端し、アプリケーションがクライアントに応答していることを確認できます。

これで、次のアーキテクチャが正常にデプロイされました。

ASM アーキテクチャ

servicemesh-cloud-gw とその asm-l7-gxlb GatewayClass では、ユーザー エクスペリエンスを簡素化するため、一部の内部インフラストラクチャ コンポーネントが抽象化されています。Cloud Load Balancing が内部証明書を使用して TLS トラフィックを終端します。また、Anthos Service Mesh Ingress ゲートウェイ プロキシ レイヤのヘルスチェックも行います。アプリとルーティングのデプロイでデプロイした whereami-route は、トラフィックを正しいメッシュホストのサービスにルーティングするように Anthos Service Mesh Ingress ゲートウェイ プロキシを構成します。

次のステップ