重启策略
- Always:当容器终止退出,总是重启容器,默认策略
- OnFailure:当容器异常退出(退出状态码非0)时,才重启容器
- Never:当容器终止退出,从不重启容器
查看pod的重启策略
# 查看pod,以yaml格式输出
kubectl get pods test-pod1 -o yaml
# 找到restartPolicy字段,就是重启策略
restartPolicy: Always
健康检查有以下3种类型:
健康检查是检查容器里面的服务是否正常
- livenessProbe(存活探测):如果检查失败,将杀死容器,根据pod的restartPolicy来操作。
- readinessProbe(就绪探测):如果检查失败,k8s会把Pod从service endpoints中剔除
- startupProbe(启动探测):检查成功才由存活检查接手,用于保护慢启动容器
支持以下三种检查方法:
- httpGet:发起HTTP请求,返回200-400范围状态码为成功。
- exec:执行Shell命令返回状态码是0为成功。
- tcpSocket:发起TCP Socket建立成功。
案例实战
- livenessProbe(存活探针):使用exec的方式(执行Shell命令返回状态码是0则为成功)
apiVersion: v1 kind: Namespace metadata: name: test-a --- apiVersion: apps/v1 kind: Deployment metadata: name: goweb-demo namespace: test-a spec: replicas: 10 selector: matchLabels: app: goweb-demo template: metadata: labels: app: goweb-demo spec: containers: - name: goweb-demo image: 192.168.11.247/web-demo/goweb-demo:20221229v3 livenessProbe: exec: command: - ls - /opt/goweb-demo/runserver initialDelaySeconds: 5 periodSeconds: 5 --- apiVersion: v1 kind: Service metadata: name: goweb-demo namespace: test-a spec: ports: - port: 80 protocol: TCP targetPort: 8090 selector: app: goweb-demo type: NodePort
periodSeconds 字段指定了 kubelet 应该每 5 秒执行一次存活探测,initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 5 秒,kubelet 在容器内执行命令 ls /opt/goweb-demo/runserver 来进行探测。 如果命令执行成功并且返回值为 0,kubelet 就会认为这个容器是健康存活的。 如果这个命令返回非 0 值,kubelet 会杀死这个容器并重新启动它。
验证存活检查的效果
# 查看某个pod的里的容器, kubectl get pods goweb-demo-686967fd56-556m9 -n test-a -o jsonpath={.spec.containers[*].name} # 进入某个pod里的容器 kubectl exec -it goweb-demo-686967fd56-556m9 -c goweb-demo -n test-a -- bash # 进入容器后,手动删除掉runserver可执行文件,模拟故障 rm -rf /opt/goweb-demo/runserver # 查看Pod详情(在输出结果的最下面,有信息显示存活探针失败了,这个失败的容器被杀死并且被重建了。) kubectl describe pod goweb-demo-686967fd56-556m9 -n test-a Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning Unhealthy 177m (x6 over 3h59m) kubelet Liveness probe failed: ls: cannot access '/opt/goweb-demo/runserver': No such file or directory # 一旦失败的容器恢复为运行状态,RESTARTS 计数器就会增加 1 tantianran@test-b-k8s-master:~$ kubectl get pods -n test-a NAME READY STATUS RESTARTS AGE goweb-demo-686967fd56-556m9 1/1 Running 1 (22s ago) 13m # RESTARTS字段加1, goweb-demo-686967fd56-8hzjb 1/1 Running 0 13m ... 2. livenessProbe(存活探针):使用 httpGet 请求的方式检查uri path是否正常 apiVersion: v1 kind: Namespace metadata: name: test-a --- apiVersion: apps/v1 kind: Deployment metadata: name: goweb-demo namespace: test-a spec: replicas: 10 selector: matchLabels: app: goweb-demo template: metadata: labels: app: goweb-demo spec: containers: - name: goweb-demo image: 192.168.11.247/web-demo/goweb-demo:20221229v3 livenessProbe: httpGet: path: /login port: 8090 httpHeaders: - name: Custom-Header value: Awesome initialDelaySeconds: 3 periodSeconds: 3 --- apiVersion: v1 kind: Service metadata: name: goweb-demo namespace: test-a spec: ports: - port: 80 protocol: TCP targetPort: 8090 selector: app: goweb-demo type: NodePort
在这个配置文件中,你可以看到 Pod 也只有一个容器。 periodSeconds 字段指定了 kubelet 每隔 3 秒执行一次存活探测。 initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 3 秒。 kubelet 会向容器内运行的服务(服务在监听 8090 端口)发送一个 HTTP GET 请求来执行探测。 如果服务器上 /login 路径下的处理程序返回成功代码,则 kubelet 认为容器是健康存活的。 如果处理程序返回失败代码,则 kubelet 会杀死这个容器并将其重启。返回大于或等于 200 并且小于 400 的任何代码都表示成功,其它返回代码都表示失败。
验证效果
# 进入容器删除静态文件,模拟故障 kubectl exec -it goweb-demo-586ff85ddb-4646k -c goweb-demo -n test-a -- bash rm -rf login.html # 查看pod的log kubectl logs goweb-demo-586ff85ddb-4646k -n test-a 2023/01/12 06:45:19 [Recovery] 2023/01/12 - 06:45:19 panic recovered: GET /login HTTP/1.1 Host: 10.244.222.5:8090 Connection: close Accept: */* Connection: close Custom-Header: Awesome User-Agent: kube-probe/1.25 html/template: "login.html" is undefined /root/my-work-space/pkg/mod/github.com/gin-gonic/gin@v1.8.2/context.go:911 (0x8836d1) /root/my-work-space/pkg/mod/github.com/gin-gonic/gin@v1.8.2/context.go:920 (0x88378c) /root/my-work-space/src/goweb-demo/main.go:10 (0x89584e) # 查看pod详情 kubectl describe pod goweb-demo-586ff85ddb-4646k -n test-a Warning Unhealthy 34s (x3 over 40s) kubelet Liveness probe failed: HTTP probe failed with statuscode: 500 # 状态码为500 # 恢复后查看Pod,RESTARTS计数器已经增1 kubectl get pod goweb-demo-586ff85ddb-4646k -n test-a NAME READY STATUS RESTARTS AGE goweb-demo-586ff85ddb-4646k 1/1 Running 1 (80s ago) 5m39s 3. readinessProbe(就绪探针)结合livenessProbe(存活探针)探测tcp端口:
第三种类型的存活探测是使用 TCP 套接字。 使用这种配置时,kubelet 会尝试在指定端口和容器建立套接字链接。 如果能建立连接,这个容器就被看作是健康的,如果不能则这个容器就被看作是有问题的。
apiVersion: v1 kind: Namespace metadata: name: test-a --- apiVersion: apps/v1 kind: Deployment metadata: name: goweb-demo namespace: test-a spec: replicas: 10 selector: matchLabels: app: goweb-demo template: metadata: labels: app: goweb-demo spec: containers: - name: goweb-demo image: 192.168.11.247/web-demo/goweb-demo:20221229v3 readinessProbe: tcpSocket: port: 8090 initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: tcpSocket: port: 8090 initialDelaySeconds: 15 periodSeconds: 20 --- apiVersion: v1 kind: Service metadata: name: goweb-demo namespace: test-a spec: ports: - port: 80 protocol: TCP targetPort: 8090 selector: app: goweb-demo type: NodePort
TCP 检测的配置和 HTTP 检测非常相似。 这个例子同时使用就绪和存活探针。kubelet 会在容器启动 5 秒后发送第一个就绪探针。 探针会尝试连接 goweb-demo 容器的 8090 端口。 如果探测成功,这个 Pod 会被标记为就绪状态,kubelet 将继续每隔 10 秒运行一次探测。除了就绪探针,这个配置包括了一个存活探针。 kubelet 会在容器启动 15 秒后进行第一次存活探测。 与就绪探针类似,存活探针会尝试连接 goweb-demo 容器的 8090 端口。 如果存活探测失败,容器会被重新启动。
验证效果
# 进入容器后,杀掉goweb-demo的进程 kubectl exec -it goweb-demo-5d7d55f846-vm2kc -c goweb-demo -n test-a -- bash root@goweb-demo-5d7d55f846-vm2kc:/opt/goweb-demo# ps -aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 2476 576 ? Ss 07:23 0:00 /bin/sh -c /opt/goweb-demo/runserver root@goweb-demo-5d7d55f846-vm2kc:/opt/goweb-demo# kill -9 1 # 查看pod详情,已经发出警告 kubectl describe pod goweb-demo-5d7d55f846-vm2kc -n test-a Warning Unhealthy 16s kubelet Readiness probe failed: dial tcp 10.244.240.48:8090: connect: connection refused Warning BackOff 16s kubelet Back-off restarting failed container # 查看pod,RESTARTS计数器已经增加为2,因为有两个探针 tantianran@test-b-k8s-master:~$ kubectl get pod -n test-a NAME READY STATUS RESTARTS AGE goweb-demo-5d7d55f846-vm2kc 1/1 Running 2 (2m55s ago) 12m 4. 使用startupProbe(启动探针)保护慢启动容器
有一种情景是这样的,某些应用在启动时需要较长的初始化时间。要这种情况下,若要不影响对死锁作出快速响应的探测,设置存活探测参数是要技巧的。 技巧就是使用相同的命令来设置启动探测,针对 HTTP 或 TCP 检测,可以通过将 failureThreshold * periodSeconds 参数设置为足够长的时间来应对糟糕情况下的启动时间。
apiVersion: v1 kind: Namespace metadata: name: test-a --- apiVersion: apps/v1 kind: Deployment metadata: name: goweb-demo namespace: test-a spec: replicas: 10 selector: matchLabels: app: goweb-demo template: metadata: labels: app: goweb-demo spec: containers: - name: goweb-demo image: 192.168.11.247/web-demo/goweb-demo:20221229v3 livenessProbe: httpGet: path: /login port: 8090 failureThreshold: 1 periodSeconds: 10 startupProbe: httpGet: path: /login port: 8090 failureThreshold: 30 periodSeconds: 10 --- apiVersion: v1 kind: Service metadata: name: goweb-demo namespace: test-a spec: ports: - port: 80 protocol: TCP targetPort: 8090 selector: app: goweb-demo type: NodePort
上面的例子,应用程序将会有最多 5 分钟(30 * 10 = 300s)的时间来完成其启动过程。 一旦启动探测成功一次,存活探测任务就会接管对容器的探测,对容器死锁作出快速响应。 如果启动探测一直没有成功,容器会在 300 秒后被杀死,并且根据 restartPolicy 来执行进一步处置。