阅读 106

终于对探针下手了

终于对探针下手了

1. kubernetes 健康检查

打造一个完全不出事的容器是不可能的,因此需要对容器进行健康检查,以 check 容器是否处于可用状态。

健康检查可分为进程级健康检查和业务级健康检查两种:

  • 进程级健康检查即检查容器进程是否存活,kubelet 定期通过 docker daemon 获取所有 docker 进程的运行情况,如果发现某个容器未正常运行,则重启该容器。

  • 业务级健康检查是更细粒度的健康检查,试想容器进程处于死锁状态,此时容器是不可用的,但是容器进程是运行的,kubelet 不会重启该容器。针对这种情况 kubernetes 设计了 probe 探针来检查容器是否可用。

probe 又分两种:活性探针(liveness probe)和业务探针(readiness probe)。

1.1 liveness probe

以 livenss probe 为例,在启动容器时执行一段死锁代码如下:

#coding:utf8import threadingimport time

num = 0lock = threading.Lock()

def func(n):
    lock.acquire()    print n    if(n == 5):        print "deadLock"
        raise Exception('deadLock')
    lock.release()if __name__ == "__main__":
    t4 = threading.Thread(target=func, args=(5,))
    t1 = threading.Thread(target=func, args=(8,))
    t2 = threading.Thread(target=func, args=(4,))
    t3 = threading.Thread(target=func, args=(2,))

    t4.start()
    t1.start()
    t2.start()
    t3.start()

启动包含该死锁代码的容器:

$ docker run -it centos_python2:v1 python2 /home/deadLock.py
5
deadLock here
Exception in thread Thread-1:
Traceback (most recent call last):  File "/usr/lib64/python2.7/threading.py", line 805, in __bootstrap_inner
    self.run()  File "/usr/lib64/python2.7/threading.py", line 758, in run
    self.__target(*self.__args, **self.__kwargs)  File "/home/deadLock.py", line 13, in func    raise Exception('Error: deadLock ')Exception: Error: deadLock

此时容器停留在死锁状态,这时候容器是无法正常工作的!

kubernetes 的 liveness probe 通过三种方式对应用进行健康检查:

  1. HTTP GET

  2. Container Exec

  3. TCP Socket

这里仅介绍第二种方式 Container Exec(详细信息看 这里),它通过在容器中检查执行命令的退出码来检查容器应用是否正常,如退出码为 0 则认为容器应用工作正常。如下所示:

[root@chunqiu ~ ]# kubectl exec -it httpd /bin/bash -n cibash-5.0$ /usr/bin/genapik8s --is-alivebash-5.0$ echo $?0bash-5.0$ /usr/bin/genapik8s --is-alive2unknown option: --is-alive2bash-5.0$ echo $?3

这里展示了一个容器应用正常工作的容器,使用 genapik8s 检查容器是否可用。对应的 helm chat 如下:

livenessProbe:
    exec:
      command:
      - /usr/bin/genapik8s
      - --is-alive
    initialDelaySeconds: 15
    periodSeconds: 5
    successThreshold: 1
    failureThreshold: 3

其中,initialDelaySeconds 表示容器启动到执行健康检查的延迟时间,延迟时间的设计是为了容器进程有时间完成必要的初始化工作,而不是在还未启动好之前就被 kubelet 重启了。

同理,将 livenessProbe 应用在前面死锁的容器,容器中执行命令的退出码不为 0,使得 kubelet 发现到该容器无法正常工作,进而重启该容器。

1.2 readiness probe

如果某些容器应用只是暂时性出了问题,而不想 kubelet 对其重启该怎么办呢?kubernetes 提供了 readiness probe 来解决这类问题。类似于 liveness probe,readiness probe 会在容器中执行检查操作,如果检查失败 kubelet 不会重启容器,而是将容器所属的 pod 从 endpoint 列表中删除,这样访问 pod 的请求就会被路由到其它 pod 上。

根据这一特性,可以构造“相同”副本的 pod,一个为 active,一个为 standby。它们都通过 service 建立连接,service 会将请求路由到 active 的 pod,而不会路由到 standby 的 pod。

这里仅以单一副本举例,不深入讨论 active 和 standby pod 的情况。构造带 readiness probe 的 pod:

apiVersion: apps/v1kind: Deploymentmetadata:
  name: readinesstesterspec:
  replicas: 1
  selector:
    matchLabels:
      app: readinessprobe
  template:
    metadata:
      labels:
        app: readinessprobe
    spec:
      containers:
      - name: httpd
        image: docker-httpd:0.2.4
        readinessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 5
          periodSeconds: 5

container 内包含一个 readinessProbe 探针,它会执行命令 cat /tmp/healthy 检查容器是否健康。容器中 healthy 是不存在的,执行会失败。创建 service 如下:

apiVersion: v1kind: Servicemetadata:
  name: readinessservicespec:
  selector:
    app: readinessprobe
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 80

检查 pod 状态:

[root@chunqiu readinessProbe ]# kubectl get pods -o wideNAME                               READY   STATUS             RESTARTS   AGE     IP              NODEreadinesstester-85bbbd7947-dzsm6   0/1     Running            0          3h34m   10.10.44.173    chunqiu-node-2[root@chunqiu readinessProbe ]# kubectl describe pods readinesstester-85bbbd7947-dzsm6...Status:               RunningControlled By:  ReplicaSet/readinesstester-85bbbd7947Containers:
  httpd:
    ...
    State:          Running
      Started:      Sun, 30 May 2021 11:57:21 +0800
    Ready:          False
    Restart Count:  0
    Readiness:      exec [cat /tmp/healthy] delay=5s timeout=1s period=5s #success=1 #failure=3Events:
  Type     Reason     Age                       From     Message
  ----     ------     ----                      ----     -------
  Warning  Unhealthy  3m13s (x2460 over 3h28m)  kubelet  Readiness probe failed: cat: /tmp/healthy: No such file or directory

这里仅列出需要重点关注的信息。从 pod 状态来看, pod 并未 ready,不过 pod 并未被重启,且 pod 是 running 的。进一步查看 service 对应的 pod endpoint 是否存在:

[root@chunqiu readinessProbe ]# kubectl describe service readinessserviceName:              readinessserviceNamespace:         defaultLabels:            <none>Annotations:       <none>Selector:          app=readinessprobeType:              ClusterIPIP:                10.254.194.117Port:              <unset>  8080/TCPTargetPort:        80/TCPEndpoints:Session Affinity:  NoneEvents:            <none>

可以看到未 ready 的 pod endpoints 并未放到 service 中,虽然 pod 有自己的 ip。

2. Deployment 和 replicaSet

这一节我们这么部署 pod 和 service 看看会发生什么。

首先创建不带 readinessProbe 的 pod:

[root@chunqiu readinessProbe ]# kubectl get pods -o wideNAME                              READY   STATUS     RESTARTS   AGE     IP              NODEreadinesstester-cd586b86d-b4n7t   1/1     Running    0          26s     10.10.44.179    chunqiu-node-2[root@chunqiu readinessProbe ]# kubectl describe service readinessserviceName:              readinessserviceNamespace:         defaultLabels:            <none>Annotations:       <none>Selector:          app=readinessprobeType:              ClusterIPIP:                10.254.194.117Port:              <unset>  8080/TCPTargetPort:        80/TCPEndpoints:         10.10.44.179:80Session Affinity:  NoneEvents:            <none>

很正常,接着将 readinessProbe 加到 pod 内,重新配置 pod,查看 pod 状态:

[root@chunqiu readinessProbe ]# kubectl get pods -o wideNAME                               READY   STATUS             RESTARTS   AGE     IP              NODEreadinesstester-85bbbd7947-xj9gv   0/1     Running            0          29s     10.10.44.161    chunqiu-node-2readinesstester-cd586b86d-b4n7t    1/1     Running            0          3m51s   10.10.44.179    chunqiu-node-2

发现有两个名为 readinesstester... 的 pod 存在,且状态还不一致,这是为什么呢?

自上而下通过 Deployment 和 replicatSet 查看 pod 干了什么:

[root@chunqiu readinessProbe ]# kubectl get deployments.appsNAME              READY   UP-TO-DATE   AVAILABLE   AGE
readinesstester   1/1     1            1           5m39s

[root@chunqiu readinessProbe ]# kubectl describe deployments.apps readinesstester...
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  5m48s  deployment-controller  Scaled up replica set readinesstester-cd586b86d to 1
  Normal  ScalingReplicaSet  2m26s  deployment-controller  Scaled up replica set readinesstester-85bbbd7947 to 1

根据 Events 可以看到 deployment-controller scale up 一个 replicaSet readinesstester-85bbbd7947,由这个 replicaSet 接管新的带 readinessProbe pod 的创建:

[root@chunqiu readinessProbe ]# kubectl get replicasets.appsNAME                         DESIRED   CURRENT   READY   AGEreadinesstester-85bbbd7947   1         1         0       9m13sreadinesstester-cd586b86d    1         1         1       12m[root@chunqiu readinessProbe ]# kubectl describe replicasets.apps readinesstester-85bbbd7947Name:           readinesstester-85bbbd7947Replicas:       1 current / 1 desiredPods Status:    1 Running / 0 Waiting / 0 Succeeded / 0 FailedEvents:
  Type    Reason            Age    From                   Message
  ----    ------            ----   ----                   -------
  Normal  SuccessfulCreate  9m24s  replicaset-controller  Created pod: readinesstester-85bbbd7947-xj9gv...

scale up 的 replicaSet 创建出 Pod,该 pod 的状态并未 ready,导致 deployment 的滚动更新策略一直卡在等待新 replicaSet 创建完成这里,因此会出现两个并行的 pod。从这个示例也可以看出 Deployment 是为了应用的更新而设计的。

芝兰生于空谷,不以无人而不芳。


来源https://www.cnblogs.com/xingzheanan/p/14828311.html

文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐