すべてのプロダクト
Search
ドキュメントセンター

Container Service for Kubernetes:ゼロダウンタイムデプロイ:ローリングアップデートとグレースフルシャットダウン

最終更新日:Apr 01, 2026

Container Service for Kubernetes (ACK) クラスター内のアプリケーションをサービス中断なしで更新するには、readiness プローブ、readinessGates、preStop フック、および Server Load Balancer (SLB) の接続ドレインを使用して Deployment を設定します。この構成により、スムーズなトラフィック移行と継続的な高可用性が実現します。

仕組み

サービスのアップグレード中に高可用性を確保するために、ステートレスアプリケーション (Deployment) にはローリングアップデート戦略を使用できます。この戦略では、Pod を 1 つずつ置き換えることで、受信トラフィックに対する Pod の継続的な可用性を確保します。コアプロセスは、以下のフェーズに分かれています。

  1. 起動フェーズ:まず、新しいバージョン (v2) の Pod が作成されます。Kubernetes は、新しい Pod が readiness プローブに合格し、リクエストを処理できることを確認するまで待機します。それまでは、Pod は Service からのトラフィックを受信しません。

  2. トラフィック移行フェーズ: readinessGates が有効化されると、新しいポッドはまず readiness チェックに合格する必要があります。その後、その IP は関連付けられたサービスのエンドポイントに登録され、ロードバランサー (SLB) のバックエンドサーバーグループと同期されて、トラフィックの受信を開始します。続いて、システムは旧バージョン (v1) のポッドに終了シグナルを送信し、エンドポイントからその IP を削除することで、新しいリクエストを受信しないようにします。

    詳細については、「readinessGates の仕組み」をご参照ください。
  3. グレースフルシャットダウンフェーズ: 古い Pod は削除される前に、事前定義された preStop フックを実行し、終了猶予期間 (terminationGracePeriodSeconds) を使用して確立された接続の処理を完了する一方、SLB は処理中のリクエストに対して接続ドレインを実行します。このプロセスにより、すべての進行中のリクエストが確実に完了し、ダウンタイムなしのローリングアップデートが実現します。

前提条件

  • クラスターのバージョンは 1.24 以降である必要があります。詳細については、「クラスターのアップグレード」をご参照ください。

  • cloud-controller-manager コンポーネントは v2.10.0 以降です。詳細については、「Cloud Controller Manager」をご参照ください。

サンプルアプリケーションのデプロイ

次の例では、ステートレスな NGINX アプリケーションをデプロイする方法を説明します。

コンソール

  1. ACK クラスター ページで、対象クラスターの名前をクリックします。左側のナビゲーションウィンドウで、Workloads > Deployments の順にクリックします。

  2. 展開 ページで、YAML のリソースの作成 をクリックします。次の内容をテンプレートエディターにコピーし、デプロイ をクリックします。

    サンプルアプリケーションの YAML

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment-demo
    spec:
      replicas: 1                 # 本番環境の高可用性のために 2 以上に設定します。デモンストレーション目的で 1 に設定します。
      selector:
        matchLabels:
          app: nginx-demo
      # ローリングアップデート戦略:更新中のサービス可用性を確保します。
      # strategy:
        # type: RollingUpdate     # Deployment のデフォルト戦略です。
        # rollingUpdate:
          # maxUnavailable: "25%" # デフォルト。更新中に利用不可にできる Pod の最大 25% です。
          # maxSurge: "25%"       # デフォルト。希望のレプリカ数を超えて作成できる Pod の最大 25% です。
      template:
        metadata:
          labels:
            app: nginx-demo 
        spec:
          # Pod レベルのグレースフルシャットダウンの制限。preStop の実行時間とアプリのクリーンアップ時間の合計より大きい必要があります。
          terminationGracePeriodSeconds: 60 
          readinessGates:
          - conditionType: service.readiness.alibabacloud.com/nginx-demo-service # nginx-demo-service Service の Readiness Gate を設定します。
          containers:
          - name: nginx
            image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
            ports:
            - containerPort: 80
            resources:
              requests:
                cpu: 500m
                memory: 1Gi
              limits:
                cpu: 500m
            # --- ヘルスチェックプローブ ---
            # startup probe:コンテナ内のアプリケーションが起動したことを確認します。
            startupProbe:
              httpGet:
                path: / # デフォルトの NGINX ルートパスへのアクセスは、起動が成功したことを示します。
                port: 80
              # 起動に十分な時間を許可します。合計タイムアウト = failureThreshold * periodSeconds。
              # ここでは、30 * 10 = 300 秒です。
              failureThreshold: 30
              periodSeconds: 10
            # readiness probe:コンテナがトラフィックを受信する準備ができているかどうかを判断します。
            readinessProbe:
              httpGet:
                path: /
                port: 80
              initialDelaySeconds: 5  # コンテナ起動後 5 秒でプローブを開始します。
              periodSeconds: 5        # 5 秒ごとにプローブします。
              timeoutSeconds: 2       # プローブのタイムアウト期間です。
              successThreshold: 1     # 1 回の成功で Pod は準備完了とマークされます。
              failureThreshold: 3     # 3 回連続で失敗すると、Pod は準備未完了とマークされます。
            # --- Pod のグレースフルシャットダウン設定 ---
            lifecycle:
              preStop:
                exec:
                  # 信頼性の高いグレースフルシャットダウンのために、アプリケーションロジックに基づいて処理中のリクエストを処理するカスタムフックを定義します。
                  # sleep のみの使用は、クリーンな終了を保証しないため推奨されません。
                  command: ["sh", "-c", "sleep 30 && /usr/sbin/nginx -s quit"]
    ---           
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-demo-service
      annotations:
        # 接続ドレインのタイムアウト。この値は、アプリケーションの preStop ロジックと一致させる必要があります。範囲:10-900。
        service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain-timeout: "30" 
        # 接続ドレインを有効にします。
        service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain: "on"
    spec:
      type: LoadBalancer
      selector:
        app: nginx-demo 
      ports:
        - protocol: TCP
          port: 80
  3. ポップアップウィンドウで、対象のステートレスアプリケーションを見つけ、ビュー をクリックし、Pod のステータスが Running であることを確認します。 

kubectl

  1. クラスターの kubeconfig ファイルを取得し、kubectl を使用してクラスターに接続します

  2. 次の YAML 内容を nginx-demo.yaml という名前のファイルに保存します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment-demo
    spec:
      replicas: 1                 # 本番環境の高可用性のために 2 以上に設定します。デモンストレーション目的で 1 に設定します。
      selector:
        matchLabels:
          app: nginx-demo
      # ローリングアップデート戦略:更新中のサービス可用性を確保します。
      # strategy:
        # type: RollingUpdate     # Deployment のデフォルト戦略です。
        # rollingUpdate:
          # maxUnavailable: "25%" # デフォルト。更新中に利用不可にできる Pod の最大 25% です。
          # maxSurge: "25%"       # デフォルト。希望のレプリカ数を超えて作成できる Pod の最大 25% です。
      template:
        metadata:
          labels:
            app: nginx-demo 
        spec:
          # Pod レベルのグレースフルシャットダウンの制限。preStop の実行時間とアプリのクリーンアップ時間の合計より大きい必要があります。
          terminationGracePeriodSeconds: 60 
          readinessGates:
          - conditionType: service.readiness.alibabacloud.com/nginx-demo-service # nginx-demo-service Service の Readiness Gate を設定します。
          containers:
          - name: nginx
            image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
            ports:
            - containerPort: 80
            resources:
              requests:
                cpu: 500m
                memory: 1Gi
              limits:
                cpu: 500m
            # --- ヘルスチェックプローブ ---
            # startup probe:コンテナ内のアプリケーションが起動したことを確認します。
            startupProbe:
              httpGet:
                path: / # デフォルトの NGINX ルートパスへのアクセスは、起動が成功したことを示します。
                port: 80
              # 起動に十分な時間を許可します。合計タイムアウト = failureThreshold * periodSeconds。
              # ここでは、30 * 10 = 300 秒です。
              failureThreshold: 30
              periodSeconds: 10
            # readiness probe:コンテナがトラフィックを受信する準備ができているかどうかを判断します。
            readinessProbe:
              httpGet:
                path: /
                port: 80
              initialDelaySeconds: 5  # コンテナ起動後 5 秒でプローブを開始します。
              periodSeconds: 5        # 5 秒ごとにプローブします。
              timeoutSeconds: 2       # プローブのタイムアウト期間です。
              successThreshold: 1     # 1 回の成功で Pod は準備完了とマークされます。
              failureThreshold: 3     # 3 回連続で失敗すると、Pod は準備未完了とマークされます。
            # --- Pod のグレースフルシャットダウン設定 ---
            lifecycle:
              preStop:
                exec:
                  # 信頼性の高いグレースフルシャットダウンのために、アプリケーションロジックに基づいて処理中のリクエストを処理するカスタムフックを定義します。
                  # sleep のみの使用は、クリーンな終了を保証しないため推奨されません。
                  command: ["sh", "-c", "sleep 30 && /usr/sbin/nginx -s quit"]
    ---           
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-demo-service
      annotations:
        # 接続ドレインのタイムアウト。この値は、アプリケーションの preStop ロジックと一致させる必要があります。範囲:10-900。
        service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain-timeout: "30" 
        # 接続ドレインを有効にします。
        service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain: "on"
    spec:
      type: LoadBalancer
      selector:
        app: nginx-demo 
      ports:
        - protocol: TCP
          port: 80
  3. NGINX アプリケーションをデプロイし、Service を作成します。

    kubectl apply -f nginx-demo.yaml
  4. 対象のアプリケーション Pod が Running 状態であることを確認します。

    kubectl get pod | grep nginx-deployment-demo
  • Pod の readiness チェック

    • startupProbe (起動プローブ):Java アプリケーションなどの起動が遅いアプリケーションが起動を完了したかどうかをチェックします。起動プローブが成功するまで、readiness プローブと liveness プローブは実行されません。これにより、Kubelet が起動の遅さを障害と誤判断してコンテナを再起動するのを防ぎます。

    • readinessProbe (readiness プローブ):コンテナが外部リクエストを処理する準備ができているかどうかを判断します。readiness チェックが成功すると、Pod の IP アドレスが関連するすべての Service の Endpoints に追加されます。これは、Pod がトラフィックを受け入れられることを示します。

    • readinessGatesreadinessProbe に加えて、readinessGates も準備完了ステータスを示した場合にのみ、Pod はトラフィックを受け入れる準備が完全に整ったと見なされます。

  • グレースフルシャットダウン

    • アプリケーションのグレースフルシャットダウン

      • preStop:コンテナが終了する前に実行されるフックコマンドです。アプリケーションのグレースフルシャットダウン用のコマンドを設定して、すべての処理中のリクエストが処理されるようにします。これにより、サービスが中断なくシャットダウンされることが保証されます。

        必要に応じてカスタムフックメソッドを設定してください。sleep コマンドのみを使用すると、グレースフルシャットダウンプロセスが正しく終了しない可能性があります。
      • terminationGracePeriodSeconds:Pod が終了対象としてマークされてから SIGKILL シグナルで強制的に終了されるまでの合計時間です。デフォルトは 30 秒です。この値は、preStop フックの実行時間とコンテナ自体のクリーンアップ時間の合計をカバーするのに十分な長さでなければなりません。

    • SLB 接続ドレイン

      • service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain アノテーション:Server Load Balancer (SLB) の接続ドレイン機能を有効にします。

      • service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain-timeout:接続ドレインのタイムアウト期間 (秒単位) です。この値は、preStop フックで処理中のリクエストを処理するために必要な時間に近い値を設定することを推奨します。

  • ローリングアップデート戦略

    • strategy:Deployment のデフォルトの更新戦略は RollingUpdate です。この戦略は、段階的な置換方式を使用します。新しい Pod を徐々に作成し、新しい Pod の準備ができた後に対応する古い Pod を削除します。これにより、更新プロセス中のサービス可用性が確保されます。

    • maxUnavailable:ローリングアップデート中に利用できなくなる Pod レプリカの最大数です。デフォルト値は 25% です。絶対数を指定することもできます。

    • maxSurge:ローリングアップデート中に、希望するレプリカ数を超えて作成できる Pod の最大数です。値が大きいほど更新は速くなりますが、より多くのリソースを消費します。デフォルト値は 25% です。絶対数を指定することもできます。

ゼロダウンタイムローリングデプロイの検証

  1. クラスターの kubeconfig ファイルを取得し、kubectl を使用してクラスターに接続します

  2. サンプルアプリケーションのアクセス URL を取得します。

    export NGINX_ENDPOINT=$(kubectl get service nginx-demo-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}{":"}{.spec.ports[0].port}')
    echo $NGINX_ENDPOINT
  3. 負荷テストツール hey をインストールします。200 の同時接続と合計 50,000 のリクエストで負荷テストを実行します。この例のリソース構成では、単一のレプリカでテストが約 1 分で完了するはずです。

    hey -c 200 -n 50000  -disable-keepalive http://$NGINX_ENDPOINT

    テストの実行中に、新しいターミナルウィンドウを開き、すぐに Deployment を再起動します。

    kubectl rollout restart deployment nginx-deployment-demo
  4. 次の表に、期待される出力を示します。

    デプロイシナリオ

    期待される出力

    ゼロダウンタイム構成なし

    ゼロダウンタイム構成なしのサンプル YAML

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment-demo
    spec:
      replicas: 1                 # 本番環境の高可用性のために 2 以上に設定します。デモンストレーション目的で 1 に設定します。
      selector:
        matchLabels:
          app: nginx-demo
      template:
        metadata:
          labels:
            app: nginx-demo 
        spec:
          containers:
          - name: nginx
            image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
            ports:
            - containerPort: 80
            resources:
              requests:
                cpu: 500m
                memory: 1Gi
              limits:
                cpu: 500m
    ---           
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-demo-service
    spec:
      type: LoadBalancer
      selector:
        app: nginx-demo 
      ports:
        - protocol: TCP
          port: 80

    トラフィック損失が観測されます。

    Status code distribution:
      [200]	49644 responses
    
    Error distribution:
      [320]	Get "http://114.215.XXX.XXX": dial tcp 114.215.XXX.XXX:80: connect: connection refused
      [18]	Get "http://114.215.XXX.XXX": dial tcp 114.215.XXX.XXX:80: connect: no route to host
      [18]	Get "http://114.215.XXX.XXX": dial tcp 114.215.XXX.XXX:80: connect: operation timed out

    ゼロダウンタイム構成あり

    トラフィック損失ゼロが達成されます。

    Status code distribution:
      [200]	50000 responses

よくある質問

Pod のステータス:Running だが Not Ready

原因:この問題は通常、起動プローブまたは readiness プローブの失敗が原因で発生します。

解決策

  • Readiness プローブの設定:対象の ワークロード編集 ページで、ヘルスチェックのリクエストパス (例:/healthz) とポートがアプリケーションが提供するものと一致していることを確認します。アプリケーションの起動時間が長い場合は、異常のしきい値 を増やして、早すぎる失敗を回避します。

    一時的に レディチェック を無効にし、Pod のターミナルまたはそのホストにログインし、curl などのコマンドを使用して、ヘルスチェックメソッドが正しく応答することを確認できます。
  • アプリケーションの問題のトラブルシューティング:Pod の イベントログ を確認して問題を調査します。最後のコンテナーが終了した時のログを表示する を選択します。

関連ドキュメント