はじめに
KubernetesではPodの正常性判断のため、以下の3種類のヘルスチェック機構があります。
ヘルスチェック機構 | 概要 | 失敗時(チェックに引っかかった時)の動作 |
---|---|---|
Liveness Probe | Podが正常に動作しているかの確認 | Podを再起動する |
Readiness Probe | Podがトラフィックの受け入れをできる状態になっているかの確認 | LoadBalancerなどのサービスの転送先から削除される(トラフィックを流さない) |
Startup Probe | コンテナアプリケーションがいつ起動したかの確認 | Liveness ProbeとReadiness Probeを無効にする |
今回はそのうち、Liveness Probeの動作を確認したいと思います。
ヘルスチェック方式
Liveness Probe/Readiness Probeともに以下の3種類のチェック方式が利用できます。
方式 | 失敗となる条件 |
---|---|
exec | 指定したコマンドを実行し、終了コードが0でない場合 |
httpGet | HTTP GETリクエストを実行し、Status Codeが200-399ではない場合 |
tcpSocket | TCPセッションが確立できない場合 |
ヘルスチェック間隔
Liveness Probe/Readiness Probeともにヘルスチェックの間隔には、以下5種類のパラメータがあります。
パラメータ | 設定内容 | デフォルト値 |
---|---|---|
initialDelaySeconds | 初回ヘルスチェックまでの遅延時間(秒) | 0 |
periodSeconds | Probeが実行される間隔(秒) | 10 |
timeoutSeconds | タイムアウトまでの時間(秒) | 1 |
successThreshold | 成功と判断する最小連続成功数(回数) | 1 |
failureThreshold | 失敗と判断する試行回数(回数) | 3 |
動作確認
それでは実際にやってみましょう。
exec
まずはexecからです。
以下のマニフェストのPodで動作を確認します。
ヘルスチェックは「spec.containers.LivenessProbe」以下にヘルスチェックの方式と間隔を指定します。
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness-exec
image: k8s.gcr.io/busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 1
この例では、/tmp/healthyファイルがあるかどうかをチェックしています。
Podデプロイ時に/tmp/healthyファイルを作成しますが、30秒後に削除します。
ヘルスチェックを5秒待ってから開始し、5秒間隔で、1回失敗したらPodを再起動する動作になります。
このマニフェストをapplyします。
$ kubectl apply -f liveness-exec.yaml
pod/liveness-exec created
Podの状態を監視します。
$ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
liveness-exec 0/1 Pending 0 0s
liveness-exec 0/1 Pending 0 0s
liveness-exec 0/1 ContainerCreating 0 0s
liveness-exec 0/1 ContainerCreating 0 1s
liveness-exec 1/1 Running 0 3s
liveness-exec 1/1 Running 1 67s
liveness-exec 1/1 Running 2 2m11s
liveness-exec 1/1 Running 3 3m16s
liveness-exec 1/1 Running 4 4m21s
liveness-exec 1/1 Running 5 5m26s
liveness-exec 0/1 CrashLoopBackOff 5 6m30s
liveness-exec 1/1 Running 6 7m55s
liveness-exec 0/1 CrashLoopBackOff 6 9m1s
liveness-exec 1/1 Running 7 11m
liveness-exec 0/1 CrashLoopBackOff 7 12m
liveness-exec 1/1 Running 8 18m
RESTARTSの数字が上がっていくのがわかりますね。
kubectl describe podで詳細を確認できます。
$ kubectl describe pod liveness-exec
Name: liveness-exec
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 18m default-scheduler Successfully assigned default/liveness-exec to k8s-worker01
Normal Pulled 15m (x4 over 18m) kubelet, k8s-worker01 Successfully pulled image "k8s.gcr.io/busybox"
Normal Created 15m (x4 over 18m) kubelet, k8s-worker01 Created container liveness-exec
Normal Started 15m (x4 over 18m) kubelet, k8s-worker01 Started container liveness-exec
Warning Unhealthy 14m (x4 over 17m) kubelet, k8s-worker01 Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
Normal Killing 14m (x4 over 17m) kubelet, k8s-worker01 Container liveness-exec failed liveness probe, will be restarted
Normal Pulling 13m (x6 over 18m) kubelet, k8s-worker01 Pulling image "k8s.gcr.io/busybox"
Warning BackOff 3m18s (x35 over 11m) kubelet, k8s-worker01 Back-off restarting failed container
httpGet
次にhttpGetの動作を確認します。
今回の例では、自分自身のindex.html(http://localhost:80/index.html)へのhttpGetを設定しています。
Podが起動して30秒後にindex.htmlファイルを削除するようにしています。
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
args:
- /bin/sh
- -c
- sleep 30; rm /usr/share/nginx/html/index.html; sleep 600
livenessProbe:
httpGet:
path: /index.html
port: 80
scheme: HTTP
initialDelaySeconds: 3
periodSeconds: 3
このマニフェストをapplyして確認します。
$ kubectl apply -f liveness-http.yaml
pod/liveness-http created
Podの状態を監視します。
$ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
liveness-http 0/1 Pending 0 0s
liveness-http 0/1 Pending 0 0s
liveness-http 0/1 ContainerCreating 0 0s
liveness-http 0/1 ContainerCreating 0 1s
liveness-http 1/1 Running 0 6s
liveness-http 1/1 Running 1 50s
liveness-http 1/1 Running 2 95s
liveness-http 1/1 Running 3 2m19s
liveness-http 1/1 Running 4 3m4s
liveness-http 1/1 Running 5 3m51s
liveness-http 0/1 CrashLoopBackOff 5 4m31s
liveness-http 1/1 Running 6 6m5s
再起動を繰り返すことによって、RESTARTSの値が増えていくことがわかりますね。
kubectl describeでもPodが再起動してる動作が確認できます。
$ kubectl describe pod liveness-http
Name: liveness-http
・・・
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 6m10s default-scheduler Successfully assigned default/liveness-http to k8s-worker01
Normal Pulled 4m36s (x3 over 6m6s) kubelet, k8s-worker01 Successfully pulled image "nginx:latest"
Normal Created 4m36s (x3 over 6m5s) kubelet, k8s-worker01 Created container nginx
Normal Started 4m36s (x3 over 6m5s) kubelet, k8s-worker01 Started container nginx
Warning Unhealthy 4m25s (x9 over 6m1s) kubelet, k8s-worker01 Liveness probe failed: Get http://192.168.79.88:80/index.html: dial tcp 192.168.79.88:80: connect: connection refused
Normal Killing 4m25s (x3 over 5m55s) kubelet, k8s-worker01 Container nginx failed liveness probe, will be restarted
Normal Pulling 3m55s (x4 over 6m9s) kubelet, k8s-worker01 Pulling image "nginx:latest"
Warning BackOff 60s (x5 over 100s) kubelet, k8s-worker01 Back-off restarting failed container
tcpSocket
最後にtcpSocketの動作を確認します。
今回の例ではnginxのポート80に対して、チェックするポートを77にしています。
Podが起動してから15秒待ってチェックを開始します。
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-tcp
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
livenessProbe:
tcpSocket:
port: 77
initialDelaySeconds: 15
periodSeconds: 3
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 1
$ kubectl apply -f liveness-tcp.yaml
pod/liveness-tcp created
Podの状態を確認します。
こちらも再起動を繰り返していることがわかります。
$ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
liveness-tcp 0/1 Pending 0 0s
liveness-tcp 0/1 Pending 0 0s
liveness-tcp 0/1 ContainerCreating 0 0s
liveness-tcp 0/1 ContainerCreating 0 2s
liveness-tcp 1/1 Running 0 6s
liveness-tcp 1/1 Running 1 26s
liveness-tcp 1/1 Running 2 48s
liveness-tcp 1/1 Running 3 69s
liveness-tcp 1/1 Running 4 90s
kubectl describeで詳細を確認できます。
$ kubectl describe pod liveness-tcp
Name: liveness-tcp
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 115s default-scheduler Successfully assigned default/liveness-tcp to k8s-worker01
Normal Pulled 47s (x4 over 109s) kubelet, k8s-worker01 Successfully pulled image "nginx:latest"
Normal Created 47s (x4 over 109s) kubelet, k8s-worker01 Created container nginx
Normal Started 47s (x4 over 109s) kubelet, k8s-worker01 Started container nginx
Warning Unhealthy 30s (x4 over 93s) kubelet, k8s-worker01 Liveness probe failed: dial tcp 192.168.79.97:77: connect: connection refused
Normal Killing 30s (x4 over 93s) kubelet, k8s-worker01 Container nginx failed liveness probe, will be restarted
Normal Pulling 29s (x5 over 113s) kubelet, k8s-worker01 Pulling image "nginx:latest"
まとめ
今回はKubernetesのヘルスチェック機能のLiveness Probeの動作を確認しました。
機能としては比較的わかりやすいですが、何をどうやってチェックするかは業務に依存してくると思いますので、その設計が難しそうですね。