preStopフックを使用すると、Application Load Balancer (ALB) Ingressに関連付けられたバックエンドポッドをシームレスに終了し、ポッドが完全に削除された後にのみシャットダウンされるようにすることができます。 preStopフックを使用すると、トラフィックの切り替えをシームレスにし、サービスのローリング更新中にサービスの中断を防ぐことができます。
前提条件
ACKマネージドクラスターまたはACK専用クラスターが作成され、クラスターのKubernetesバージョンが1.18以降であること。 詳細については、「ACK管理クラスターの作成」または「ACK専用クラスターの作成」をご参照ください。 クラスターを更新する場合は、「ACKクラスターの手動更新」をご参照ください。
ALB Ingressコントローラーがクラスターにインストールされています。 詳細については、「ALB Ingressコントローラーの管理」をご参照ください。
説明ALB Ingressを使用してACK専用クラスターにデプロイされたサービスにアクセスするには、まずALB Ingressコントローラーが必要とする権限をクラスターに付与する必要があります。 詳細については、「ACK専用クラスターにALB Ingressコントローラーへのアクセスを許可する」をご参照ください。
制御ポリシー機能の動作
ポッドのライフサイクル
ポッドには、次のタイプのコンテナが含まれます。
Init container: Init containersはメインコンテナの前に実行され、特定の初期化操作が完了します。
メインコンテナ: メインコンテナはアプリケーションのプロセスを実行します。
次の図は、ポッドのライフサイクルを示しています。
init containersの実行: Init containersはメインコンテナの前に実行され、特定の初期化操作が完了します。
メインコンテナの実行:
メインコンテナは、コンテナの起動後にpostStartフック関数を呼び出します。
システムは、メインコンテナに対してライブネスチェック (liveness probe) とレディネスチェック (readiness probe) を実行します。
メインコンテナは、コンテナが終了する前にpreStopフック関数を呼び出します。
ポッド終了手順とトラフィックルーティング規則の更新手順
ポッドを削除すると、システムはポッドの終了手順とトラフィックルーティングルールの更新手順を同時に実行します。 次のリストは、手順を説明しています。
ポッド終了手順
kube-apiserverは削除要求を受け取り、ポッドを
終了としてマークします。preStopフックがポッドに設定されている場合、システムはpreStopフックを実行します。
クラスタはコンテナにSIGTERM信号を送信します。
システムは、コンテナが終了するまで、またはポッドの正常なシャットダウンプロセスがタイムアウトするまで待機します。
説明ポッドのデフォルトの猶予期間 (
terminationGracePeriodSeconds) は30秒です。ポッドが猶予期間内に終了しない場合、システムはコンテナにSIGKILL信号を送信します。
ポッドが削除されました。
トラフィックルーティング規則の更新手順
kube-apiserverは削除要求を受け取り、ポッドを
終了としてマークします。エンドポイントコントローラは、エンドポイントからポッドのIPアドレスを削除します。
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フックを設定する
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次のコマンドを実行して、テスト展開とテストサービスを展開します。
kubectl apply -f tea-service.yamltea-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次のコマンドを実行してIngressを作成します。
kubectl apply -f tea-ingress.yaml次のコマンドを実行して、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フックが有効かどうかをテストする
テストスクリプトを実行します。
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次のコマンドを実行して、
test.shスクリプトを実行します。bash test.sh
次のコマンドを実行して、アプリケーションのローリングアップデートを開始し、アプリケーションを再デプロイします。
kubectl rollout restart deploy tea更新を確認します。
ローリング更新前のレプリケートされたポッドの数は3です。

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

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

すべての古いポッドがpreStopフック機能の実行を完了するか、ポッドの
グレースフルシャットダウンがタイムアウトすると、kubectlは古いポッドに信号を送信してポッドを終了します。 ポッドが終了すると、ローリング更新が完了します。
テストスクリプトの実行結果を表示します。 リクエストごとに200が返された場合、ローリング更新中にサービスの中断は発生しません。
次のコマンドを実行して、テストスクリプトの実行結果を表示します。
cat log.txt期待される出力:

関連ドキュメント
ALB Ingressを使用して、リクエストの転送、HTTPリクエストのHTTPSへのリダイレクト、カナリアリリースの実装を行うことができます。 詳細については、「高度なALB Ingress設定」をご参照ください。
準備完了ゲートを設定して、ポッドが起動される前に準備完了を確認するには、「準備完了ゲートを使用して、ローリングアップデート中にALB Ingressに関連付けられているポッドをシームレスに起動する」をご参照ください。
ALB Ingressの使用時にエラーが発生した場合は、ALB Ingress FAQおよびALB Ingressコントローラーのトラブルシューティングを参照してください。