强大的自愈能力是 Kubernetes 这类容器编排引擎的一个重要特性。自愈的默认实现方式是自动重启发生故障的容器。除此之外,用户还可以利用 Liveness 和 Readiness 探测机制设置更精细的健康检查,进而实现如下需求:

  1. 零停机部署。
  2. 避免部署无效的镜像。
  3. 更加安全的滚动升级。

在docker swarm中可以使用命令检查服务是否健全(探测某个目录或者某个文件),来判断是否可以提供正常的服务。

容器运行正常,服务未必正常

默认健康检查

每个容器启动时都会执行一个进程,此进程由 Dockerfile 的 CMD 或 ENTRYPOINT 指定。如果进程退出时返回码非零,则认为容器发生故障,Kubernetes 就会根据 restartPolicy 重启容器。

支持的三种健康检查方式

httpGet: 发送 http 请求,放回 200-400 范围状态码为成功

exec: 执行 shell 命令返回状态码是0为成功

tcpSocket: 发起 TCP Socket 建立成功

模拟故障发生场景

编写启动一个Pod的yml文件

$ vim healthcheck.yml
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: healthcheck
  name: healthcheck
spec:
  restartPolicy: OnFailure
  containers:
  - name: healthcheck
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 10; exit 1   # 模拟该容器10s之后exit 1,故障

运行Pod

[root@node1 ~]# kubectl apply -f healthcheck.yml 
pod/healthcheck created

查看Pod,已经重启了五次,状态为Error,则不再重启

[root@node1 ~]# kubectl get pod healthcheck 
NAME          READY   STATUS   RESTARTS   AGE
healthcheck   0/1     Error    5          6m11s

在这个例子中,容器进程返回值非0,Kubernetes则认为容器发生故障,需要重启。但有不少情况是发生了故障,但进程并不会退出。比如访问 Web 服务器时显示 500 内部错误,可能是系统超载,也可能是资源死锁,此时 httpd 进程并没有异常退出。

在k8s的这种情况下,就可以使用k8s的Health Check机制Liveness探测来处理

Liveness探测

先将之前模拟故障的Pod删除

$ kubectl delete -f healthcheck.yml 
pod "healthcheck" deleted

Liveness(活性检测) 探测让用户可以自定义判断容器是否健康的条件。如果探测失败,Kubernetes 就会重启容器。

exec

修改模拟故障的yml文件如下:

$ vim healthcheck.yml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: healthcheck
  name: healthcheck
spec:
  restartPolicy: OnFailure
  containers:
  - name: healthcheck
    image: busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 6000
    # 创建/tmp/healthy,30s之后将文件删除
    livenessProbe:
      exec:
        command:    # 用来探测文件
        - cat         
        - /tmp/healthy
      initialDelaySeconds: 10  # 容器启动10s之后进行liveness的检测,被叫做探针
      periodSeconds: 5 # 每5s进行一次探测

根据文件中信息得出:

运行容器后创建healthy文件,10s之后使用cat /tmp/healthy进行检测,文件是否存在,15/20/25检测都没有问题,30s时,将healthy文件删除,再检测文件就不在了,Kubernetes默认检测三次失败,就被认为是异常,所以容器就会退出。然后重新创建容器

运行Pod

$ kubectl apply -f healthcheck.yml 
pod/healthcheck created

查看pod

$ kubectl get pod -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
healthcheck   1/1     Running   0          53s   10.244.2.19   node3   <none>           <none>

30s之后再次进行查看,pod已经重启一次

$ kubectl get pod
NAME          READY   STATUS    RESTARTS   AGE
healthcheck   1/1     Running   1          114s

查看pod的事件信息

$ kubectl describe pod healthycheck
...
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Scheduled  2m37s                default-scheduler  Successfully assigned default/healthcheck to node3
  Normal   Pulling    66s (x2 over 2m36s)  kubelet, node3     Pulling image "busybox"
  Normal   Pulled     51s (x2 over 2m19s)  kubelet, node3     Successfully pulled image "busybox"
  Normal   Created    50s (x2 over 2m19s)  kubelet, node3     Created container healthcheck
  Normal   Started    50s (x2 over 2m18s)  kubelet, node3     Started container healthcheck
  Warning  Unhealthy  6s (x6 over 107s)    kubelet, node3     Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
  Normal   Killing    6s (x2 over 97s)     kubelet, node3     Container healthcheck failed liveness probe, will be restarted

倒数第二条信息表示:Liveness probe失败,没有找到文件或者目录

倒数第一条信息表示:容器Pod健康检查失败,将要重启容器

实际情况是重启6次之后,事件信息如下:一条警告,Unhealthy(不健康),不再输出will be restarted

  Warning  Unhealthy  53s (x21 over 10m)    kubelet, node3     Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory

Readiness探测

Kubernetes Health Check 机制还包括 Readiness 探测。

用户通过 Liveness 探测可以告诉 Kubernetes 什么时候通过重启容器实现自愈;Readiness 探测则是告诉 Kubernetes 什么时候可以将容器加入到 Service 负载均衡池中,对外提供服务。

修改Liveness的文件

[root@node1 ~]# vim healthcheck.yml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: readiness
  name: readiness
spec:
  restartPolicy: OnFailure
  containers:
  - name: readiness
    image: busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 6000
    readinessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 10
      periodSeconds: 5

语法完全是一样的。只是将Liveness改为了readiness

运行Pod

[root@node1 ~]# kubectl apply -f healthcheck.yml 
pod/readiness created

30s左右查看Pod的READY,为1/1

[root@node1 ~]# kubectl get pod readiness 
NAME        READY   STATUS    RESTARTS   AGE
readiness   1/1     Running   0          40s

在过大概10秒左右,再次查看,又变回了0/1

[root@node1 ~]# kubectl get pod readiness 
NAME        READY   STATUS    RESTARTS   AGE
readiness   0/1     Running   0          73s

查看Pod事件信息

[root@node1 ~]# kubectl describe pod readiness
...
Events:
  Type     Reason     Age                   From               Message
  ----     ------     ----                  ----               -------
  Normal   Scheduled  3m4s                  default-scheduler  Successfully assigned default/readiness to node2
  Normal   Pulling    3m3s                  kubelet, node2     Pulling image "busybox"
  Normal   Pulled     2m47s                 kubelet, node2     Successfully pulled image "busybox"
  Normal   Created    2m47s                 kubelet, node2     Created container readiness
  Normal   Started    2m47s                 kubelet, node2     Started container readiness
  Warning  Unhealthy  33s (x21 over 2m13s)  kubelet, node2     Readiness probe failed: cat: can't open '/tmp/healthy': No such file or directory

事件信息为readiness探测失败。

整个变化过程为:

  1. 刚被创建时,READY 状态为不可用。
  2. 15 秒后(initialDelaySeconds + periodSeconds),第一次进行 Readiness 探测并成功返回,设置 READY 为可用。
  3. 30 秒后,/tmp/healthy 被删除,连续 3 次 Readiness 探测均失败后,READY 被设置为不可用。

Liveness与Readiness

  1. Liveness 探测和 Readiness 探测是两种 Health Check 机制,如果不特意配置,Kubernetes 将对两种探测采取相同的默认行为,即通过判断容器启动进程的返回值是否为零来判断探测是否成功。
  2. 两种探测的配置方法完全一样,支持的配置参数也一样。不同之处在于探测失败后的行为:Liveness 探测是重启容器;Readiness 探测则是将容器设置为不可用,不接收 Service 转发的请求。
  3. Liveness 探测和 Readiness 探测是独立执行的,二者之间没有依赖,所以可以单独使用,也可以同时使用。用 Liveness 探测判断容器是否需要重启以实现自愈;用 Readiness 探测判断容器是否已经准备好对外提供服务。

评论




正在载入...
PoweredHexo
HostedAliyun
DNSAliyun
ThemeVolantis
UV
PV
BY-NC-SA 4.0