この記事は何
タイトル通り。
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をするパス、などにすると良いのかもしれない。