一覧CL-11-3 · Kubernetesの状態管理

ヘルスチェックとローリングアップデート

検査失敗後のReady、再起動回数、新旧Pod数から、更新が止まる理由を説明します。

説明

readinessは要求を受けられる状態か、livenessはコンテナを再起動すべき状態かを判定します。同じ検査に見えても、失敗した後の処理は異なります。Deploymentの更新では、ReadyなPod数も旧版を減らす条件になります。

1個のPodで、準備完了を表すファイルと生存を表すファイルを別に用意します。それぞれを消して状態と再起動回数を確認した後、Readyにならない版へ更新して旧版が残ることを調べます。

検査失敗後のReady、再起動回数、新旧Pod数から、更新が止まる理由を説明します。

11個のPodと検査を用意する

readinessは/tmp/ready、livenessは/tmp/healthyの存在を検査します。起動時に両方を作る定義です。

python3 -c1個のPodと二つの検査設定を用意する 'import json; p="deployment.json"; d=json.load(open(p)); d["spec"]["replicas"]=1; open(p,"w").write(json.dumps(d)); c=d["spec"]["template"]["spec"]["containers"][0]; print(json.dumps({k:c[k] for k in ["readinessProbe","livenessProbe"]},sort_keys=True))' kubectl apply -f deployment.json検査付きのDeploymentを作る python3 observe.py wait 1 1 0初期状態を確認する

1個がReadyになりました。readinessは1回の失敗、livenessは2回続けて失敗した場合にそれぞれの処理へ進む設定です。

2readinessだけを失敗させる

/tmp/readyを消します。プロセスと/tmp/healthyはそのままです。

kubectl exec deployment/web -- rm /tmp/ready準備完了の条件だけを失わせる python3 observe.py wait 1 0 0Readyと再起動回数を読む

Podは1個のまま、Readyは0、再起動も0です。readinessの失敗だけではコンテナは再起動しません。

3準備完了へ戻す

同じコンテナ内にファイルを戻します。

kubectl exec deployment/web -- touch /tmp/ready準備完了の条件を戻す python3 observe.py wait 1 1 0再起動なしで復帰したことを読む

再起動せずReadyへ戻りました。起動し直すことと、要求を受けられる状態になることは別です。

4livenessを失敗させる

/tmp/healthyを消し、再起動を待ちます。起動コマンドが両方のファイルを作り直します。

kubectl exec deployment/web -- rm /tmp/healthy生存検査を失敗させる python3 observe.py wait 1 1 1再起動1回とReadyへの復帰を待つ

再起動回数が1になり、Readyへ戻りました。Podを別に作ったのではなく、同じPod内のコンテナが再起動しています。

5更新時の台数条件

maxSurge=1は必要数を超えて追加できる個数、maxUnavailable=0は更新中に許す利用不能数です。

python3 observe.py budget更新設定と必要数を表示する

必要数1に対し、新版を追加して最大2個にできます。利用可能数を1未満に減らす更新は許していません。

6Readyにならない版へ更新する

VERSION=badでは起動時に/tmp/readyを作りません。Podテンプレートを変更するため、新しいReplicaSetが作られます。

kubectl set env deployment/web VERSION=bad準備完了にならない版へ更新する python3 observe.py wait 2 1 1旧版と新版の合計数・Readyを確認する

Podは2個でもReadyは1個です。新版がReadyにならないため、旧版が残っています。Pod数だけを見て更新成功と判断できません。

7準備完了になる版へ直す

VERSION=v2へ変更すると、新しいPodは/tmp/readyを作ります。

kubectl set env deployment/web VERSION=v2起動条件を修正した版へ更新する python3 observe.py wait 1 1 0更新後の必要数とReadyを確認する

更新後はPod1個・Ready1個へ戻ります。新しいPodの再起動回数は0で、旧Podの再起動回数を引き継ぐ値ではありません。

8最終的に動く版

Deploymentの宣言と、実際のコンテナ内の環境変数を照合します。

kubectl get deployment web宣言の版を読む -o jsonpath='{.spec.template.spec.containers[0].env[0].value}{"\n"}' kubectl exec deployment/web -- printenv VERSION実行中の版を読む

両方v2です。宣言だけでなく、実際に動くコンテナまで更新が反映されています。

まとめ

readiness失敗はReadyを下げ、liveness失敗は再起動につながります。

更新中は総Pod数とReady数を別々に確認します。

新版がReadyにならない場合、更新条件により旧版が残ります。

操作履歴と解説を振り返れます。

Kubernetes 1.37.0 / kind 0.33.0 / Linux arm64

1
python3 -c 'import json; p="deployment.json"; d=json.load(open(p)); d["spec"]["replicas"]=1; open(p,"w").write(json.dumps(d)); c=d["spec"]["template"]["spec"]["containers"][0]; print(json.dumps({k:c[k] for k in ["readinessProbe","livenessProbe"]},sort_keys=True))' kubectl apply -f deployment.json python3 observe.py wait 1 1 0
{"livenessProbe": {"exec": {"command": ["test", "-f", "/tmp/healthy"]}, "failureThreshold": 2, "periodSeconds": 1}, "readinessProbe": {"exec": {"command": ["test", "-f", "/tmp/ready"]}, "failureThreshold": 1, "periodSeconds": 1}}
deployment.apps/web created
pods=1 ready=1 restarts=0
2
kubectl exec deployment/web -- rm /tmp/ready python3 observe.py wait 1 0 0
pods=1 ready=0 restarts=0
3
kubectl exec deployment/web -- touch /tmp/ready python3 observe.py wait 1 1 0
pods=1 ready=1 restarts=0
4
kubectl exec deployment/web -- rm /tmp/healthy python3 observe.py wait 1 1 1
pods=1 ready=1 restarts=1
5
python3 observe.py budget
{"maxSurge": 1, "maxUnavailable": 0}
desired=1
6
kubectl set env deployment/web VERSION=bad python3 observe.py wait 2 1 1
deployment.apps/web env updated
pods=2 ready=1 restarts=1
7
kubectl set env deployment/web VERSION=v2 python3 observe.py wait 1 1 0
deployment.apps/web env updated
pods=1 ready=1 restarts=0
8
kubectl get deployment web -o jsonpath='{.spec.template.spec.containers[0].env[0].value}{"\n"}' kubectl exec deployment/web -- printenv VERSION
v2
v2

演習完了