# Pod 探针

在生产环境下，进程正常启动并不代表应用能正常处理请求，**合理地设计应用的健康检查尤为重要**。Pod 提供的<mark style="color:blue;">**探针**</mark>可以很方便地用来<mark style="color:blue;">**检测容器内的应用是否正常**</mark>。

## 探针种类

Kubernetes 对 Pod 的健康状态可以通过三类探针来检查：<mark style="color:blue;">**startupProbe**</mark>、<mark style="color:blue;">**livenessProbe**</mark> 和 <mark style="color:blue;">**readinessProbe**</mark>，kubelet 定期执行这三类探针来诊断容器的健康状况。

### <mark style="color:blue;">**startupProbe 探针**</mark>

Kubernetes 1.16 新加的探测方式，用于<mark style="color:blue;">**判断容器内的应用程序是否成功启动**</mark>。如果配置了 startupProbe，就会先禁用其他探测，直到它成功为止。

* 如果探测失败，kubelet 会杀死容器，之后根据重启策略进行处理。
* 如果探测成功，或没有配置 startupProbe，则状态为 Success，之后不再进行探测。

### <mark style="color:blue;">**livenessProbe 探针**</mark>

用于<mark style="color:blue;">**判断容器是否存活（Running 状态）。**</mark>

* 如果 livenessProbe 探针探测到容器不健康，则 kubelet 将杀掉该容器，并根据容器的重启策略做相应的处理。
* 如果一个容器不包含 livenessProbe 探针，那么 kubelet 认为该容器的 livenessProbe 探针返回的值永远是 Success。

### <mark style="color:blue;">**readinessProbe 探针**</mark>

用于<mark style="color:blue;">**判断容器服务是否可用（Ready 状态）**</mark>，达到 Ready 状态的 Pod 才可以接收请求。

{% hint style="info" %}

#### 对于被 Service 管理的 Pod，**Service 与 Pod Endpoint 的关联关系将基于 Pod 是否 Ready 进行设置**。如果在运行过程中 Ready 状态变为 False，则系统自动将其从 Service 的后端 Endpoint 列表中隔离出去，后续再把恢复到 Ready 状态的 Pod 加回后端 Endpoint 列表。这样就能保证客户端在访问 Service 时不会被转发到服务不可用的 Pod 实例上。

{% endhint %}

## 实现方式

StartupProbe<mark style="color:blue;">、</mark>LivenessProbe 和 ReadinessProbe 均可配置以下三种实现方式：

{% hint style="info" %}

#### 对于每种探测方式，都需要设置 <mark style="color:blue;">**initialDelaySeconds**</mark> 和 <mark style="color:blue;">**timeoutSeconds**</mark> 两个参数，它们的含义分别如下：

* <mark style="color:blue;">**initialDelaySeconds**</mark>：启动容器后进行首次健康检查的等待时间。
* <mark style="color:blue;">**timeoutSeconds**</mark>：健康检查发送请求后等待响应的超时时间。当超时发生时，kubelet 会认为容器已经无法提供服务，将会重启该容器。
  {% endhint %}

### <mark style="color:blue;">**ExecAction**</mark>

**在容器内部执行一个命令，如果该命令的返回码为 0，则表明容器健康。**

<details>

<summary><mark style="color:purple;"><strong>Example</strong></mark></summary>

```yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: busybox
    args:
    - /bin/sh
    - -c
    - echo ok > /tmp/health; sleep 10; rm -rf /tmp/health; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/health
      initialDelaySeconds: 15
      timeoutSeconds: 1
    resources:
        limits:
          memory: "128Mi"
          cpu: "500m"
```

</details>

在上面的例子中，通过执行 **cat /tmp/health** 命令来判断一个容器运行是否正常。

在该 Pod 运行后，将在创建 /tmp/health 文件 10s 后删除该文件，而 LivenessProbe 健康检查的初始探测时间（initialDelaySeconds）为 15s，探测结果是 Fail，将导致 kubelet 杀掉该容器并重启它。

### <mark style="color:blue;">**TCPSocketAction**</mark>

**通过容器的 IP 地址和端口号执行 TCP 检查，如果能够建立 TCP 连接，则表明容器健康。**

<details>

<summary><mark style="color:purple;"><strong>Example</strong></mark></summary>

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-tcp
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80
    livenessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 30
      timeoutSeconds: 1
    resources:
      limits:
        memory: "128Mi"
        cpu: "500m"
```

</details>

在上面的例子中，通过与容器内的 localhost:80 建立 TCP 连接进行健康检查。

### <mark style="color:blue;">**HTTPGetAction**</mark>

**通过容器的 IP 地址、端口号及路径调用 HTTP Get 方法，如果响应的状态码大于等于 200 且小于 400，则认为容器健康。**

<details>

<summary><mark style="color:purple;"><strong>Example</strong></mark></summary>

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-http
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80
    livenessProbe:
      httpGet:
        path: /_status/healthz
        port: 80
      initialDelaySeconds: 30
      timeoutSeconds: 1
    resources:
      limits:
        memory: "128Mi"
        cpu: "500m"
```

</details>

在上面的例子中，kubelet 定时发送 HTTP 请求到 localhost:80/\_status/healthz 来进行容器应用的健康检查。
