sagantaf

IT関連の技術記事を書くブログ。

Podをヘルスチェックする3つの方法 - probeを理解する

KubernetesにはPodをヘルスチェックする方法として3つのprobeという機能を用意しています。その3つのprobeの使い方や違いを解説します。

probeはKubernetesの重要な機能で、エンドユーザーにとって使いやすいサービス提供のために欠かせないものです。基本的な機能としてはPodがトラフィックを適切に処理できる状態かどうかを一定の間隔で監視し、再起動などのアクションを実行できます。

ReadinessProbe

ReadinessProbeとは

ReadinessProbeはServiceを構築するときに一緒に検討するべきリソースの一つです。

ServiceはYAMLのlabelに一致するPodを見つけたら、そこにトラフィックを流すしくみになっています。Podを見つけるとすぐにトラフィックを流し始めるため、Podの状況を見てはいません。もし、Podが起動後に何か設定が必要で、それに対して時間がかかる場合、トラフィックが流れてきても処理できず、エラーになってしまいます。

この問題を解決するためにReadinessProbeが使われます。RedinessProbeはPodのYAMLに書き加えることで設定できます。ReadinessProbeが設定されたPodがデプロイされたら、Podの準備ができていないうちはServiceからトラフィックを流さないようにコントロールプレーにシグナルを送れるようになります。

ReadinessProbeの書き方

ReadinessProbeの設定パターンは3種類あります。

  1. HTTP: Podの 準備ができたことを、HTTPリクエストを送ることで確認する方法です。200以上400未満のレスポンスコードが返ってきたら準備完了とみなします。
  2. Command: Podの準備ができたことを、コマンドを実行することで確認する方法です。exit code 0で返ってきたら準備完了とみなします。
  3. TCP: Podの準備ができたことを、TCPのコネクションを生成することで確認する方法です。コネクションを生成できたら準備完了とみなします。

それぞれの事例を見ていきましょう。

1.HTTPパターン

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod-readinessprobe
spec:
  containers:
  - name: nginx
    image: nginx
    readinessProbe:
      httpGet:
        path: /ready
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5

initialDelaySecondesには、最初のヘルスチェックを実行するまでに待つ時間を設定します。periodsSecondsには、ヘルチェックの実行間隔を設定します。 この設定の場合は、Podが起動して5秒後、/readyエンドポイントに対してHTTP GETリクエストを送り、その後5秒ごとにリクエストを繰り返します。HTTPステータスコードが200-399の範囲内であればPodを準備完了とみなし、PodはServiceからのリクエストを受け入れるようになります。

2.Commandパターン

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  containers:
  - name: myapp-container
    image: myapp
    readinessProbe:
      exec:
        command:
        - cat
        - /tmp/ready
      initialDelaySeconds: 5
      periodSeconds: 5

このパターンでは、コマンドを指定します。上記の書き方の場合、コンテナ内でcat /tmp/readyコマンドを実行し、ファイルが存在すれば(exitコードが0なら)Podは準備完了とみなされます。Podで稼働するアプリの実装として、準備が完了したら当該ファイルを作成する処理を入れておく必要があります。

3.TCPパターン

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  containers:
  - name: myapp-container
    image: myapp
    readinessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5

このパターンではTCPソケットのポート番号を指定します。PodがTCPポート80で接続を受け入れられるかどうかで準備完了を判断します。このパターンはPodで稼働するアプリケーションでHTTPを起動させていない場合や、所定のファイルを置けない(置きたくない)場合に利用できます。

実際のアプリ開発の場面では、アプリケーションの状態に関連するエンドポイントを呼び出すことで、より有効性が増します。たとえば、アプリがDBを使用している場合、内部的にMySQLへの接続を開くページを呼び出して、アプリケーションがそのDBと通信できることを確認するようにできます。ただ単に200を返すようなページを用意するのではなく、実際にDBに接続しにいくようなテスト用のページを用意することで、より堅牢なアプリになるというわけです。


LivenessProbe

LivenessProbeとは

LivenessProbeはReadinessProbeと似ています。ReadinessProbeはPodの準備完了状況を伝えるためのヘルスチェックとして使えるのに対し、LivenessProbeは定期的なヘルスチェックとして利用します。

ServiceではPodの生死を検知することができません。Podが死んでいてもトラフィックを送り続けてしまいます。

ivenessProbeをPodに設定しておくことで、Podに対して常にヘルスチェックを実行し、異常が生じた場合にはPodを再起動してくれます。

LivenessProbeの書き方

設定パターンはReadinessと同じ3種類です。それぞれの設定方法を見ていきましょう。

1.HTTP Probe

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod-livenessprobe
spec:
  containers:
  - name: nginx
    image: nginx
    livenessProbe:
     httpGet:
         path: /health
         port: 80
      initialDelaySeconds: 15
      periodSeconds: 20

この例では、HTTP GETリクエストを用いてヘルスチェックします。Podが起動して15秒後に/healthエンドポイントにリクエストを送り、その後20秒ごとにチェックを繰り返します。レスポンスコードが200-399ならPodは正常とみなされます。

2.Command Probe

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  containers:
  - name: myapp-container
    image: myapp
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 15
   periodSeconds: 20

この例ではcat /tmp/healthyコマンドを実行し、exitコードが0ならPodは正常と判断されます。

3.TCP Probe

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  containers:
  - name: myapp-container
     image: myapp
     livenessProbe:
     tcpSocket:
       port: 80
     initialDelaySeconds: 15
     periodSeconds: 20

TCPソケットを使ったLivenessProbeの例です。PodがTCPポート80で接続を受け入れるかどうかをチェックし、接続できればPodは正常とみなされます。


StartupProbe

StartupProbeとは

StartupProbeは比較的新しい機能で、Kubernetes 1.16でアルファ版として導入され、その後のバージョンで改善が進められました(LivenessProbeとReadinessProbeはKubernetesの初期のバージョンから存在しています)。正式に安定した機能としてリリースされたのはKubernetes 1.20です。

StartupProbeは、特に起動に時間がかかるアプリケーションの健康状態をチェックするために設計されています。LivenessProbeやReadinessProbeとは異なり、StartupProbeはコンテナが初めて起動する際にのみ実行されます。

起動が遅いアプリケーションでは、LivenessProbeが早すぎる段階でPodを異常と判断し、再起動を引き起こす可能性があります。StartupProbeはこの問題を解決するために、アプリケーションが起動して安定するまでの間、LivenessProbeとReadinessProbeのチェックを一時的に停止します。

StartupProbeの書き方

例によって3種類あります。

1.HTTP Probe

apiVersion: v1
kind: Pod
metadata:
  name: slow-start-app
spec:
  containers:
  - name: myapp
     image: myapp
     startupProbe:
     httpGet:
        path: /start
        port: 8080
     failureThreshold: 30
     periodSeconds: 10

この例ではHTTP GETリクエストを用いてStartupをチェックします。/startエンドポイントに対してHTTPリクエストを送り、10秒ごとにリクエストを繰り返します。failureThresholdは30に設定されており、これはProbeが30回失敗するまでPodを起動し続けることを意味します。

2.Command Probe

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  containers:
  - name: myapp-container
    image: myapp
    startupProbe:
      exec:
        command:
        - cat
        - /tmp/start
      failureThreshold: 30
      periodSeconds: 10

コマンドを実行してStartupを確認する例です。cat /tmp/startコマンドを実行し、exitコードが0ならアプリケーションは起動中と判断されます。このチェックは10秒ごとに実行され、30回の失敗まで許容されます。

3.TCP Probe

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  containers:
  - name: myapp-container
    image: myapp
    startupProbe:
      tcpSocket:
        port: 8080
      failureThreshold: 30
      periodSeconds: 10

TCPソケットを使ったStartupProbeの例です。PodがTCPポート8080で接続を受け入れるかどうかをチェックし、接続できればアプリケーションは起動中とみなされます。チェックは10秒ごとに実行され、最大30回の失敗まで許容されます。

3つのprobeをうまく組み合わせて利用する

Kubernetesにおいて、ReadinessProbe、LivenessProbe、およびStartupProbeを組み合わせて使用することは、異常な通信を発生させにくくできるという信頼性と状態監視を自動化できるという効率性などを高めるために有効です。説明してきたように、それぞれのProbeは異なる目的と機能を持っており、合わせて使用することで、アプリケーションの稼働状況をより細かく監視し、適切に対応することが可能になります。

3つのProbeの役割

改めて3つのProbeを整理します。

  • StartupProbe: アプリケーションが初めて起動する際に使用され、起動に時間がかかる場合に特に有用。このProbeが成功するまで、LivenessProbeとReadinessProbeは無効化される。
  • LivenessProbe: アプリケーションが動作しているかどうかを定期的に確認し、問題がある場合にはPodを再起動させる。
  • ReadinessProbe: アプリケーションがトラフィックを受け入れる準備ができているかどうかをチェックし、準備ができていない間はトラフィックを受け入れない。

設定例

以下は、3つのProbeを組み合わせたYAML設定の例です。

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  containers:
  - name: myapp-container
    image: myapp
    startupProbe:
      httpGet:
        path: /startup
        port: 8080
      failureThreshold: 30
      periodSeconds: 10
    livenessProbe:
      httpGet:
        path: /health
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 5

上記の例では - StartupProbe: /startupエンドポイントをチェックし、アプリケーションの起動を監視します。最大30回まで失敗を許容し、10秒ごとにチェックします。つまり最大で300秒間は監視を続けます。 - LivenessProbe: StartupProbeのチェック完了後から5秒後に/healthエンドポイントでアプリケーションが正常に動作しているかを確認し、問題があればPodを再起動します。10秒ごとにチェックを行います。 - ReadinessProbe: StartupProbeのチェック完了後から5秒後に/readyエンドポイントでトラフィックを受け入れる準備ができているかを確認し、準備ができていない場合はトラフィックを受け入れません。5秒ごとにチェックします。

このように、3つのProbeを適切に組み合わせることで、アプリケーションが正常に起動し、安定して動作し、適切なタイミングでトラフィックを処理することが可能になります。

なお、最近のKubernetesのバージョンでは、grpcによるヘルスチェックの機能もアルファ版として提供されています。詳細は公式ページを参考にしてください( Podのライフサイクル | Kubernetes