preStop でスリープを実行することで SIGTERM を遅延させ、ALB Ingress controller がシャットダウン前に Pod の登録解除を完了できるようにします。
前提条件
始める前に、以下を確認してください。
-
Kubernetes 1.18 以降を実行している ACK マネージドクラスターまたは ACK 専用クラスター (提供終了) があること。アップグレードについては、「ACK クラスターの手動アップグレード」をご参照ください。
-
クラスターに ALB Ingress controller がインストールされていること。
ACK 専用クラスターで ALB Ingress を使用するには、まず ALB Ingress controller 用にクラスターを認可する必要があります。
仕組み
Pod のライフサイクル
Pod には 2 種類のコンテナが含まれます。
-
Init コンテナ:初期化のために、メインコンテナの前に実行されます。
-
メインコンテナ:アプリケーションを実行します。起動後に postStart フックが実行され、コンテナの存続期間中は liveness チェックと readiness チェックが実行され、終了前に preStop フックが実行されます。
次の図は、Pod のライフサイクルを示しています。
エラーが発生する理由:2 つの処理が並行して実行される
Pod を削除すると、Pod の終了処理とトラフィックルーティングルールの更新という 2 つの処理が並行して実行されるため、502/504 エラーが発生します。
Pod の終了処理
-
kube-apiserver が Pod を
Terminatingとしてマークします。 -
設定されている場合、システムは preStop フックを実行します。
-
クラスターがコンテナに SIGTERM シグナルを送信します。
-
システムは、コンテナが停止するか、猶予期間 (
terminationGracePeriodSeconds、デフォルト:30 秒) が終了するまで待機します。 -
猶予期間後も Pod が実行中の場合、kubelet はさらに 2 秒待機してから SIGKILL シグナルを送信します。
-
Pod が削除されます。
トラフィックルーティングルールの更新処理
-
kube-apiserver が Pod を
Terminatingとしてマークします。 -
endpoint controller が、エンドポイントから Pod の IP アドレスを削除します。
-
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 10 と terminationGracePeriodSeconds: 45 を使用します。
preStopの時間とプログラムのシャットダウン時間の合計がterminationGracePeriodSecondsを超えると、グレースフルシャットダウンはタイムアウトし、kubelet は 2 秒の待機後に SIGKILL を送信します。両方の時間をカバーできるようにterminationGracePeriodSecondsを長く設定してください。
ステップ 1:preStop フックを使用してアプリケーションをデプロイする
-
以下の内容で
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 -
Deployment と Service をデプロイします。
kubectl apply -f tea-service.yaml -
次の内容で
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 -
Ingress を作成します。
kubectl apply -f tea-ingress.yaml -
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 フックがサービス中断を防ぐことを検証する
-
以下の内容で
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 -
スクリプトを実行します。
bash test.sh -
ローリング再起動をトリガーします。
kubectl rollout restart deploy tea -
ロールアウトの進行状況を監視します。次のスクリーンショットは、更新の各フェーズで予想される Pod の状態を示しています。




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

次のステップ
-
HTTP から HTTPS へのリダイレクトやカナリアリリースなどの高度なルーティングについては、「ALB Ingress の高度な設定」をご参照ください。
-
ローリングアップデート中に、トラフィックを受信する前に Pod が readiness チェックに合格するようにするには、「Readiness Gate を使用して、ALB Ingress に関連付けられた Pod のローリングアップデート中にシームレスな起動を実現する」をご参照ください。
-
問題が発生した場合は、「ALB Ingress のよくある質問」および「ALB Ingress controller のトラブルシューティング」をご参照ください。