blog.petitviolet.net

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"

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 をするパス、などにすると良いのかもしれない。

from: https://qiita.com/petitviolet/items/135c08cee5bfa5e1709b