petitviolet blog

    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