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

Container Service for Kubernetes:preStop フックを使用して、ALB Ingress のローリングアップデート中の 502/504 エラーを防ぐ

最終更新日:Jun 17, 2026

preStop でスリープを実行することで SIGTERM を遅延させ、ALB Ingress controller がシャットダウン前に Pod の登録解除を完了できるようにします。

前提条件

始める前に、以下を確認してください。

ACK 専用クラスターで ALB Ingress を使用するには、まず ALB Ingress controller 用にクラスターを認可する必要があります。

仕組み

Pod のライフサイクル

Pod には 2 種類のコンテナが含まれます。

  • Init コンテナ:初期化のために、メインコンテナの前に実行されます。

  • メインコンテナ:アプリケーションを実行します。起動後に postStart フックが実行され、コンテナの存続期間中は liveness チェックと readiness チェックが実行され、終了前に preStop フックが実行されます。

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

image

エラーが発生する理由:2 つの処理が並行して実行される

Pod を削除すると、Pod の終了処理とトラフィックルーティングルールの更新という 2 つの処理が並行して実行されるため、502/504 エラーが発生します。

Pod の終了処理

  1. kube-apiserver が Pod を Terminating としてマークします。

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

  3. クラスターがコンテナに SIGTERM シグナルを送信します。

  4. システムは、コンテナが停止するか、猶予期間 (terminationGracePeriodSeconds、デフォルト:30 秒) が終了するまで待機します。

  5. 猶予期間後も Pod が実行中の場合、kubelet はさらに 2 秒待機してから SIGKILL シグナルを送信します。

  6. Pod が削除されます。

トラフィックルーティングルールの更新処理

  1. kube-apiserver が Pod を Terminating としてマークします。

  2. endpoint controller が、エンドポイントから Pod の IP アドレスを削除します。

  3. ALB Ingress controller がバックエンドサーバーをリコンサイルし、バックエンドサーバーグループから Service エンドポイントを削除します。

両方の処理が並行して実行されるため、ALB Ingress controller が Pod のシャットダウン前にリコンサイルを完了できずに、終了処理中の Pod にトラフィックがルーティングされてしまう可能性があります。

preStop フックがエラーを防ぐ仕組み

preStop フックを使用しない場合、ローリングアップデート中に次のようなエラーが発生する可能性があります。

ステータスコード 原因
504 Pod が非べき等リクエストを処理中に終了しました。
502 Pod が SIGTERM を受信した後にシャットダウンしましたが、ALB Ingress controller がまだバックエンドサーバーグループから Pod を削除していませんでした。

preStop フックは、kube-apiserver が Pod を Terminating としてマークした時点からスリープによる遅延を追加し、ALB Ingress controller が SIGTERM を受信する前に Pod の登録解除を完了するための時間を確保します。

時間配分

preStop の sleep とコンテナのシャットダウンは、同じ猶予期間 (terminationGracePeriodSeconds) を共有します。sleep 10 で、プログラムのシャットダウンに 5 秒かかる場合、terminationGracePeriodSeconds は、安全マージンを加えて少なくとも 15 に設定します。このトピックでは、sleep 10terminationGracePeriodSeconds: 45 を使用します。

preStop の時間とプログラムのシャットダウン時間の合計が terminationGracePeriodSeconds を超えると、グレースフルシャットダウンはタイムアウトし、kubelet は 2 秒の待機後に SIGKILL を送信します。両方の時間をカバーできるように terminationGracePeriodSeconds を長く設定してください。

ステップ 1:preStop フックを使用してアプリケーションをデプロイする

  1. 以下の内容で tea-service.yaml を作成します。lifecycle.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:
              preStop:          # ALB Ingress controller がバックエンドサーバーグループから
                exec:           # Pod の登録解除を完了できるように、SIGTERM を 10 秒遅延させます。
                  command:
                  - /bin/sh
                  - -c
                  - "sleep 10"
          terminationGracePeriodSeconds: 45   # preStop の実行時間 + プログラムのシャットダウン時間を超える必要があります。
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: tea-svc
    spec:
      ports:
      - port: 80
        targetPort: 80
        protocol: TCP
      selector:
        app: tea
      type: NodePort
  2. Deployment と Service をデプロイします。

    kubectl apply -f tea-service.yaml
  3. 次の内容で tea-ingress.yaml を作成します。

    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. Ingress の ALB アドレスを取得します。

    kubectl get ingress

    出力例:

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

    次のステップで使用する ADDRESS の値をメモしておいてください。

ステップ 2:preStop フックがサービス中断を防ぐことを検証する

  1. 以下の内容で test.sh を作成します。このスクリプトは、1 秒に 1 回リクエストを送信し、各 HTTP ステータスコードをログに記録します。

    #!/bin/bash
    HOST="demo.ingress.top"
    DNS="alb-110zvs5nhsvfv*****.cn-chengdu.alb.aliyuncs.com"  # 実際の ADDRESS の値に置き換えてください。
    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. スクリプトを実行します。

    bash test.sh
  3. ローリング再起動をトリガーします。

    kubectl rollout restart deploy tea
  4. ロールアウトの進行状況を監視します。次のスクリーンショットは、更新の各フェーズで予想される Pod の状態を示しています。

    image

    image

    image

    image

  5. テストログを確認します。すべてのリクエストが 200 を返すことで、サービスが中断されなかったことが確認できます。

    cat log.txt

    出力例:

    image

次のステップ