kubernetes

kubernetesで動かすコンテナのヘルスチェック

More than 1 year has passed since last update.


この記事は何

タイトル通り。

kubernetes上でコンテナなWebアプリを動かす時に必要になってくるヘルスチェックや起動時のデータ読み込みをどうやって設定するか。

ドキュメントはこの辺り。

Configure Liveness and Readiness Probes | Kubernetes

コンテナのヘルスチェックには2種類あり、livenessとreadiness。

簡単に説明するとこんな感じか。


  • livenessはコンテナそのものが立ち上がっているかどうかをチェックするもの

  • readinessはリクエスト受け付け準備が整っているかどうかをチェックするもの


コンテナのヘルスチェック

コンテナの生存確認にコマンドを使う場合はexec.commandを指定する。

livenessProbe:

initialDelaySeconds: 10
periodSeconds: 10
exec:
command:
- "true"

initialDelaySecondsperiodSecondsで初回実行のタイミングと定期実行のスケジュールを設定することが出来る。

他に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の設定はtruefalseに変わっただけ。

$ 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とかperiodSecondslivenessProbeと同じでドキュメント参照

設定値を確認してみると以下のようになっている。

$ 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


所感

livenessProbereadinessProbeと2つのヘルスチェックがあるが、どちらも同じ処理をさせるならヘルスチェックが2倍走るだけになるので無意味なはず。

うまく使い分けて安全に運用していきたい。

今回はlivenessProbeではexec、readinessProbeではhttpGetにしたが、

例えばどちらもhttpGetにしてlivenessProbeでは何の処理もせず200返すだけのパス、readinessProbeではDBへのSELECTをするパス、などにすると良いのかもしれない。