一、Pod探针基础

1.1 Pod的三种探针

种类 说明
startupProbe Kubernetes1.16 新加的探测方式,用于判断容器内的应用程序是否已经启动。如果 配置了startupProbe,就会先禁用其他探测,直到它成功为止。如果探测失败,Kubelet 会杀死容器,之后根据重启策略进行处理,如果探测成功,或没有配置 startupProbe, 则状态为成功,之后就不再探测。
livenessProbe 用于探测容器是否在运行,如果探测失败,kubelet 会“杀死”容器并根据重启策略 进行相应的处理。如果未指定该探针,将默认为 Success
readinessProbe 一般用于探测容器内的程序是否健康,即判断容器是否为就绪(Ready)状态。如果是,则可以处理请求,反之 Endpoints Controller 将从所有的 Service 的 Endpoints 中删除此容器所在Pod的IP地址。如果未指定,将默认为Success

livenessProbe和startupProbe二者区别

  • startupProbe只探测一次,而 livenessProbe循环探测
  • startupProbe用于启动慢(大于30s)的情况下使用
  • startupProbe是在容器刚开始启动时进行检测

1.2 Pod探针的实现方式

使用探针来检查容器有四种不同的方法。 每个探针都必须准确定义为这四种机制中的一种:

实现方式 说明
Exec 在容器内执行一个指定的命令,如果命令返回值为0,则认为容器健康
TCPSocket 通过TCP连接检查容器指定的端口,如果端口开放,则认为容器健康
HTTPGet(最可靠) 对指定的URL进行Get请求,如果状态码在200~400(不包括400) 之间,则认为容器健康
gRPC 1.24版本开始出现,使用gRPC执行一个远程过程调用。 目标应该实现gRPC健康检查。 如果响应的状态是 "SERVING",则认为诊断成功。 gRPC 探针是一个 Alpha 特性,只有在你启用了 "GRPCContainerProbe" 特性门控时才能使用。

1.3 Pod探针的探测结果

每次探测都将获得以下三种结果之一:

种类 说明
success 容器通过了诊断
failure 容器未通过诊断
unknown 诊断失败,因此不会采取任何行动

二、零宕机发布服务实践

参考链接:配置存活、就绪和启动探针

1.模拟没有配置健康检查

(1)创建一个没有探针的 Pod

$ vim nginx01.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
    command:
    - sh
    - -c
    - sleep 25; nginx -g "daemon off;"
    imagePullPolicy: Always
  restartPolicy: OnFailure

(2)创建Pod

 $ k create -f nginx01.yml

(3)查看pod分配IP

$ k get po nginx -owide
NAME                            READY   STATUS    RESTARTS       AGE     IP               NODE           NOMINATED NODE   READINESS GATES
nginx                           1/1     Running   0              16s     172.25.244.201   k8s-master01   <none>           <none>

(4)测试pod分配IP

$ curl 172.25.244.201
curl: (7) Failed connect to 172.25.244.201:80; Connection refused

上面因为pod没有启动成功,导致pod分配IP测试失败

(5)等待25s后,Pod完全启动成功,再次测试pod分配IP,发现状态码为200,代表成功

$ curl -I 172.25.244.201 2>/dev/null | head -1 | awk '{print $2}'
200

2.配置健康检查-livenessProbe和readinessProbe

(1)定义一个新的yaml文件

$ vim nginx.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
    readinessProbe:
      httpGet:
        path: /index.html
        port: 80
        scheme: HTTP
      initialDelaySeconds: 10
      timeoutSeconds: 2
      periodSeconds: 5
      successThreshold: 1
      failureThreshold: 2
    livenessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 10
      timeoutSeconds: 2
      periodSeconds: 5
      successThreshold: 1
      failureThreshold: 2
    command:
    - sh
    - -c
    - sleep 25; nginx -g "daemon off;"
  restartPolicy: OnFailure

上面参数说明:

  • initialDelaySeconds:容器启动后要等待多少秒后才启动启动、存活和就绪探针, 默认是 0 秒,最小值是 0。
  • periodSeconds:执行探测的时间间隔(单位是秒)。默认是 10 秒。最小值是 1。
  • timeoutSeconds:探测的超时后等待多少秒。默认值是 1 秒。最小值是 1。
  • successThreshold:探针在失败后,被视为成功的最小连续成功数。默认值是 1。 存活和启动探测的这个值必须是 1。最小值是 1。
  • failureThreshold:探针连续失败了 failureThreshold 次之后, Kubernetes 认为总体上检查已失败:容器状态未就绪、不健康、不活跃。 对于启动探针或存活探针而言,如果至少有 failureThreshold 个探针已失败, Kubernetes 会将容器视为不健康并为这个特定的容器触发重启操作。 kubelet 会考虑该容器的 terminationGracePeriodSeconds 设置。 对于失败的就绪探针,kubelet 继续运行检查失败的容器,并继续运行更多探针; 因为检查失败,kubelet 将 Pod 的 Ready 状况设置为 false
  • successThreshold: 探针成功了 successThreshold 次之后, Kubernetes 认为总体上检查已失败:容器状态就绪、健康、活跃。

(2)创建Pod

 $ k create -f nginx.yml

(3)查看pod

$ k get po nginx -owide
NAME    READY   STATUS    RESTARTS   AGE   IP              NODE           NOMINATED NODE   READINESS GATES
nginx   0/1     Running   0          15s   172.18.195.10   k8s-master03   <none>           <none>

此时pod的状态虽然为Running,但是READY为0/1

(4)等待10s左右继续查看Pod,并测试Pod分配IP。此时Pod完全建立

$ k get po nginx
NAME    READY   STATUS    RESTARTS      AGE
nginx   1/1     Running   3 (33s ago)   2m49s

$ curl -I 172.18.195.10 2>/dev/null | head -1 | awk '{print $2}'
200

3.配置健康检查-startupProbe

有时候,会有一些现有的应用在启动时需要较长的初始化时间。这里可能会有人想到设置固定的探测参数,但是如果只是设置不变的探测参数,当Pod发生故障,等待时间过长导致"无法容忍"。 要这种情况下,若要不影响对死锁作出快速响应的探测,设置存活探测参数是要技巧的。技巧就是使用相同的命令来设置启动探测,针对 HTTP 或 TCP 检测,可以通过将 failureThreshold * periodSeconds 参数设置为足够长的时间来应对糟糕情况下的启动时间。针对这种情况,就出现了startupProbe

下面介绍一下配置健康检查-startupProbe:

(1)定义一个新的yaml文件

$ vim nginx.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
    startupProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 2
      timeoutSeconds: 2
      periodSeconds: 5
      successThreshold: 1
      failureThreshold: 20
    readinessProbe:
      httpGet:
        path: /index.html
        port: 80
        scheme: HTTP
      initialDelaySeconds: 2
      timeoutSeconds: 2
      periodSeconds: 5
      successThreshold: 1
      failureThreshold: 2
    livenessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 2
      timeoutSeconds: 2
      periodSeconds: 5
      successThreshold: 1
      failureThreshold: 2
    command:
    - sh
    - -c
    - sleep 30; nginx -g "daemon off;"

上面参数说明:

  • initialDelaySeconds:容器启动后要等待多少秒后才启动启动、存活和就绪探针, 默认是 0 秒,最小值是 0。
  • periodSeconds:执行探测的时间间隔(单位是秒)。默认是 10 秒。最小值是 1。
  • timeoutSeconds:探测的超时后等待多少秒。默认值是 1 秒。最小值是 1。
  • successThreshold:探针在失败后,被视为成功的最小连续成功数。默认值是 1。 存活和启动探测的这个值必须是 1。最小值是 1。
  • failureThreshold:探针连续失败了 failureThreshold 次之后, Kubernetes 认为总体上检查已失败:容器状态未就绪、不健康、不活跃。 对于启动探针或存活探针而言,如果至少有 failureThreshold 个探针已失败, Kubernetes 会将容器视为不健康并为这个特定的容器触发重启操作。 kubelet 会考虑该容器的 terminationGracePeriodSeconds 设置。 对于失败的就绪探针,kubelet 继续运行检查失败的容器,并继续运行更多探针; 因为检查失败,kubelet 将 Pod 的 Ready 状况设置为 false
  • successThreshold: 探针成功了 successThreshold 次之后, Kubernetes 认为总体上检查已失败:容器状态就绪、健康、活跃。

(2)创建Pod

 $ k create -f nginx.yml

(3)查看pod状态,初始时READY为0/1,状态为Running

$ k get po nginx
NAME                            READY   STATUS    RESTARTS       AGE
nginx                           0/1     Running   0              5s

(4)等待30s左右再次查看pod状态,初始时READY为1/1,状态为Running

$ k get po nginx
NAME                            READY   STATUS    RESTARTS       AGE
nginx                           1/1     Running   0              40s

当然我们也可以通过kubectl describe查看重启次数,这里因为我们设置的睡眠时间为30s,探测时间为5s,所以大概在第6次Pod会完全起来。

$ k describe po nginx

查看重启次数