作業メモ。
Kubernetes完全ガイド impress top gearシリーズを読みながら手元で確認した時のメモ。
環境
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.3", GitCommit:"2bba0127d85d5a46ab4b778548be28623b32d0b0", GitTreeState:"clean", BuildDate:"2018-05-28T20:03:09Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"11+", GitVersion:"v1.11.5-eks-6bad6d", GitCommit:"6bad6d9c768dc0864dab48a11653aa53b5a47043", GitTreeState:"clean", BuildDate:"2018-12-06T23:13:14Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"}
Kubernetes のヘルスチェックについて
Configure Liveness and Readiness Probes
Kubernetes のヘルスチェックでは2種類のヘルスチェックがある。
- Liveness Probe:Pod が正常に起動しているかの確認。ヘルスチェック失敗時には設定によって Pod の再起動も可能
- Readiness Probe:Readiness(準備ができていること)の確認。Pod がサービスイン出来ているかの確認。ヘルスチェック失敗時にはトラフィックを流さないように出来る(Pod の再起動はしない)
なお、いずれも独立しており、両方設定することも片方のみ設定する事も可能。
3種類のヘルスチェック方式について
どのような方式でヘルスチェックを行うかという方式については3種類ある。
Liveness/Readiness いずれでもすべて設定可能。
- ExecAction:指定した任意のコマンドをコンテナ内で実行する。終了ステータスコードが0なら成功
- TCPSocketAction:コンテナ IP の特定ポートについて TCP チェックを行う。ポートが開いていれば成功
- HTTPGetAction:コンテナ IP の特定ポート・パスに対して HTTP GET リクエストを行う。レスポンスの HTTP ステータスコードが200以上400未満の場合、成功
ExecAction を試す(Liveness Probe)
Liveness Probe で ExecAction を試す。
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
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
args
に指定があるようにコンテナではヘルスチェック用のファイルを作成し、30秒 sleep 後、ヘルスチェック用ファイルを削除する。
また、ヘルスチェックではヘルスチェック用のファイル /tmp/healhy
の存在を確認する。
initialDelaySeconds
は kubelet がヘルスチェックを開始するまで初回に待機する時間で periodSeconds
はヘルスチェック間隔。
上記より、こちらでは一定期間経過後、LivenessProbe が失敗し、Pod が再起動するはず。
試す。
$kubectl create -f https://k8s.io/examples/pods/probe/exec-liveness.yaml
# コンテナは起動成功
$kubectl describe pod liveness-exec
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 4s default-scheduler Successfully assigned default/liveness-exec to ip-172-31-19-51.ap-northeast-1.compute.internal
Normal Pulling 3s kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal pulling image "k8s.gcr.io/busybox"
Normal Pulled 2s kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Successfully pulled image "k8s.gcr.io/busybox"
Normal Created 2s kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Created container
Normal Started 2s kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Started container
# 35秒後状態を確認すると unhealhy になっている
$kubectl describe pod liveness-exec
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 43s default-scheduler Successfully assigned default/liveness-exec to ip-172-31-19-51.ap-northeast-1.compute.internal
Normal Pulling 42s kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal pulling image "k8s.gcr.io/busybox"
Normal Pulled 41s kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Successfully pulled image "k8s.gcr.io/busybox"
Normal Created 41s kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Created container
Normal Started 41s kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Started container
Warning Unhealthy 4s (x2 over 9s) kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
# 追加で待つと RESTART(再起動)が増加
$kubectl get pod liveness-exec
NAME READY STATUS RESTARTS AGE
liveness-exec 1/1 Running 2 2m
# イベントでも複数回 Created/Started があるのが確認できる.下記の場合、x3 となっている
$kubectl describe pod liveness-exec
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3m default-scheduler Successfully assigned default/liveness-exec to ip-172-31-19-51.ap-northeast-1.compute.internal
Normal Pulling 45s (x3 over 3m) kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal pulling image "k8s.gcr.io/busybox"
Normal Killing 45s (x2 over 2m) kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Killing container with id docker://liveness:Container failed liveness probe.. Container will be killed and recreated.
Normal Pulled 44s (x3 over 3m) kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Successfully pulled image "k8s.gcr.io/busybox"
Normal Created 43s (x3 over 3m) kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Created container
Normal Started 43s (x3 over 3m) kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Started container
Warning Unhealthy 5s (x8 over 2m) kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
HTTPGetAction を試す(Liveness Probe)
次は LivenessProbe で HTTPGetAction を試す。
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
image: k8s.gcr.io/liveness
args:
- /server
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: X-Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
パス「healhtz」のポート8080に HTTP GET リクエストを行い、ヘルスチェックを行う。
こちらのコンテナでは以下のようなプログラムが動いており、最初の10秒間はステータスコード200を返し、以降は500を返すようになっている。
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
duration := time.Now().Sub(started)
if duration.Seconds() > 10 {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))
} else {
w.WriteHeader(200)
w.Write([]byte("ok"))
}
})
試す。
$kubectl create -f https://k8s.io/examples/pods/probe/http-liveness.yaml
# 時間経過後確認すると Liveness probe が失敗し、コンテナが kill されたメッセージがある
$ kubectl describe pod liveness-http
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 1m default-scheduler Successfully assigned default/liveness-http to ip-172-31-19-51.ap-northeast-1.compute.internal
Normal Pulled 32s (x3 over 1m) kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Successfully pulled image "k8s.gcr.io/liveness"
Normal Created 32s (x3 over 1m) kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Created container
Normal Started 32s (x3 over 1m) kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Started container
Normal Pulling 16s (x4 over 1m) kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal pulling image "k8s.gcr.io/liveness"
Warning Unhealthy 16s (x9 over 58s) kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Liveness probe failed: HTTP probe failed with statuscode: 500
Normal Killing 16s (x3 over 52s) kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Killing container with id docker://liveness:Container failed liveness probe.. Container will be killed and recreated.
# RESTARTS が増加している
$kubectl get pod liveness-http
NAME READY STATUS RESTARTS AGE
liveness-http 1/1 Running 2 54s
TCPSocketAction を試す(Liveness Probe,Readiness Probe)
一つのマニュフェストに Liveness Probe と Readiness Probe を定義して TCPSocketAction を確認する。
apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: k8s.gcr.io/goproxy:0.1
ports:
- containerPort: 8080
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
上記マニュフェストでは Liveness Probe と Readiness Probe を定義しており、ポート8080に対して TCP 接続を試みて、接続できる場合にはヘルスチェック成功となる。
こちらのコンテナでは 8080 ポートでの接続は可能なため、いずれのヘルスチェックも成功する。
試す。
$kubectl create -f https://k8s.io/examples/pods/probe/tcp-liveness-readiness.yaml
# ヘルスチェックは成功しているのでエラーメッセージは出ない
$ kubectl describe pod goproxy
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 36s default-scheduler Successfully assigned default/goproxy to ip-172-31-19-51.ap-northeast-1.compute.internal
Normal Pulling 36s kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal pulling image "k8s.gcr.io/goproxy:0.1"
Normal Pulled 33s kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Successfully pulled image "k8s.gcr.io/goproxy:0.1"
Normal Created 33s kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Created container
Normal Started 33s kubelet, ip-172-31-19-51.ap-northeast-1.compute.internal Started container
# RESTARS は0で READY 状態が1/1
$kubectl get pod goproxy
NAME READY STATUS RESTARTS AGE
goproxy 1/1 Running 0 2m
予想通り、Pod は再起動しない。