实验环境:

在这里插入图片描述
按照图示部署好了K8s集群,一个Master,两个worker nodes。

概述:

健康检查(Health Check)用于检测应用实例是否正常工作(例如某pod中文件丢失了,但是状态还是running,这种情况下deployment无法查看),是保障业务可用性的一种传统机制,一般用于负载均衡下的业务,如果实例的状态不符合预期,将会把该实例“摘除”,不承担业务流量。

Kubernetes中的健康检查使用存活性探针(liveness probes)和就绪性探针(readiness probes)来实现,service即为负载均衡,k8s保证 service 后面的 pod 都可用,是k8s中自愈能力的主要手段,基于这两种探测机制,可以实现如下需求:

  1. 异常实例自动剔除,并重启新实例;
  2. 多种类型探针检测,保证异常pod不接入流量;
  3. 不停机部署,更安全的滚动升级。

目前支持的探测方式包括:

  1. HTTP Get
  2. TCP
  3. Command

活性探针:

检查到了pod出现问题,通过重启来解决文件,所谓的重启,就是删除整个pod创建同名pod。

1.以Command的方式创建带liveness probes的pod:

yaml文件如下,可以去官网拷贝:

[root@vms201 health_check]# cat podlive.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: podlieness
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: liveness
    image: busybox
    imagePullPolicy: IfNotPresent
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 1000
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5 #容器启动的5s内不监测
      periodSeconds: 5 #每5s钟检测一次

livenessProbe相关参数:

  1. initialDelaySeconds:容器启动后第一次执行探测是需要等待多少秒。
  2. periodSeconds:执行探测的频率,默认是10秒,最小1秒。
  3. timeoutSeconds:探测超时时间,默认1秒,最小1秒。(一般是用于http或者tcp探测时使用)
  4. successThreshold:探测失败后,最少连续探测成功多少次才被认定为成功,默认是1,对于liveness必须是1,最小值是1。
  5. failureThreshold:当 Pod 启动了并且探测到失败,Kubernetes 的重试次数。存活探测情况下的放弃就意味着重新启动容器。就绪探测情况下的放弃 Pod 会被打上未就绪的标签。默认值是 3。最小值是 1

如果没有健康检查,在pod启动时会在指定目录中创建了一个文件,30s后删除此文件,并且容器本还可以存活1000s。但是这里通过livnessProbe检查是否存在此文件以判断容器是否正常。command便是健康检查的命令,查看是否存在指定文件夹,如果存在则返回为1,表示pod没有故障,否则返回为0,说明健康检查有文件,会删除pod后重新创建:

[root@vms201 health_check]# kubectl apply -f podlive.yaml
pod/podlieness created

[root@vms201 health_check]# kubectl get pods
NAME         READY   STATUS    RESTARTS   AGE
podlieness   1/1     Running   4          3m5s

可以看到在3m5s的时候,此pod因为健康检查,已经重启了4次。

如果设置了容器删除的宽限期,重启的时间会加上宽限期的时间。

2.以 HTTP Get的方式对pod做健康性检查

修改yaml文件:

[root@vms201 health_check]# cat podliveHttp.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: liveness
    image:
    imagePullPolicy: IfNotPresent
    livenessProbe:
      failureThreshold: 3
      httpGet:
        path: /index.html
        port: 80
        scheme: HTTP
      initialDelaySeconds: 10
      periodSeconds: 10
      successThreshold: 1
      timeoutSeconds: 10

此yaml定义了健康检查的方式是每10s使用HTTP Get的方式去访问容器的index页面。如果可以正常获取结果,说明容器没有故障,否则则说明容器存在故障。

创建并查看pod:

[root@vms201 health_check]# kubectl apply -f podliveHttp.yaml
pod/liveness-exec created
[root@vms201 health_check]# kubectl get pods
NAME            READY   STATUS    RESTARTS   AGE
liveness-http  1/1     Running   0          6s

查看pod中是否存在被检测的index页面:存在

[root@vms201 health_check]# kubectl exec -it liveness-http -- ls /usr/share/nginx/html/index.html
/usr/share/nginx/html/index.html

删除掉此文件:

kubectl exec -it liveness-http -- ls /usr/share/nginx/html/index.html

再次查看pod是否重启:已经重启了一次,说明探测成功。

[root@vms201 health_check]# kubectl get pods
NAME            READY   STATUS    RESTARTS   AGE
liveness-http   1/1     Running   1          4m2s

3.以 TCP的方式对pod做健康性检查

修改yaml文件:

[root@vms201 health_check]# cat podlivesTCP.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-tcp
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: liveness
    image: nginx
    imagePullPolicy: IfNotPresent
    livenessProbe:
      failureThreshold: 3
      tcpSocket:
        port: 80
      initialDelaySeconds: 10
      periodSeconds: 10
      successThreshold: 1
      timeoutSeconds: 10

应用并查看pod:

[root@vms201 health_check]# kubectl apply -f podlivesTCP.yaml
pod/liveness-tcp created
[root@vms201 health_check]# kubectl get pods
NAME           READY   STATUS    RESTARTS   AGE
liveness-tcp   1/1     Running   0          10s

部署完成后,每隔10s,都会去检测pod的TCP 80号端口是否正常,如果无法通信,则重启pod。

绪性探针:

发现容器出现问题不重启的,只是用户发送来的请求不会发送到此pod上。以command的方式执行为例:

实验概述:
创建三个nginx的pod,分别把主页里的内容修改为1、2、3。然后设置一个SVC,将流量负载到3个pod上去。当其中有pod出现故障后,通过readiness的检查方式,让流量不分配到出现故障的pod上。

步骤1: 创建3个pods

修改yaml文件: 主要是将关键的key从livenessProbe修改为readinessProbe。

[root@vms201 health_check]# cat podlivereadiness.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: pod
  name: pod1
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: readinessc1
    image: nginx
    imagePullPolicy: IfNotPresent
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "touch /tmp/healthy"]
    readinessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5 
      periodSeconds: 5 

创建3个nginx容器:pod1、pod2、pod3。

[root@vms201 health_check]# kubectl apply -f podlivereadiness.yaml
pod/pod1 created
[root@vms201 health_check]# sed 's/pod1/pod2/' podlivereadiness.yaml | kubectl apply -f -
pod/pod2 created
[root@vms201 health_check]# sed 's/pod1/pod3/' podlivereadiness.yaml | kubectl apply -f -
pod/pod3 created

[root@vms201 health_check]# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
pod1   1/1     Running   0          46s
pod2   1/1     Running   0          35s
pod3   1/1     Running   0          30s

步骤2: 修改nginx的index页面,分别为1、2、3

[root@vms201 health_check]# kubectl exec -it pod1 -- sh -c "echo 1 > /usr/share/nginx/html/index.html"
[root@vms201 health_check]# kubectl exec -it pod2 -- sh -c "echo 2 > /usr/share/nginx/html/index.html"
[root@vms201 health_check]# kubectl exec -it pod3 -- sh -c "echo 3 > /usr/share/nginx/html/index.html"

步骤3: 创建SVC,将流量负载到三个设备上去

[root@vms201 health_check]# kubectl expose --name=svc1 pod pod1 --port=80
service/svc1 exposed
[root@vms201 health_check]# kubectl get svc -o wide
NAME   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE   SELECTOR
svc1   ClusterIP   10.103.194.55   <none>        80/TCP    10s   test=pod

已经将SVC绑定到了label为test=pod的3个pods上。

步骤4: 访问svc1的IP地址,查看流量负载情况

[root@vms201 ~]# while true ; do
> curl -s 10.103.194.55
> sleep 1
> done
3
2
1
3
3
1
2
3
1
1
1

流量目前被负载到了3个pods上。

步骤5: 删除掉pod1上的健康检查文件,再次查看流量的分配情况

kubectl exec -it pod1 -- rm /tmp/healthy

可以看到,当删除掉了pod1上的健康检查文件,pod1的READY为0/1,说明出现故障被检查到了,但是STATUS为Running,说明pod1并没有被删除:

[root@vms201 health_check]# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
pod1   0/1     Running   0          9m48s
pod2   1/1     Running   0          9m37s
pod3   1/1     Running   0          9m32s

再次测试流量的负载:

[root@vms201 ~]# while true ; do
> curl -s 10.103.194.55
> sleep 1
> done
3
2
2
2
3
3
3
3
3
2
3
2
3
2
2
2
2

流量仅被负载到pod2和pod3上面去了,实验结果符合预期,健康检测成功。

其他两种检查方式同理,这里就不多描述了。

参考资料:
《老段CKA课程》
https://www.jianshu.com/p/5def7f934d2e

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐