kubectl rollout statusはいつ完了するか
前提
kubectl rollout restart deployment
を実行した際に、.spec.strategy.type==RollingUpdate
の場合以下のような挙動になります。
- 新規podの起動開始
- 新規podの起動完了
- 旧podの停止開始
- 旧podの停止完了
その進捗を確認できる kubectl rollout status
というコマンドがあります。
しかし具体的にどのタイミングで完了になるかが、公式ドキュメントからだと確認できませんでした。
By default 'rollout status' will watch the status of the latest rollout until it's done. If you don't want to wait for the rollout to finish then you can use --watch=false. Note that if a new rollout starts in-between, then 'rollout status' will continue watching the latest revision. If you want to pin to a specific revision and abort if it is rolled over by another revision, use --revision=N where N is the revision you need to watch for.
私が運用しているプロダクトは一部 shoryuken を使用しているコンポーネントがあります。
shoryukenは設定やjobの処理状況により、TERM受信からプロセス停止まで時間がかかるケースが発生します。
CI/CDや各種パイプラインを構築する際に、status checkが旧podの停止完了まで待つかどうかがポイントになりました。
そのため実際に動作確認して検証しました。
動作環境
% kubectl version
Client Version: v1.30.5
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.30.2
% sw_vers
ProductName: macOS
ProductVersion: 15.1.1
BuildVersion: 24B91
動作確認
実際に動かして kubectl rollout status
の振る舞いを確認します。
準備
適当なdeploymentを用意します。
挙動が確認しやすいように、コンテナの起動完了および停止処理にそれぞれ10秒待つようにします。
deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: graceful-shutdown-test
spec:
replicas: 1
selector:
matchLabels:
app: graceful-shutdown-test
template:
metadata:
labels:
app: graceful-shutdown-test
spec:
terminationGracePeriodSeconds: 60
containers:
- name: main
image: busybox
command: ["/bin/sh"]
args:
- -c
- |
echo "Starting container, waiting 10 seconds before becoming ready..."
sleep 10
echo "Container is now ready"
trap 'echo "Received SIGTERM, sleeping for 10 seconds..."; sleep 10; echo "Exiting..."; exit 0' TERM
while true; do sleep 5; done
readinessProbe:
exec:
command:
- sh
- -c
- "[ -f /tmp/ready ]"
initialDelaySeconds: 5
periodSeconds: 5
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "sleep 10 && touch /tmp/ready"]
kubectl apply -f deployment.yml
でapplyします。
検証
watchコマンドで実際のpodとkubectl rollout status
の結果をチェックしながら作業します。
watch -t "kubectl get po && kubectl rollout status deployment graceful-shutdown-test -w=false"
rollout実行前
NAME READY STATUS RESTARTS AGE
graceful-shutdown-test-59ff466875-6vss2 1/1 Running 0 47m
deployment "graceful-shutdown-test" successfully rolled out
kubectl rollout restart deployment graceful-shutdown-test
で rollout実施します。
rollout開始で新規のpodが ContainerCreating になります。
kubectl rollout status
はまだ Waiting... となっています。
NAME READY STATUS RESTARTS AGE
graceful-shutdown-test-59ff466875-6vss2 1/1 Running 0 49m
graceful-shutdown-test-85797fc66d-w88nh 0/1 ContainerCreating 0 4s
Waiting for deployment "graceful-shutdown-test" rollout to finish: 1 old replicas are pending termination...
新規のpod (graceful-shutdown-test-85797fc66d-w88nh
) が起動完了するとほぼ同時に、旧podが Terminating 状態になります。
この時点で kubectl rollout status
は完了状態に切り替わりました。
NAME READY STATUS RESTARTS AGE
graceful-shutdown-test-59ff466875-6vss2 1/1 Terminating 0 49m
graceful-shutdown-test-85797fc66d-w88nh 1/1 Running 0 19s
deployment "graceful-shutdown-test" successfully rolled out
そこから数秒後に旧podの停止も完了しました。
kubectl rollout status
の結果は変わらず完了状態です
NAME READY STATUS RESTARTS AGE
graceful-shutdown-test-85797fc66d-w88nh 1/1 Running 0 34s
deployment "graceful-shutdown-test" successfully rolled out
これらの結果から kubectl rollout status
は旧podの停止完了まで見届けないことがわかりました。
ちなみに
同じ内容のissueがありました。
そこでも「新podの起動のみ確認し、旧podの状態には依存しない」と回答されています。
旧podの停止完了まで確認する必要があれば、 kubectl wait
を使うかシェルで確認してねとありました。
kubectl wait --for=delete pod --selector app=graceful-shutdown-test --timeout=180s
のような形で 停止完了 (=コンテナ削除) イベントをpollingできそうですが少し考慮事項が多そうです。
Discussion