Kubernetes Probe is 何

## はじめに

Kubernetesのマニフェストファイルの設計をしている中でProbeについて理解する必要がありましたので、本記事ではProbeについてまとめていきたいと思います。

Kubernetesとは何か？については以前の記事で執筆したことがありますので、Kubernetesがそもそもよくわからないという方はこちらの記事を参照ください。

https://qiita.com/triple321jhango/items/5374ae3d1735750e6cf9


## Probeとは
ProbeとはkubeletからPodにヘルスチェックを行う仕組みで、いわゆる死活監視やトラフィックの制御を行います。
定期的にコンテナの診断を行う常駐医師の役割をするのがProbeです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/b1eaab87-fbcb-f9b7-4300-1bb3d6d833be.png" width=70%>


:::note info
kubeletとはKubernetesクラスター内のノードで実行されるエージェントです。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/440464d2-4041-ca89-f361-c450f35f3235.png)


## Probeの種類
Probeにはいくつか種類があり、以下3つが存在します。

### Liveness Probe
コンテナの生存確認を行います。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/a617a009-5e34-830c-dbed-d16a2e7c9448.png" width=70%>

コンテナ内のアプリケーションが応答しなかった場合には、コンテナは再作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/47221c91-ee05-a335-5cc2-0aaa6eb30e5c.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/e5e8ca4a-bf6c-486b-5f47-7c8669c6e8eb.png)



### Readiness Probe
コンテナがトラフィックを受け入れられる状態であるかを確認します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/35dd59da-d89f-d450-d3fa-bef12f0a6b39.png" width=70%>


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/e30c6a9c-7a57-e1c5-aec1-2b7ecce1dc3a.png)
仮にPodがトラフィックを受け入れられない状態の場合、ServiceはPodを切り離します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/457bd677-0c97-f83e-df7a-c6f9507874a2.png)

### Startup Probe
コンテナアプリケーションが起動完了したかの確認を行います。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/3f6f0e35-f8fd-d37f-a679-366573b3ed31.png" width=70%>

Startup Probeによってアプリケーションの起動が完了するまでに最大5分間の猶予を与えることが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/3d99ed93-ad74-66d8-2d29-ac673630ae1f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/fa0c481a-af30-54cc-6a87-68cd5b9a6cff.png)

Startup Probeに成功すると、その後はLiveness Probeが引き継いでコンテナの生存確認を行います。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/36218699-a5f2-503c-7f94-787842db8fc8.png" width=70%>

## Probeのパラメータについて
Probeにはいくつかパラメータを設定する項目がありますが、以下のようなものが存在します。

### initialDelaySeconds
コンテナが起動してからLiveness ProbeまたはReadiness Probeが開始されるまでの秒数を指定します。
デフォルトは0秒、最小値は0。
つまりどういうことかというと、
- `Liveness Probe`はコンテナの生存確認を行うこと
- `Readiness Probe`はコンテナのトラフィック受け入れ状態であるかを確認すること
上記でしたね。

**Liveness Probeの観点**
コンテナが起動してすぐに再起動されないように、最初のProbeを実行する前に待ち時間を設定します。
コンテナが起動してすぐにProbeを実行すると、アプリケーションが本来数秒後に起動してくるにもかかわらず、すぐに死んでると判断してしまうと、そこで再作成されてしまうことを防ぐためにこの設定を行います。

**Readiness Probeの観点**
アプリケーションが起動してすぐにトラフィックを受け入れられる準備ができない場合、準備が整う前にトラフィックを送ってしまって、受け入れダメでした、と判断されないように適切な秒数を設定して準備が整う前にトラフィックを送るのを防ぎます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/7708befa-efdb-7812-31b6-38ce720e217d.png" width=70%>


### periodSeconds
Probeが実行される頻度(秒数)を指定する。
デフォルトは10秒。最小値は1。

Probeというのはコンテナがちゃんと動いているかのチェックですが、このチェックを定期的に行う際に、どのくらいの間隔でチェックを行うかを定義するものです。

`periodSeconds: 10`と定義すれば、10秒ごとにコンテナがちゃんと動いているかを確認するよ、ということです。


### timeoutSeconds
Probeがタイムアウトになるまでの秒数を指定する。
デフォルトは1秒、最小値は1。
これは文字通り、コンテナからの応答をどれくらい待つか？を指定するものです。

例をあげると、あなたがお友達の家に行き、チャイムを鳴らしても反応がなければ居ないと判断するのと一緒です。
`timeoutSeconds: 1`と定義すれば、1秒待ってもコンテナから返事がない場合はコンテナが動いていないと判断するということです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/e098c585-8b10-4763-4496-989e66c761a5.png" width=70%>

### successThreshold
一度Probeが失敗した後、次のProbeが成功したとみなされるための最小連続成功数を指定する。デフォルトは1。
これはLiveness Probe、Startup Probeには1を設定する必要があり、最小値は1です。
要するに失敗しても、次に成功していなくてはいけないということですね。
スクイズに一度失敗したら、次は失敗できないのと一緒ですね。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/98224ffd-9490-aeaf-df6c-7984451e4c30.png" width=70%>


## failureThreshold
Probeが失敗した場合、Probeを試行する回数を指定する。デフォルトは3。最小値は1。
- Liveness Probeの場合、`failureThreshold`で設定した試行回数に到達すると、コンテナが生きていないと判断し、コンテナの再起動を行います。
- Readiness Probeの場合、`failureThreshold`で設定した試行回数に到達すると、コンテナがトラフィックの受け入れ態勢が整っていないと判断し、ServiceがPodを切り離します。

何度も呼びかけているのに、呼びかけに応答がなければ「ぁー、だめだな」と諦めてしまうのと一緒ですね。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379725/077b9fd8-52f5-04ee-a200-e0eb7b813c77.png" width=70%>


## Probeを行う手段
ここまで紹介してきたProbeですが、Probeを行う手段はなんですか？という話をします。
Podが生きているか、受け入れ態勢大丈夫か？といったことを確認するためにはどういった方法で確認をしているのか、以下で説明します。
Probeを行う手段には以下の3つがありますが、今回は`httpGet`に内容を絞って解説します。
- `httpGet`
- `exec`
- `tcpSocket`

### httpGet
`httpGet`、つまりHTTPのGETリクエストをPodに対して送信して、Podの返答が200番や300番台のステータスコードが返ってきた場合はコンテナが`Healthy`であると判断されます。

以下のマニフェストの全体像を例にします。

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: liveness
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: liveness
  template:
    metadata:
      labels:
        app: liveness
    spec:
      containers:
        - name: liveness
          image: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:latest
          resources:
            requests:
              cpu: "2"
              memory: "10G"
          ports:
            - containerPort: 8080
          livenessProbe:
            httpGet:
              port: 8080
              path: /liveness/healthcheck
            periodSeconds: 10
            timeoutSeconds: 5
            successThreshold: 1
            failureThreshold: 10
```


Probeに関する箇所は以下です。

```yaml
          livenessProbe:
            httpGet:
              port: 8080
              path: /liveness/healthcheck
            periodSeconds: 10
            timeoutSeconds: 5
            successThreshold: 1
            failureThreshold: 10
```

上記の場合、以下のような意味になります。
- `8080`ポートの`/liveness/healthcheck`のパスにHTTP GETリクエストを送信します。
- `periodSeconds: 10` 10秒ごとにヘルスチェックを実行
- `timeoutSeconds: 5` 5秒間応答を待つ
- `failureThreshold: 10` 10回連続でヘルスチェックに失敗するとコンテナを再起動

以下のマニフェストファイルを使用して、ヘルスチェックを意図的に失敗させ、Podが再起動するか検証してみましょう。

:::note warn
本マニフェストはNginxに`/healthcheck`というパスが存在しないので、必然的にヘルスチェックは失敗します。
`failureThreshold`:1に修正し、1回失敗したらヘルスチェック失敗という仕様にします。
:::

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-liveness-check
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-liveness
  template:
    metadata:
      labels:
        app: nginx-liveness
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 8080
          livenessProbe:
            httpGet:
              path: /healthcheck
              port: 8080
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 1
```

指定のディレクトリにマニフェストファイルを作成し、以下コマンドでPodを起動させてみます。
(`nginx-healthcheck-deployment.yml`という名前でマニフェストファイルを作成しています)
```bash
kubectl apply -f nginx-healthcheck-deployment.yml

$ kubectl get pod -w
NAME                                    READY   STATUS    RESTARTS   AGE
nginx-liveness-check-7df747898c-8rxq9   1/1     Running   0          34s
nginx-liveness-check-7df747898c-8rxq9   1/1     Running   1 (9s ago)   39s
nginx-liveness-check-7df747898c-8rxq9   1/1     Running   2 (7s ago)   48s
nginx-liveness-check-7df747898c-8rxq9   0/1     CrashLoopBackOff   2 (2s ago)   52s
nginx-liveness-check-7df747898c-8rxq9   1/1     Running            3 (24s ago)   74s
nginx-liveness-check-7df747898c-8rxq9   1/1     Running            4 (5s ago)    86s
nginx-liveness-check-7df747898c-8rxq9   0/1     CrashLoopBackOff   4 (1s ago)    92s
nginx-liveness-check-7df747898c-8rxq9   1/1     Running            5 (49s ago)   2m20s
```
ステータスが`Running`と`ClashLoopBackOff`を繰り返しているのがわかりますね。

## 最後に
本記事ではProbeについての解説と実際に検証をしてみました。
実務で検証作業をする上で、予習をしておきたい意味も込めて執筆しました。
同じようにProbeに関する設計や検証をしようとしている方の助けになれば幸いです。


## 参考
https://kubernetes.io/ja/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/