6. 健康检查

强大的自愈能力是Kubernetes这类容器编排引擎的一个重要特性,自愈的默认实现方式是自动重启发生故障的容器。

6.1 为什么需要健康检查

用户还可以利用Liveness和Readiness探测机制设置更精细的健康检查,进而实现如下需求:

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

6.2 检查策略

在Pod部署到Kubernetes集群中以后,为了确保Pod处于健康正常的运行状态,Kubernetes提供了两种探针,用于检测容器的状态:

6.2.1 存活探测

Liveness是检查容器是否处于运行状态,如果检测失败,kubelet将会杀掉掉容器,并根据重启策略进行下一步的操作,如果容器没有提供Liveness Probe,则默认状态为Success;

Liveness探测器是让Kubernetes知道你的应用是否活着,如果你的应用还活着,那么Kubernetes就让它继续存在,如果你的应用程序已经死了,Kubernetes将移除Pod并重新启动一个来替换它。

让我们想象另一种情况,当我们的应用在成功启动以后因为一些原因“宕机”,或者遇到死锁情况,导致它无法响应用户请求。 ​ 在默认情况下,Kubernetes会继续向Pod发送请求,通过使用存活探针来检测,当发现服务不能在限定时间内处理请求(请求错误或者超时),就会重新启动有问题的pod。

d2d9eb3416d74986ad019d9c729b9671.png

6.2.2 就绪探测

Readiness 是检查容器是否已经处于可接受服务请求的状态,如果Readiness Probe失败,端点控制器将会从服务端点(与Pod匹配的)中移除容器的IP地址,Readiness的默认值为Failure,如果一个容器未提供Readiness,则默认是Success。

就绪探针旨在让Kubernetes知道你的应用是否准备好为请求提供服务,Kubernetes只有在就绪探针通过才会把流量转发到Pod,如果就绪探针检测失败,Kubernetes将停止向该容器发送流量,直到它通过。

一个应用往往需要一段时间来预热和启动,比如一个后端项目的启动需要连接数据库执行数据库迁移等等,一个Spring项目的启动也需要依赖Java虚拟机。即使该过程已启动,您的服务在启动并运行之前也无法运行。应用在完全就绪之前不应接收流量,但默认情况下,Kubernetes会在容器内的进程启动后立即开始发送流量。通过就绪探针探测,直到应用程序完全启动,然后才允许将流量发送到新副本。

3d3353d1a87c4ab38ece8e9368870caa.png

6.2.3 两者对比

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

6.2.4 如何配置

对于LivenessProbe和ReadinessProbe用法都一样,拥有相同的参数和相同的监测方式。

  • initialDelaySeconds:用来表示初始化延迟的时间,也就是告诉监测从多久之后开始运行,单位是秒
  • timeoutSeconds: 用来表示监测的超时时间,如果超过这个时长后,则认为监测失败
  • periodSeconds:指定每多少秒执行一次探测,Kubernetes如果连续执行3次Liveness探测均失败,则会杀掉并重启容器

6.3 使用场景

  • 如果容器中的进程能够在遇到问题或不健康的情况下自行崩溃,则不一定需要存活探针; kubelet 将根据 Pod 的restartPolicy 自动执行正确的操作。
  • 如果希望容器在探测失败时被杀死并重新启动,那么请指定一个存活探针,并指定restartPolicy 为 Always 或 OnFailure。
  • 如果要仅在探测成功时才开始向 Pod 发送流量,请指定就绪探针,在这种情况下,就绪探针可能与存活探针相同,但是 spec 中的就绪探针的存在意味着 Pod 将在没有接收到任何流量的情况下启动,并且只有在探针探测成功后才开始接收流量。
  • 如果您希望容器能够自行维护,您可以指定一个就绪探针,该探针检查与存活探针不同的端点。
  • 如果您只想在 Pod 被删除时能够排除请求,则不一定需要使用就绪探针;在删除 Pod 时,Pod 会自动将自身置于未完成状态,无论就绪探针是否存在,当等待 Pod 中的容器停止时,Pod 仍处于未完成状态。

6.4 默认的健康检查

我们首先学习Kubernetes默认的健康检查机制:每个容器启动时都会执行一个进程,此进程由Dockerfile的CMD或ENTRYPOINT指定。

如果进程退出时返回码非零,则认为容器发生故障,Kubernetes就会根据restartPolicy重启容器

6.4.1 创建资源清单

Pod的restartPolicy设置为OnFailure,默认为Always,sleep 10; exit 1模拟容器启动10秒后发生故障

vi pod-default-health.yml

apiVersion: v1
kind: Pod
metadata:
  name: pod-default-health
  namespace: default
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.12
    ports: 
    - containerPort: 80
    args: ["/bin/sh","-c"," sleep 10;exit 1"]

6.4.2 创建容器

kubectl apply -f pod-default-health.yml

6.4.3 监控Pod变化

kubectl get pods -o wide -w

该命令可以不断显示容器的因为失败不断重启

在上面的例子中,容器进程返回值非零,Kubernetes则认为容器发生故障,需要重启。

有不少情况是发生了故障,但进程并不会退出,比如访问Web服务器时显示500内部错误,可能是系统超载,也可能是资源死锁,此时httpd进程并没有异常退出,在这种情况下重启容器可能是最直接、最有效的解决方案,那我们如何利用HealthCheck机制来处理这类场景呢?

6.5 探针类型

探针类型是指通过何种方式来进行健康检查,K8S有三种类型的探测:HTTP,Command和TCP。

6.5.1 exec存活探针

对于命令探测,是指Kubernetes在容器内运行命令,如果命令以退出代码0返回,则容器将标记为正常。否则,它被标记为不健康

下面的资源会在先创建一个nginx的任务,生存测试探针livenessProbe会执行test -e /tmp/healthy命令检查文件是否存在, 若文件存在则返回状态码 0,表示成功通过测试。

apiVersion: v1
kind: Pod
metadata:
  name: pod-nginx-demo
  namespace: default
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.12
    ports: 
    - containerPort: 80
    livenessProbe:
      initialDelaySeconds: 5
      periodSeconds: 3
      exec:
        command: ["test","-e","/tmp/healthy"]

6.5.1.1 创建pod

创建pod

kubectl create -f pod-demo.yaml
kubectl get pod -w -o wide

 启动后不断检测/tmp/healthy是否存在,不存在重启容器

827ba12dedc54dafb72fda3452014979.png

6.5.1.2 创建文件

新开一个窗口写入登录pod容器,写入healthy文件

# 登录pod容器
kubectl exec pod-nginx-demo -it /bin/bash
echo healthy > /tmp/healthy
# 在html目录写入healthy文件
echo healthy > /tmp/healthy

查看原来的pod状态

kubectl get pods -o wide -w

我们发现pod不在不断地重启了

c3f013e98297435eb9f5207f4413e39d.png

6.5.2 HTTP就绪探针

HTTP探测可能是最常见的探针类型,即使应用不是HTTP服务,也可以创建一个轻量级HTTP服务器来响应探测,比如让Kubernetes通过HTTP访问一个URL,如果返回码在200到300范围内,就将应用程序标记为健康状态,否则它被标记为不健康。

上面 清单 文件 中 定义 的 httpGet 测试 中, 请求的资源路径 为/healthy, 地址 默认 为 Pod IP, 端口使用了容器中定义的端口名称 HTTP, 这也是明确为容器指明要暴露的端口的用途之一。

apiVersion: v1
kind: Pod
metadata:
  name: pod-nginx-demo
  namespace: default
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.12
    ports: 
    - containerPort: 80
    readinessProbe:
      initialDelaySeconds: 5
      periodSeconds: 3
      httpGet:
        port: 80
        path: /healthy
        scheme: HTTP

 6.5.2.1 创建pod

kubectl create -f pod-demo.yaml
#查看pod状态
kubectl get pods -o wide -w

我们发现nginx 一致处于未未就绪状态

7e5ba9e5e4f84349bbe5034589e5ad66.png

6.5.2.2 查看pod详情

 kubectl describe pod pod-nginx-demo

42540f3486e24d61942fe27d25e6a5e2.png

6.5.2.3 创建文件

新开一个窗口写入登录pod容器,写入healthy文件

# 登录pod容器
kubectl exec pod-nginx-demo -it /bin/bash
# 在html目录写入healthy文件
echo healthy > /usr/share/nginx/html/healthy

查看原来的pod状态

9511a0e7577c4e83aeec20f1b7733a54.png

6.5.2.4 访问

curl 10.244.1.30/healthy

ecc7a70a53214286ac9ec3338776f510.png

再次删除healthy文件

rm -f /usr/share/nginx/html/healthy

c56f6bc2f7a0423c9017558f57659801.png

再次查看pod状态,进入未就绪状态

 kubectl get pods -o wide -w

02711d28b3284d6a907ab76d3a682794.png

6.5.3 TCP探针

TCP探测是指Kubernetes尝试在指定端口上建立TCP连接。

如果它可以建立连接,容器被认为是健康的; 如果它不能被认为是不健康的。

这常用于对gRPC或FTP服务的探测。

下面的资源清单文件,向Pod IP的80/tcp端口发起连接请求,并根据连接建立的状态判断Pod存活状态。

 

apiVersion: v1
kind: Pod
metadata:
  name: pod-nginx-demo
  namespace: default
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.12
    ports: 
    - containerPort: 80
    livenessProbe:
      tcpSocket:
        port: 80

6.5.3.1 探测结果

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

  • 成功:容器通过了诊断。
  • 失败:容器未通过诊断。
  • 未知:诊断失败,因此不会采取任何行动。

6.5.3.2 创建pod

kubectl create -f pod-demo.yaml
#查看pod状态
kubectl get pods -o wide -w

只要80端口正常一致就是正常状态

6b1ad7ebe20645b190da123762348c3e.png

 

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐