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

Container Service for Kubernetes:preStopフックを使用して、ALB Ingressのバックエンドポッドのローリングアップデート中にシームレスなポッド終了を有効にする

最終更新日:Jan 26, 2025

preStopフックを使用すると、Application Load Balancer (ALB) Ingressに関連付けられたバックエンドポッドをシームレスに終了し、ポッドが完全に削除された後にのみシャットダウンされるようにすることができます。 preStopフックを使用すると、トラフィックの切り替えをシームレスにし、サービスのローリング更新中にサービスの中断を防ぐことができます。

前提条件

制御ポリシー機能の動作

ポッドのライフサイクル

ポッドには、次のタイプのコンテナが含まれます。

  • Init container: Init containersはメインコンテナの前に実行され、特定の初期化操作が完了します。

  • メインコンテナ: メインコンテナはアプリケーションのプロセスを実行します。

次の図は、ポッドのライフサイクルを示しています。

  1. init containersの実行: Init containersはメインコンテナの前に実行され、特定の初期化操作が完了します。

  2. メインコンテナの実行:

    1. メインコンテナは、コンテナの起動後にpostStartフック関数を呼び出します。

    2. システムは、メインコンテナに対してライブネスチェック (liveness probe) とレディネスチェック (readiness probe) を実行します。

    3. メインコンテナは、コンテナが終了する前にpreStopフック関数を呼び出します。

ポッド終了手順とトラフィックルーティング規則の更新手順

ポッドを削除すると、システムはポッドの終了手順とトラフィックルーティングルールの更新手順を同時に実行します。 次のリストは、手順を説明しています。

ポッド終了手順

  1. kube-apiserverは削除要求を受け取り、ポッドを終了としてマークします。

  2. preStopフックがポッドに設定されている場合、システムはpreStopフックを実行します。

  3. クラスタはコンテナにSIGTERM信号を送信します。

  4. システムは、コンテナが終了するまで、またはポッドの正常なシャットダウンプロセスがタイムアウトするまで待機します。

    説明

    ポッドのデフォルトの猶予期間 (terminationGracePeriodSeconds) は30秒です。

  5. ポッドが猶予期間内に終了しない場合、システムはコンテナにSIGKILL信号を送信します。

  6. ポッドが削除されました。

トラフィックルーティング規則の更新手順

  1. kube-apiserverは削除要求を受け取り、ポッドを終了としてマークします。

  2. エンドポイントコントローラは、エンドポイントからポッドのIPアドレスを削除します。

  3. ALB Ingressコントローラーはバックエンドサーバーを調整し、バックエンドサーバーグループからサービスエンドポイントを削除します。 これにより、トラフィックは削除されたポッドにルーティングされなくなります。

preStopフックを使用してポッドをシームレスに終了

ローリング更新中に、古いポッドがシームレスに終了しない場合、サービスにリクエストを送信すると、次のステータスコードが返される場合があります。 これは、サービスの可用性を損なう。

ステータスコード

原因

504

古いポッドは、ポッドが削除されたときに、べき以外の要求を処理していました。

502

システムからSIGTERM信号を受信すると、古いポッドが削除されます。 ただし、古いポッドが削除されると、ALB Ingressコントローラによって調整が完了しません。 その結果、リクエストが処理されても、ポッドはバックエンドサーバーグループに存在します。

上記の問題を防ぐには、次の操作を実行します。

preStopフックをデプロイに追加して、kube-apiserverが削除リクエストを受信した後に開始するスリープ期間を指定します。 スリープ期間は、ポッドがSIGTERM信号を受信する前に、コンテナがトラフィックルーティング規則を更新し、ALB Ingressコントローラーがバックエンドサーバーを調整し、バックエンドサーバーグループから古いポッドを削除するのに十分な期間を保証します。 このようにして、ポッドをシームレスに終了させ、ローリング更新および再起動中のサービスの中断を防ぐことができます。

ポッドのデフォルトの猶予期間 (terminationGracePeriodSeconds) は30秒です。 これは、ポッドがSIGTERM信号を受信してから30秒間継続して実行できることを示します。 プログラムのシャットダウン時間と、停止前のフックで定義された操作を完了するのに必要な時間の合計が30秒を超えると、ポッドの正常なシャットダウンがタイムアウトします。 猶予期間が終了すると、kubeletは2秒間待機し、SIGKILL信号をポッドに送信してポッドを強制終了します。

説明

この場合、猶予期間 (terminationGracePeriodSeconds) を長くして、前の操作を完了するのに十分な期間を確保することを推奨します。

ステップ1: ポッドのpreStopフックを設定する

  1. tea-service.yamlという名前のファイルを作成し、次の内容をファイルにコピーします。 ファイルには、シームレスなポッド終了を保証するために追加されるpreStopフックが含まれています。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: tea
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: tea
      template:
        metadata:
          labels:
            app: tea
        spec:
          containers:
          - name: tea
            image: registry.cn-hangzhou.aliyuncs.com/acs-sample/nginxdemos:latest
            ports:
            - containerPort: 80
            lifecycle:  # Specify a preStop hook function that requires kube-apiserver to wait 10 seconds before sending the SIGTERM signal to the pod. 
              preStop:  # The preStop hook configurations. 
                exec:  # Perform the operations defined by the preStop hook by running commands. 
                  command:  # The command to run. 
                  - /bin/sh
                  - -c
                  - "sleep 10"  # Sleep for 10 seconds. 
          terminationGracePeriodSeconds: 45  # Specify the grace period of the pod. 
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: tea-svc
    spec:
      ports:
      - port: 80
        targetPort: 80
        protocol: TCP
      selector:
        app: tea
      type: NodePort
  2. 次のコマンドを実行して、テスト展開とテストサービスを展開します。

    kubectl apply -f tea-service.yaml
  3. tea-ingress.yamlという名前のファイルを作成し、次の内容をファイルにコピーします。 ファイルはIngressを作成するために使用されます。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: tea-ingress
    spec:
      ingressClassName: alb
      rules:
       - host: demo.ingress.top
         http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: tea-svc
                port:
                  number: 80
  4. 次のコマンドを実行してIngressを作成します。

    kubectl apply -f tea-ingress.yaml
  5. 次のコマンドを実行して、ALB IngressのADDRESSパラメーターを照会します。

    kubectl get ingress

    期待される出力:

    NAME                    CLASS   HOSTS                     ADDRESS                                              PORTS   AGE
    tea-ingress             alb     demo.ingress.top          alb-110zvs5nhsvfv*****.cn-chengdu.alb.aliyuncs.com   80      7m5s

ステップ2: preStopフックが有効かどうかをテストする

  1. テストスクリプトを実行します。

    1. test.shという名前のスクリプトを作成し、次の内容をスクリプトにコピーします。 このスクリプトは、1秒単位でNGINXサービスに要求を送信し、返されたステータスコードを記録することにより、サービスの可用性をテストするために使用されます。

      #!/bin/bash
      HOST="demo.ingress.top"
      DNS="alb-110zvs5nhsvfv*****.cn-chengdu.alb.aliyuncs.com"   # Set the value to the value of the ADDRESS parameter of the ALB Ingress. 
      printf "Response Code|| TIME \n" >> log.txt
      
      while true; do
        RESPONSE=$(curl -H Host:$HOST  -s -o /dev/null -w "%{http_code}" -m 1  http://$DNS/)
        TIMESTAMP=$(date +%Y-%m-%d_%H:%M:%S)
        echo "$TIMESTAMP - $RESPONSE" >> log.txt
        sleep 1
      done
    2. 次のコマンドを実行して、test.shスクリプトを実行します。

      bash test.sh
  2. 次のコマンドを実行して、アプリケーションのローリングアップデートを開始し、アプリケーションを再デプロイします。

    kubectl rollout restart deploy tea 
  3. 更新を確認します。

    1. ローリング更新前のレプリケートされたポッドの数は3です。

      image

    2. 再デプロイ中、新しいポッドがリクエストを処理する準備ができていない場合でも、2つの古いポッドが実行されます。

      image

    3. 新しいポッドがリクエストを処理し、ALBインスタンスのバックエンドサーバーグループに追加されると、古いポッドは終了します。

      image

    4. すべての古いポッドがpreStopフック機能の実行を完了するか、ポッドのグレースフルシャットダウンがタイムアウトすると、kubectlは古いポッドに信号を送信してポッドを終了します。 ポッドが終了すると、ローリング更新が完了します。

      image

  4. テストスクリプトの実行結果を表示します。 リクエストごとに200が返された場合、ローリング更新中にサービスの中断は発生しません。

    次のコマンドを実行して、テストスクリプトの実行結果を表示します。

    cat log.txt

    期待される出力:

    image

関連ドキュメント