kubernetesで動かすコンテナのヘルスチェック
2018-04-01
Qiitakubernetesこの記事は何
タイトル通り。 kubernetes 上でコンテナな Web アプリを動かす時に必要になってくるヘルスチェックや起動時のデータ読み込みをどうやって設定するか。
ドキュメントはこの辺り。 Configure Liveness and Readiness Probes | Kubernetes
コンテナのヘルスチェックには 2 種類あり、liveness と readiness。 簡単に説明するとこんな感じか。
- liveness はコンテナそのものが立ち上がっているかどうかをチェックするもの
- readiness はリクエスト受け付け準備が整っているかどうかをチェックするもの
コンテナのヘルスチェック
コンテナの生存確認にコマンドを使う場合はexec.command
を指定する。
livenessProbe:
initialDelaySeconds: 10
periodSeconds: 10
exec:
command:
- "true"
initialDelaySeconds
とperiodSeconds
で初回実行のタイミングと定期実行のスケジュールを設定することが出来る。
他にtimeoutSeconds
, successThreshold
, failureThreshold
の設定項目があるのでドキュメントを参照。
実際の設定を見るにはkubectl describe <pod>
を実行すれば良い。
例えばこのようになっている。
pod の名前は適当に読み替えてほしい。
$ kubectl describe po app-86d46c684c-rf5sj | grep Liveness
Liveness: exec [true] delay=10s timeout=1s period=10s #success=1 #failure=3
これだとtrue
を実行するだけなのでコンテナが立ち上がれば liveness は正常となり、コンテナは無事に立ち上がる。
次はわざと失敗させてみる。
livenessProbe:
initialDelaySeconds: 10
periodSeconds: 10
exec:
command:
- "false"
このような設定にしてkubectl apply
して反映してからkubectl describe
してみる
Liveness の設定はtrue
がfalse
に変わっただけ。
$ kubectl describe po app-65c89f7c5d-pwdr9 | grep Liveness
Liveness: exec [false] delay=10s timeout=1s period=10s #success=1 #failure=3
当然false
を実行すると終了ステータスが失敗扱いになるため liveness は異常となる。
その結果、コンテナは再作成される。
$ kubectl describe po app-65c89f7c5d-pwdr9 | grep Killing
Normal Killing 5m (x2 over 6m) kubelet, minikube Killing container with id docker://app:Container failed liveness probe.. Container will be killed and recreated.
しかし何度やっても liveness が正常になることはないので、pod の status を見てみるとCrashLoopBackOff
となってしまっている。
$ kubectl get po app-65c89f7c5d-pwdr9
NAME READY STATUS RESTARTS AGE
app-65c89f7c5d-pwdr9 1/2 CrashLoopBackOff 6 8m
このようにしてlivenessProbe
を使ってコンテナのヘルスチェックを行うことが出来る。
コンテナの疎通チェック
livenessProbe
はコンテナのヘルスチェック、というだけであってコンテナ内のサービス、例えば Web アプリが正常に起動しているかどうかはまた別の話。
JVM を立ち上げたり最初にデータ読み込みであったりと、アプリケーションによっては最初にリクエストを受け付けられるようになるまでに時間がかかるものもある。
そういった時にヘルスチェック/疎通チェックとして使うのがreadinessProbe
というもの。
先程と違って 8080 番ポートの/health パスへ HTTP リクエストでコンテナのプロセスへ疎通確認をしてみる。
ports:
- containerPort: 8080
name: api-port
readinessProbe:
initialDelaySeconds: 5
periodSeconds: 20
httpGet:
path: /health
port: api-port
httpHeaders:
- name: X-k8s-Header
value: readiness
port 指定は直接書いてもいいが、一応名前付けしてある。
initialDelaySeconds
とかperiodSeconds
はlivenessProbe
と同じでドキュメント参照。
設定値を確認してみると以下のようになっている。
$ kubectl describe po app-65c89f7c5d-pwdr9 | grep Readiness
Readiness: http-get http://:api-port/health delay=5s timeout=1s period=20s #success=1 #failure=3
httpGet
の API リファレンスはこの辺にある。
Kubernetes API Reference Docs
両方まとめて書くとこんな感じになる。
spec:
containers:
- name: app
image: my-app:latest
ports:
- containerPort: 8080
name: api-port
livenessProbe:
initialDelaySeconds: 10
periodSeconds: 10
exec:
command:
- "true"
readinessProbe:
initialDelaySeconds: 5
periodSeconds: 20
httpGet:
path: /health
port: api-port
httpHeaders:
- name: X-k8s-Header
value: readiness
所感
livenessProbe
とreadinessProbe
と 2 つのヘルスチェックがあるが、どちらも同じ処理をさせるならヘルスチェックが 2 倍走るだけになるので無意味なはず。
うまく使い分けて安全に運用していきたい。
今回はlivenessProbe
では exec、readinessProbe
では httpGet にしたが、
例えばどちらも httpGet にしてlivenessProbe
では何の処理もせず 200 返すだけのパス、readinessProbe
では DB への SELECT をするパス、などにすると良いのかもしれない。
from: https://qiita.com/petitviolet/items/135c08cee5bfa5e1709b