K8S Health
分布式系统问题
分布式系统比较难于管理的主要原因在于,在系统运行过程中,如果有某一点出现问题,我们需要让系统自动绕过该问题,并且自动修复该问题,来给用户带来 0 宕机时间的高可用系统。
Kubernetes 健康检查
运行状况检查是一种可以让 K8S 知道当前系统中每一个 Pod 实例状态是否正常的简单方法,如果某个实例的某个服务不可用,那么其他服务就不应访问它,也就是不应该有任何流量发送到该服务,正确的方式应该是将流量发往另一个正常的实例或稍后重试。同时系统还应该将不可用的服务恢复到健康的状态。
在 Kubernetes 中当 Pod 中所有的容器(应用进程)启动后,Kuberntes 将会开始向该 Pod 发送流量。并且在容器故障时重新启动容器。这个默认的行为一个足够好了,但是 Kubernetes 提供了可以自定义运行健康检查的方式,让我们更有针对性的应对不同容器做出更合理的检查方式。
Kubernetes 健康检查方式
Kubernetes 提供了两种健康检查的方式:
Readiness 探针的用途旨在让 Kubernetes 知道我们的应用何时准备就绪,可对外提供服务。Kubernetes 在允许服务将流量发送到 Pod 之前,会确保 readiness 通过检查。如果启动时 readiness 探针失败,Kubernetes 会停止向这个 Pod 发送流量
Liveness 探针的用途旨在让 Kubernetes 知道我们的应用是否存活,如果检测到应用非存活状态,Kubernetes 会删除这个 Pod,并启动一个新的 Pod 替换它。
Kubernetes 健康检查类型
Kubernetes 提供了三种健康检查的类型:
HTTP:发送 HTTP 请求,Kubernetes 会 ping 一个指定 path,当返回状态码在 200-300 范围内会标记为健康,否则标记为不健康。即使应用不是 HTTP 服务,也可以写一个轻量级 HTTP 接口,用于响应 Liveness 检测。
CMD:在容器中运行指定命令,如果命令返回码为 0 会标记为健康,否则标记为不健康。当不能使用 HTTP 检测服务是否健康时,可以使用 CMD 运行指定命令的方式进行健康检查。
TCP:在容器中对指定端口建立 TCP 链接,如果可以建立会标记为健康,否则标记为不健康。当服务为 grpc 或 ftp 等服务时,可以使用 TCP 对指定端口建立 TCP 链接进行健康检查。
Kubernetes 健康检查属性
Kubernetes 提供了五种健康检查的属性:
initialDelaySeconds:第一次检查,在容器启动多少秒后执行检查,单位秒。
periodSeconds:周期性检查,在容器启动后执行检查的周期是多少秒,单位秒。
timeoutSeconds:检查超时时间,检查运行超过多少秒后认为失败,单位秒。
successThreshold:检查成功阈值,检查通过次数达到阈值时认为成功,单位秒。
failureThreshold:检查失败阈值,检查失败此时达到阈值时认为失败,单位秒。
Liveness 存活性检查
Kubernetes 会定期执行 Liveness 探针检测,在通过检测时不会对 Pod 做任何处理。在未通过检测时 Kubernetes 会删除该 Pod,并启动新的 Pod 替换它。
- HTTP 方式
启动 nginx 容器 5 秒后执行存活性检查,ping /index.html 路径,检查周期 5 秒,检查超时时间 5 秒,失败 3 次后认为失败,成功 1 次后认为成功。
apiVersion: v1
kind: Pod
metadata:
name: liveness-http
labels:
app: liveness-http
spec:
containers:
- name: liveness
image: nginx:1.9
ports:
- name: http
containerPort: 80
livenessProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
```
* CMD 方式
启动 busybox 容器 5 秒后执行存活性检查,cat /tmp/healthy 文件,检查周期 5 秒,检查超时时间 5 秒,失败 3 次后认为失败,成功 1 次后认为成功。
```yaml
apiVersion: v1
kind: Pod
metadata:
name: liveness-cmd
labels:
app: liveness-cmd
spec:
containers:
- name: busybox
image: busybox
command: ["sh", "-c", "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"]
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
```
* TCP 方式
启动 nginx 容器 5 秒后执行存活性检查,对 80 端口建立 tcp 链接,检查周期 5 秒,检查超时时间 5 秒,失败 3 次后认为失败,成功 1 次后认为成功。
```yaml
apiVersion: v1
kind: Pod
metadata:
name: liveness-tcp
labels:
app: liveness-tcp
spec:
containers:
- name: liveness
image: nginx:1.9
ports:
- name: http
containerPort: 80
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
```
<center>
<img style="border-radius: 0.3125em;box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="http://qiniu.raindrop-wl.cn/liveness-pass.png">
<div style="color:orange; border-bottom: 1px solid #d9d9d9;display: inline-block;color: #999;padding: 2px;">
liveness-pass
</div>
</center>
<center>
<img style="border-radius: 0.3125em;box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="http://qiniu.raindrop-wl.cn/liveness-notpass.png">
<div style="color:orange; border-bottom: 1px solid #d9d9d9;display: inline-block;color: #999;padding: 2px;">
liveness-notpass
</div>
</center>
### Readiness 可用性检查
  Kuberntes 会定期执行 Readiness 探针检测,在未通过检测时不会将流量发往该 Pod。在通过检测后才会将流量发往该 Pod。
* HTTP 方式
启动 nginx 容器 5 秒后执行可用性检查,ping /index.html 路径,检查周期 5 秒,检查超时时间 5 秒,失败 3 次后认为失败,成功 1 次后认为成功。
```yaml
apiVersion: v1
kind: Pod
metadata:
name: readiness-http
labels:
app: readiness-http
spec:
containers:
- name: readiness
image: nginx:1.9
ports:
- name: http
containerPort: 80
readinessProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
```
* CMD 方式
启动 busybox 容器 5 秒后执行可用性检查,cat /tmp/healthy 文件,检查周期 5 秒,检查超时时间 5 秒,失败 3 次后认为失败,成功 1 次后认为成功。
```yaml
apiVersion: v1
kind: Pod
metadata:
name: readiness-cmd
labels:
app: readiness-cmd
spec:
containers:
- name: nginx
image: nginx:1.9
command: ["sh", "-c", "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"]
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
```
* TCP 方式
启动 nginx 容器 5 秒后执行可用性检查,对 80 端口建立 tcp 链接,检查周期 5 秒,检查超时时间 5 秒,失败 3 次后认为失败,成功 1 次后认为成功。
```yaml
apiVersion: v1
kind: Pod
metadata:
name: readiness-tcp
labels:
app: readiness-tcp
spec:
containers:
- name: readiness
image: nginx:1.9
ports:
- name: http
containerPort: 80
readinessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
```
<center>
<img style="border-radius: 0.3125em;box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="http://qiniu.raindrop-wl.cn/readiness-notpass.png">
<div style="color:orange; border-bottom: 1px solid #d9d9d9;display: inline-block;color: #999;padding: 2px;">
readiness-notpass
</div>
</center>
<center>
<img style="border-radius: 0.3125em;box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="http://qiniu.raindrop-wl.cn/readiness-pass.png">
<div style="color:orange; border-bottom: 1px solid #d9d9d9;display: inline-block;color: #999;padding: 2px;">
readiness-pass
</div>
</center>
### 注意事项
* 当使用 Liveness 时,需要注意 initialDelaySecons 参数设置的时间一定要大于应用启动时间,否则应用只能不断的循环重启,永远无法就绪。
* 建议使用 P99 的启动时间作为 initialDelaySecons 参数的值。随着应用启动时间变快或变慢,确保更新该参数。
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!