强大的自愈能力是 Kubernetes 这类容器编排引擎的一个重要特性。自愈的默认实现方式是自动重启发生故障的容器。除此之外,用户还可以利用 Liveness 和 Readiness 探测机制设置更精细的健康检查,进而实现如下需求:
- 零停机部署
- 避免部署无效的镜像
- 更加安全的滚动升级
重启策略+健康检查(应用自修复)
Kubernetes 默认的健康检查机制:每个容器启动时都会执行一个进程,此进程由 Dockerfile 的 CMD 或 ENTRYPOINT 指定。如果进程退出时返回码非零,则认为容器发生故障,Kubernetes 就会根据 restartPolicy
重启容器。
Pod 的重启策略
Kubernetes 中定义了如下三种重启策略,可以通过spec.restartPolicy字段在 Pod 定义中进行设置。
- Always表示一直重启,这也是默认的重启策略。Kubelet 会定期查询容器的状态,一旦某个容器处于退出状态,就对其执行重启操作
- OnFailure 表示只有在容器异常退出,即退出码不为 0 时,才会对其进行重启操作
- Never 表示从不重启
pod重启策略为OnFailure,正常情况下pod运行完退出之后状态为Completed
[root@k8s-master ~]# cat restart-policy-never.yml
apiVersion: v1
kind: Pod
metadata:
name: restart-policy-pod
namespace: default
labels:
app: busybox
annotations:
version: Onfailure
purpose: demo
spec:
containers:
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","sleep 10"]
restartPolicy: Never
[root@k8s-master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
restart-policy-pod 0/1 Completed 0 20s
注:在 Pod 中设置的重启策略适用于 Pod 内的所有容器。下面我们模拟一个容器发生故障的场景,Pod 配置文件如下:
[root@k8s-master ~]# cat restart-policy-failure.yml
apiVersion: v1
kind: Pod
metadata:
name: restart-policy-pod
namespace: default
labels:
app: busybox
annotations:
version: latest
purpose: demo
spec:
containers:
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","sleep 10,exit 1"]
restartPolicy: OnFailure
- Pod 的
restartPolicy
设置为OnFailure
,默认为Always
-
sleep 10; exit 1
模拟容器启动 10 秒后发生故障。
执行 kubectl apply
创建 Pod,命名为 healthcheck
。
[root@k8s-master ~]# kubectl apply -f restart-policy-failure.yml
pod/restart-policy-pod created
过几分钟查看 Pod 的状态:
[root@k8s-master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
restart-policy-pod 0/1 CrashLoopBackOff 5 4m
可看到容器当前已经重启了 5 次。
虽然我们可以设置一些重启策略,确保容器异常退出时可以重启。但是对于运行中的容器,是不是就意味着容器内的服务正常了呢?
- 比如某些 Java 进程启动速度非常慢,在容器启动阶段其实是无法提供服务的,虽然这个时候该容器是处于运行状态。
- 再比如,有些服务的进程发生阻塞,导致无法对外提供服务,这个时候容器对外还是显示为运行态。
那么我们该如何解决此类问题呢?有没有一些方法,比如可以通过一些周期性的检查,来确保容器中运行的业务没有任何问题。
在上面的例子中,容器进程返回值非零,Kubernetes 则认为容器发生故障,需要重启。但有不少情况是发生了故障,但进程并不会退出。比如访问 Web 服务器时显示 500 内部错误,可能是系统超载,也可能是资源死锁,此时 httpd 进程并没有异常退出,在这种情况下重启容器可能是最直接最有效的解决方案,那我们如何利用 Health Check 机制来处理这类场景呢?
答案就是 Liveness 探测,我们下一一篇博客介绍。