我是 LEE,老李,一个在 IT 行业摸爬滚打 16 年的技术老兵。

事件布景

因为 k8s 中采用很多的异步机制、以及多种对象联系规划上的解耦,当运用实例数 添加/删去、或许运用版本产生变化触发翻滚晋级时,体系并不能确保运用相关的 service、ingress 装备总是及时能完结刷新。在一些情况下,往往仅仅新的 Pod 完结自身初始化,体系尚未完结 Endpoint、负载均衡器等外部可达的拜访信息刷新,老得 Pod 就当即被删去,最终造成服务时刻短的额不可用,这关于出产来说是不可接受的,所以 k8s 就加入了一些存活性探针:StartupProbe、LivenessProbe、ReadinessProbe。

技术探究

POD 状况

Pod 常见的状况

  • Pending:挂起,咱们在恳求创立 pod 时,条件不满意,调度没有完结,没有任何一个节点能满意调度条件。现已创立了可是没有合适它运转的节点叫做挂起,这其中也包括集群为容器创立网络,或许下载镜像的过程。
  • Running:Pod 内一切的容器都现已被创立,且至少一个容器正在处于运转状况、正在发动状况或许重启状况。
  • Succeeded:Pod 中所以容器都履行成功后退出,而且没有处于重启的容器。
  • Failed:Pod 中所以容器都已退出,可是至少还有一个容器退出时为失利状况。
  • Unknown:未知状况,所谓 pod 是什么状况是 apiserver 和运转在 pod 节点的 kubelet 进行通信获取状况信息的,假如节点之上的 kubelet 自身出毛病,那么 apiserver 就连不上 kubelet,得不到信息了,就会看 Unknown

K8S 三种探针 ReadinessProbe、LivenessProbe和StartupProbe 之探索

###Pod 重启战略

  • Always: 只需容器失效退出就重新发动容器。
  • OnFailure: 当容器以非正常(异常)退出后才主动重新发动容器。
  • Never: 无论容器状况怎么,都不重新发动容器。

###Pod 常见状况转化场景

K8S 三种探针 ReadinessProbe、LivenessProbe和StartupProbe 之探索

探针简介

K8S 供给了 3 种探针:

  • ReadinessProbe
  • LivenessProbe
  • StartupProbe(这个 1.16 版本添加的)

探针存在的意图

在 Kubernetes 中 Pod 是最小的计算单元,而一个 Pod 又由多个容器组成,相当于每个容器便是一个运用,运用在运转期间,可能因为某也意外情况致使程序挂掉。

那么怎么监控这些容器状况稳定性,确保服务在运转期间不会产生问题,产生问题后进行重启等机制,就成为了重中之重的作业,考虑到这点 kubernetes 推出了活性探针机制。

有了存活性探针能确保程序在运转中假如挂掉可以主动重启,可是还有个常常遇到的问题,比如说,在 Kubernetes 中发动 Pod,显现分明 Pod 现已发动成功,且能拜访里边的端口,可是却回来错误信息。还有便是在履行翻滚更新时候,总会呈现一段时刻,Pod 对外供给网络拜访,可是拜访却产生 404,这两个原因,都是因为 Pod 现已成功发动,可是 Pod 的的容器中运用程序还在发动中导致,考虑到这点 Kubernetes 推出了安排妥当性探针机制。

  1. LivenessProbe: 存活性探针,用于判别容器是不是健康,假如不满意健康条件,那么 Kubelet 将依据 Pod 中设置的 restartPolicy (重启战略)来判别,Pod 是否要进行重启操作。LivenessProbe 依照装备去勘探 ( 进程、或许端口、或许指令履行后是否成功等等),来判别容器是不是正常。假如勘探不到,代表容器不健康(可以装备接连多少次失利才记为不健康),则 kubelet 会杀掉该容器,并依据容器的重启战略做相应的处理。假如未装备存活探针,则默许容器发动为经过(Success)状况。即探针回来的值永远是 Success。即 Success 后 pod 状况是 RUNING

  2. ReadinessProbe: 安排妥当性探针,用于判别容器内的程序是否存活(或许说是否健康),只要程序(服务)正常, 容器开端对外供给网络拜访(发动完结并安排妥当)。容器发动后依照 ReadinessProbe 装备进行勘探,无问题后成果为成功即状况为 Success。pod 的 READY 状况为 true,从 0/1 变为 1/1。假如失利继续为 0/1,状况为 false。若未装备安排妥当探针,则默许状况容器发动后为 Success。关于此 pod、此 pod 相关的 Service 资源、EndPoint 的联系也将基于 Pod 的 Ready 状况进行设置,假如 Pod 运转过程中 Ready 状况变为 false,则体系主动从 Service 资源 相关的 EndPoint 列表中去除此 pod,届时 service 资源接收到 GET 恳求后,kube-proxy 将必定不会把流量引进此 pod 中,经过这种机制就能避免将流量转发到不可用的 Pod 上。假如 Pod 恢复为 Ready 状况。将再会被加回 Endpoint 列表。kube-proxy 也将有概率经过负载机制会引进流量到此 pod 中。

  3. StartupProbe: StartupProbe 探针,主要处理在复杂的程序中 ReadinessProbe、LivenessProbe 探针无法更好的判别程序是否发动、是否存活。从而引进 StartupProbe 探针为 ReadinessProbe、LivenessProbe 探针服务。

(★) ReadinessProbe 与 LivenessProbe 的差异

  • ReadinessProbe 当检测失利后,将 Pod 的 IP:Port 从对应的 EndPoint 列表中删去。
  • LivenessProbe 当检测失利后,将杀死容器并依据 Pod 的重启战略来决定作出对应的措施。

(★) StartupProbe 与 ReadinessProbe、LivenessProbe 的差异

假如三个探针同时存在,先履行 StartupProbe 探针,其他两个探针将会被暂时禁用,直到 pod 满意 StartupProbe 探针装备的条件,其他 2 个探针发动,假如不满意依照规则重启容器。

别的两种探针在容器发动后,会依照装备,直到容器消亡才中止勘探,而 StartupProbe 探针仅仅在容器发动后依照装备满意一次后,不在进行后续的勘探。

正确的 ReadinessProbe 与 LivenessProbe 运用方法

LivenessProbe 和 ReadinessProbe 两种探针都支撑下面三种勘探办法:

  • ExecAction:在容器中履行指定的指令,假如履行成功,退出码为 0 则勘探成功。
  • HTTPGetAction:经过容器的 IP 地址、端口号及途径调用 HTTP Get 办法,假如呼应的状况码大于等于 – 200 且小于 400,则以为容器 健康。
  • TCPSocketAction:经过容器的 IP 地址和端口号履行 TCP 检 查,假如可以树立 TCP 衔接,则标明容器健康。

探针勘探成果有以下值:

  • Success:表明经过检测。
  • Failure:表明未经过检测。
  • Unknown:表明检测没有正常进行。

LivenessProbe 和 ReadinessProbe 两种探针的相关属性 探针(Probe)有许多可选字段,可以用来更加准确的操控 Liveness 和 Readiness 两种探针的行为(Probe):

  • initialDelaySeconds:容器发动后要等候多少秒后就探针开端作业,单位“秒”,默许是 0 秒,最小值是 0
  • periodSeconds:履行勘探的时刻距离(单位是秒),默许为 10s,单位“秒”,最小值是 1
  • timeoutSeconds:探针履行检测恳求后,等候呼应的超时时刻,默许为 1s,单位“秒”,最小值是 1
  • successThreshold:探针检测失利后以为成功的最小衔接成功次数,默许为 1s,在 Liveness 探针中有必要为 1s,最小值为 1s。
  • failureThreshold:勘探失利的重试次数,重试必定次数后将以为失利,在 readiness 探针中,Pod 会被标记为未安排妥当,默许为 3s,最小值为 1s

Tips:initialDelaySeconds 在 ReadinessProbe 其实可以不用装备,不装备默许 pod 刚发动,开端进行 ReadinessProbe 勘探,但那有怎么样,除了 StartupProbe,ReadinessProbe、LivenessProbe 运转在 pod 的整个生命周期,刚发动的时候 ReadinessProbe 检测失利了,只不过显现 READY 状况一直是 0/1,ReadinessProbe 失利并不会导致重启 pod,只要 StartupProbe、LivenessProbe 失利才会重启 pod。而比及多少 s 后,真正服务发动后,查看 success 成功后,READY 状况天然正常

正确的 StartupProbe 运用方法

StartupProbe 探针支撑下面三种勘探办法:

  • ExecAction:在容器中履行指定的指令,假如履行成功,退出码为 0 则勘探成功。
  • HTTPGetAction:经过容器的 IP 地址、端口号及途径调用 HTTP Get 办法,假如呼应的状况码大于等于 200 且小于 400,则以为容器 健康。
  • TCPSocketAction:经过容器的 IP 地址和端口号履行 TCP 检 查,假如可以树立 TCP 衔接,则标明容器健康。

探针勘探成果有以下值:

  • Success:表明经过检测。
  • Failure:表明未经过检测。
  • Unknown:表明检测没有正常进行。

StartupProbe 探针属性

  • initialDelaySeconds:容器发动后要等候多少秒后就探针开端作业,单位“秒”,默许是 0 秒,最小值是 0
  • periodSeconds:履行勘探的时刻距离(单位是秒),默许为 10s,单位“秒”,最小值是 1
  • timeoutSeconds:探针履行检测恳求后,等候呼应的超时时刻,默许为 1s,单位“秒”,最小值是 1
  • successThreshold:探针检测失利后以为成功的最小衔接成功次数,默许为 1s,在 Liveness 探针中有必要为 1s,最小值为 1s。
  • failureThreshold:勘探失利的重试次数,重试必定次数后将以为失利,在 readiness 探针中,Pod 会被标记为未安排妥当,默许为 3s,最小值为 1s

Tips:在 StartupProbe 履行完之后,其他 2 种探针的一切装备才全部发动,相当于容器刚发动的时候,所以其他 2 种探针假如装备了 initialDelaySeconds,主张不要给太长。

运用举例

LivenessProbe 探针运用示例

1. 经过 exec 方法做健康勘探

[root@localhost ~]# vim liveness-exec.yaml
apiVersion: v1
kind: Pod
metadata:
    name: liveness-exec
    labels:
        app: liveness
spec:
    containers:
        - name: liveness
          image: busybox
          args: #创立测验探针勘探的文件
              - /bin/sh
              - -c
              - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
          LivenessProbe:
              initialDelaySeconds: 10 #推迟检测时刻
              periodSeconds: 5 #检测时刻距离
              exec: #运用指令查看
                  command: #指令,类似于运转指令sh
                      - cat #sh 后的第一个内容,直到需要输入空格,变成下一行
                      - /tmp/healthy #因为不能输入空格,需要别的声明,成果为sh cat"空格"/tmp/healthy

思路收拾:

容器在初始化后,履行(/bin/sh -c “touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600″)首要创立一个 /tmp/healthy 文件,然后履行睡觉指令,睡觉 30 秒,到时刻后履行删去 /tmp/healthy 文件指令。

而设置的存活探针检检测方法为履行 shell 指令,用 cat 指令输出 healthy 文件的内容,假如能成功履行这条指令一次(默许 successThreshold:1),存活探针就以为勘探成功,因为没有装备(failureThreshold、timeoutSeconds),所以履行(cat /tmp/healthy)并只等候 1s,假如 1s 内履行后回来失利,勘探失利。

在前 30 秒内,因为文件存在,所以存活探针勘探时履行 cat /tmp/healthy 指令成功履行。30 秒后 healthy 文件被删去,所以履行指令失利,Kubernetes 会依据 Pod 设置的重启战略来判别,是否重启 Pod。

2. 经过 HTTP 方法做健康勘探

[root@localhost ~]# vi liveness-http.yaml
apiVersion: v1
kind: Pod
metadata:
    name: liveness-http
    labels:
        test: liveness
spec:
    containers:
        - name: liveness
          image: test.com/test-http-prober:v0.0.1
          LivenessProbe:
              failureThreshold: 5 #检测失利5次表明未安排妥当
              initialDelaySeconds: 20 #推迟加载时刻
              periodSeconds: 10 #重试时刻距离
              timeoutSeconds: 5 #超时时刻设置
              successThreshold: 2 #查看成功为2次表明安排妥当
              httpGet:
                  scheme: HTTP
                  port: 8081
                  path: /ping

思路收拾:

在 pod 发动后,初始化等候 20s 后,LivenessProbe 开端作业,去恳求 http://Pod_IP:8081/ping 接口,类似于 curl -I http://Pod_IP:8081/ping 接口,考虑到恳求会有推迟(curl -I 后一直呈现假死状况),所以给这次恳求操作一直继续 5s,假如 5s 内拜访回来数值在>=200 且<=400 代表第一次检测 success,假如是其他的数值,或许 5s 后还是假死状况,履行类似(ctrl+c)中断,并反回 failure 失利。

等候 10s 后,再一次的去恳求 http://Pod_IP:8081/ping 接口。假如有接连的 2 次都是 success,代表无问题。假如期间有接连的 5 次都是 failure,代表有问题,直接重启 pod,此操作会伴随 pod 的整个生命周期。

Tips

Http Get 勘探方法有如下可选的操控字段:

  • scheme: 用于衔接 host 的协议,默许为 HTTP。
  • host:要衔接的主机名,默许为 Pod IP,可以在 Http Request headers 中设置 host 头部。
  • port:容器上要拜访端口号或称号。
  • path:http 服务器上的拜访 URI。
  • httpHeaders:自定义 HTTP 恳求 headers,HTTP 允许重复 headers。

3. 经过 TCP 方法做健康勘探

[root@localhost ~]# vi liveness-tcp.yaml
apiVersion: v1
kind: Pod
metadata:
    name: liveness-tcp
    labels:
        app: liveness
spec:
    containers:
        - name: liveness
          image: nginx
          LivenessProbe:
              initialDelaySeconds: 15
              periodSeconds: 20
              tcpSocket:
                  port: 80

思路收拾:

TCP 查看方法和 HTTP 查看方法非常相似,在容器发动 initialDelaySeconds 参数设定的时刻后,kubelet 将发送第一个 LivenessProbe 探针,尝试衔接容器的 80 端口,类似于 telnet 80 端口。 每隔 20 秒(periodSeconds)做勘探,假如衔接失利则将杀死 Pod 重启容器。

ReadinessProbe 探针运用示例

ReadinessProbe 探针运用方法和 LivenessProbe 探针勘探办法相同,也是支撑三种,仅仅一个是用于勘探运用的存活,一个是判别是否对外供给流量的条件。

[root@localhost ~]# vim readiness-exec.yaml
apiVersion: v1
kind: Pod
metadata:
    name: readiness-exec
    labels:
        app: readiness-exec
spec:
    containers:
        - name: readiness-exec
          image: busybox
          args: #创立测验探针勘探的文件
              - /bin/sh
              - -c
              - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
          LivenessProbe:
              initialDelaySeconds: 10
              periodSeconds: 5
              exec:
                  command:
                      - cat
                      - /tmp/healthy
---
apiVersion: v1
kind: Pod
metadata:
    name: readiness-http
    labels:
        app: readiness-http
spec:
    containers:
        - name: readiness-http
          image: test.com/test-http-prober:v0.0.1
          ports:
              - name: server
                containerPort: 8080
              - name: management
                containerPort: 8081
          ReadinessProbe:
              initialDelaySeconds: 20
              periodSeconds: 5
              timeoutSeconds: 10
              httpGet:
                  scheme: HTTP
                  port: 8081
                  path: /ping
---
apiVersion: v1
kind: Pod
metadata:
    name: readiness-tcp
    labels:
        app: readiness-tcp
spec:
    containers:
        - name: readiness-tcp
          image: nginx
          LivenessProbe:
              initialDelaySeconds: 15
              periodSeconds: 20
              tcpSocket:
                  port: 80

这里说说 terminationGracePeriodSeconds

terminationGracePeriodSeconds 这个参数非常的重要,具体讲解。请参考我的别的一篇文章《详细解读 Kubernetes 中 Pod 优雅退出,帮你处理大问题》, 里边有详细的解说,我这里说下其他的内容。

Tips: terminationGracePeriodSeconds 不能用于 ReadinessProbe,假如将它运用于 ReadinessProbe 将会被 apiserver 接口所回绝

LivenessProbe:
    httpGet:
        path: /ping
        port: liveness-port
    failureThreshold: 1
    periodSeconds: 30
    terminationGracePeriodSeconds: 30 # 宽限时刻30s

StartupProbe 探针运用示例

[root@localhost ~]# vim startup.yaml
apiVersion: v1
kind: Pod
metadata:
    name: startup
    labels:
        app: startup
spec:
    containers:
        - name: startup
          image: nginx
          StartupProbe:
              failureThreshold: 3 # 失利阈值,接连几次失利才算真失利
              initialDelaySeconds: 5 # 指定的这个秒今后才履行勘探
              timeoutSeconds: 10 # 勘探超时,到了超时时刻勘探还没回来成果说明失利
              periodSeconds: 5 # 每隔几秒来运转这个
              httpGet:
                  path: /test
                  prot: 80

思路收拾:

在容器发动 initialDelaySeconds (5 秒) 参数设定的时刻后,kubelet 将发送第一个 StartupProbe 探针,尝试衔接容器的 80 端口。 假如接连勘探失利没有超越 3 次 (failureThreshold) ,且每次勘探距离为 5 秒 (periodSeconds) 和勘探履行时刻不超越超时时刻 10 秒/每次 (timeoutSeconds),则以为勘探成功,反之勘探失利,kubelet 直接杀死 Pod。

总结

经过对三种探针的探究,咱们可以得到一句话的总结:理解底层结构,可以最大程度在可用性、安全性,继续性等方面让 Pod 到达最佳作业状况。 凡事没有“银弹”,特别对重要的事务需要一个案例一个处理方案,期望这次的剖析能供给给我们开启一个思路之门。