Cloud Service Mesh の例: カナリア デプロイ


このチュートリアルでは、Cloud Service Mesh を使用してカナリア デプロイをロールアウトする一般的なユースケースを実施します。

カナリア デプロイとは

カナリア デプロイでは、トラフィックのごく一部を新しいバージョンのマイクロサービスに転送し、古いバージョンを段階的に廃止して、ユーザーベース全体に段階的にロールアウトできます。このプロセス中になんらかの問題が発生した場合に、トラフィックを古いバージョンに戻すことができます。Cloud Service Mesh では、新しいサービスを安全に導入できるよう、トラフィックを転送できます。

費用

このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

このチュートリアルの終了後に作成したリソースを削除すれば、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。

始める前に

Online Boutique をデプロイする

  1. kubectl の現在のコンテキストを、Online Boutique をデプロイしたクラスタに設定します。

    gcloud container clusters get-credentials CLUSTER_NAME  \
    --project=PROJECT_ID \
    --zone=CLUSTER_LOCATION 
    
  2. サンプル アプリケーションと Ingress ゲートウェイの名前空間を作成します。

    kubectl create namespace onlineboutique
    
  3. Envoy プロキシを自動的に挿入するには、onlineboutique 名前空間にラベルを付けます。自動サイドカー インジェクションを有効にする方法の手順を行います。

  4. サンプルアプリをデプロイする。このチュートリアルでは、マイクロサービスのデモアプリである Online Boutique をデプロイします。

    kubectl apply \
    -n onlineboutique \
    -f https://raw.githubusercontent.com/GoogleCloudPlatform/anthos-service-mesh-samples/main/docs/shared/online-boutique/kubernetes-manifests.yaml
    
  5. 次のコマンドを実行して、productcatalog デプロイにラベル version=v1 を追加します。

    kubectl patch deployments/productcatalogservice -p '{"spec":{"template":{"metadata":{"labels":{"version":"v1"}}}}}' \
    -n onlineboutique
    

    デプロイしたサービスを表示します。

    kubectl get pods -n onlineboutique
    

    予想される出力:

    NAME                                     READY   STATUS    RESTARTS   AGE
    adservice-85598d856b-m84m6               2/2     Running   0          2m7s
    cartservice-c77f6b866-m67vd              2/2     Running   0          2m8s
    checkoutservice-654c47f4b6-hqtqr         2/2     Running   0          2m10s
    currencyservice-59bc889674-jhk8z         2/2     Running   0          2m8s
    emailservice-5b9fff7cb8-8nqwz            2/2     Running   0          2m10s
    frontend-77b88cc7cb-mr4rp                2/2     Running   0          2m9s
    loadgenerator-6958f5bc8b-55q7w           2/2     Running   0          2m8s
    paymentservice-68dd9755bb-2jmb7          2/2     Running   0          2m9s
    productcatalogservice-84f95c95ff-c5kl6   2/2     Running   0          114s
    recommendationservice-64dc9dfbc8-xfs2t   2/2     Running   0          2m9s
    redis-cart-5b569cd47-cc2qd               2/2     Running   0          2m7s
    shippingservice-5488d5b6cb-lfhtt         2/2     Running   0          2m7s
    

    アプリケーションのすべての Pod が稼働状態になり、READY 列に 2/2 が入力されます。これは、Pod に Envoy サイドカー プロキシが正常に挿入されたことを示します。

  6. productcatalog の v1 に VirtualServiceDestinationRule をデプロイします。

    kubectl apply -f destination-vs-v1.yaml -n onlineboutique
    
    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: productcatalogservice
    spec:
      host: productcatalogservice
      subsets:
      - labels:
          version: v1
        name: v1
    ---
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: productcatalogservice
    spec:
      hosts:
      - productcatalogservice
      http:
      - route:
        - destination:
            host: productcatalogservice
            subset: v1

    なお、リソースには v1 のみが存在します。

  7. Ingress の外部 IP アドレスを使用して、ブラウザでアプリケーションにアクセスします。

    kubectl get services -n GATEWAY_NAMESPACE
    

次のセクションでは、Cloud Service Mesh の UI について説明し、指標を表示する方法を示します。

Google Cloud コンソールにサービスをデプロイして表示する

  1. Google Cloud コンソールで、[GKE Enterprise Services] ページに移動します。

    [GKE Enterprise Services] に移動

  2. デフォルトでは、[テーブル] ビューにサービスを表示します。

    テーブルの概要では、すべてのサービスと重要な指標を一目で確認できます。

    すべてのサービス ワークロード

  3. 右上の [トポロジ] をクリックします。ここでは、相互にサービスとそのインタラクションが表示されます。

    サービスを展開して、各サービスの 1 秒あたりのリクエスト数を表示するには、それらにカーソルを合わせます。

    すべてのサービス ワークロード トポロジ

  4. [テーブルビュー] に戻ります。

  5. [サービス テーブル] で productcatalogservice を選択します。ここでは、サービスの概要が表示されます。

  6. 画面左側にある [トラフィック] をクリックします。

  7. productcatalogservice への受信トラフィックの 100% がワークロード サービスに送信されるようにします。

    productcatalog svc トラフィック

次のセクションでは、productcatalog サービスの v2 を作成します。

サービスの v2 をデプロイする

  1. このチュートリアルでは、productcatalogservice-v2 を使用して、EXTRA_LATENCY フィールドを含むリクエストに 3 秒のレイテンシを設定します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: productcatalogservice-v2
    spec:
      selector:
        matchLabels:
          app: productcatalogservice
      template:
        metadata:
          labels:
            app: productcatalogservice
            version: v2
        spec:
          containers:
          - env:
            - name: PORT
              value: '3550'
            - name: EXTRA_LATENCY
              value: 3s
            name: server
            image: gcr.io/google-samples/microservices-demo/productcatalogservice:v0.3.6
            livenessProbe:
              exec:
                command: ["/bin/grpc_health_probe", "-addr=:3550"]
            ports:
            - containerPort: 3550
            readinessProbe:
              exec:
                command: ["/bin/grpc_health_probe", "-addr=:3550"]
            resources:
              limits:
                cpu: 200m
                memory: 128Mi
              requests:
                cpu: 100m
                memory: 64Mi
          terminationGracePeriodSeconds: 5

    このリソースを onlineboutique 名前空間に適用します。

    kubectl apply -f productcatalog-v2.yaml -n onlineboutique
    
  2. アプリケーションの Pod を確認します。

    kubectl get pods -n onlineboutique
    

    予想される出力:

    NAME                                     READY   STATUS    RESTARTS   AGE
    adservice-85598d856b-8wqfd                  2/2     Running   0          25h
    cartservice-c77f6b866-7jwcr                 2/2     Running   0          25h
    checkoutservice-654c47f4b6-n8c6x            2/2     Running   0          25h
    currencyservice-59bc889674-l5xw2            2/2     Running   0          25h
    emailservice-5b9fff7cb8-jjr89               2/2     Running   0          25h
    frontend-77b88cc7cb-bwtk4                   2/2     Running   0          25h
    loadgenerator-6958f5bc8b-lqmnw              2/2     Running   0          25h
    paymentservice-68dd9755bb-dckrj             2/2     Running   0          25h
    productcatalogservice-84f95c95ff-ddhjv      2/2     Running   0          25h
    productcatalogservice-v2-6df4cf5475-9lwjb   2/2     Running   0          8s
    recommendationservice-64dc9dfbc8-7s7cx      2/2     Running   0          25h
    redis-cart-5b569cd47-vw7lw                  2/2     Running   0          25h
    shippingservice-5488d5b6cb-dj5gd            2/2     Running   0          25h
    

    2 つの productcatalogservices が現在表示されていることに注意してください。

  3. DestinationRule は、サービスのサブセットを指定する方法です。このシナリオでは、productcatalogservice の v1 用と v2 用のサブセットがあります。

    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: productcatalogservice
    spec:
      host: productcatalogservice
      subsets:
      - labels:
          version: v1
        name: v1
      - labels:
          version: v2
        name: v2

    labels フィールドに注意してください。productcatalogservice のバージョンは、VirtualService によってトラフィックが転送された後に区別されます。

    DestinationRule を適用します。

    kubectl apply -f destination-v1-v2.yaml -n onlineboutique
    

v1 と v2 間のトラフィックを分割する

  1. VirtualService は、トラフィックのごく一部を productcatalogservice の v2 に設定する方法です。

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: productcatalogservice
    spec:
      hosts:
      - productcatalogservice
      http:
      - route:
        - destination:
            host: productcatalogservice
            subset: v1
          weight: 75
        - destination:
            host: productcatalogservice
            subset: v2
          weight: 25

    サブセット フィールドはバージョンを示し、重みフィールドはトラフィック分割の割合を示します。トラフィックの 75% が productcatalog の v1 に、25% が v2 に送信されます。

    VirtualService を適用します。

    kubectl apply -f vs-split-traffic.yaml -n onlineboutique
    

クラスタの Ingress の EXTERNAL_IP にアクセスすると、フロントエンドがロードされるのが定期的に遅くなっていることがわかります。

次のセクションでは、GKE Enterprise の Google Cloud コンソールでのトラフィック分割について説明します。

Google Cloud コンソールでトラフィック分割を確認する

  1. Google Cloud コンソールに戻り、[GKE Enterprise Services] ページに移動します。 [GKE Enterprise Services] に移動

  2. 右上の [トポロジ] をクリックします。

    productcatalogservice ワークロードを開きますproductcatalogserviceproductcatalogservice-v2 のデプロイが表示されます。

    productcatalog svc v1 v2 トラフィックのトポロジ

  3. [テーブルビュー] に戻ります。[サービス テーブル] で productcatalogservice をクリックします。左側のナビゲーション バーにある [トラフィック] に戻ります。

  4. 受信トラフィックが、VirtualService ファイルで指定されている割合で v1 と v2 に分割され、productcatalog サービスのワークロードが 2 つあることに注意してください。

    画面の右側にリクエスト、エラー率、レイテンシの指標が表示されます。Cloud Service Mesh では、各サービスにこれらの指標の概要が表示され、オブザーバビリティが確保されます。

    productcatalog svc v1 v2 トラフィック

特定バージョンへのロールアウトまたはロールバック

カナリア デプロイ中に指標を監視した後、新しいサービスにロールアウトするか、VirtualService リソースを使用して古いサービスにロールバックできます。

ロールアウト

v2 サービスの動作に問題がなければ、v2 サービスへのトラフィックの動作を徐々に増やします。最終的には、100% のトラフィックが新しいサービスに転送されます。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: productcatalogservice
spec:
  hosts:
  - productcatalogservice
  http:
  - route:
    - destination:
        host: productcatalogservice
        subset: v2

すべてのトラフィックを productcatalogservice の v2 に転送するには:

kubectl apply -f vs-v2.yaml -n onlineboutique

ロールバック

v1 サービスにロールバックする必要がある場合は、単に先ほどの destination-vs-v1.yaml を適用します。これにより、トラフィックは productcatalogservice の v1 にのみ転送されます。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: productcatalogservice
spec:
  hosts:
  - productcatalogservice
  http:
  - route:
    - destination:
        host: productcatalogservice
        subset: v1

すべてのトラフィックを productcatalogservice の v1 に転送するには:

kubectl apply -f vs-v1.yaml -n onlineboutique

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

このチュートリアルで使用したリソースについて、これ以降 Google Cloud アカウントに課金されないようにするには、プロジェクトを削除するか、個々のリソースを削除します。

プロジェクトの削除

  1. Cloud Shell で、プロジェクトを削除します。

    gcloud projects delete PROJECT_ID
    

リソースの削除

  • 追加料金の発生を回避するには、クラスタを削除します。

    gcloud container clusters delete  CLUSTER_NAME  \
    --project=PROJECT_ID \
    --zone=CLUSTER_LOCATION 
    
  • クラスタを維持して Online Boutique のサンプルを削除するには:

    1. アプリケーションの名前空間を削除します。

      kubectl delete -f namespace onlineboutique
      

      予想される出力:

      namespace "onlineboutique" deleted
      
    2. サービス エントリを削除します。

      kubectl delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/main/istio-manifests/frontend.yaml -n onlineboutique
      kubectl delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/main/istio-manifests/frontend-gateway.yaml -n onlineboutique
      

      予想される出力:

      serviceentry.networking.istio.io "allow-egress-googleapis" deleted
      serviceentry.networking.istio.io "allow-egress-google-metadata" deleted
      

次のステップ