实验环境:
按照图示部署好了K8s集群,一个Master,两个worker nodes。
概述:
健康检查(Health Check)用于检测应用实例是否正常工作(例如某pod中文件丢失了,但是状态还是running,这种情况下deployment无法查看),是保障业务可用性的一种传统机制,一般用于负载均衡下的业务,如果实例的状态不符合预期,将会把该实例“摘除”,不承担业务流量。
Kubernetes中的健康检查使用存活性探针(liveness probes)和就绪性探针(readiness probes)来实现,service即为负载均衡,k8s保证 service 后面的 pod 都可用,是k8s中自愈能力的主要手段,基于这两种探测机制,可以实现如下需求:
- 异常实例自动剔除,并重启新实例;
- 多种类型探针检测,保证异常pod不接入流量;
- 不停机部署,更安全的滚动升级。
目前支持的探测方式包括:
- HTTP Get
- TCP
- 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相关参数:
- initialDelaySeconds:容器启动后第一次执行探测是需要等待多少秒。
- periodSeconds:执行探测的频率,默认是10秒,最小1秒。
- timeoutSeconds:探测超时时间,默认1秒,最小1秒。(一般是用于http或者tcp探测时使用)
- successThreshold:探测失败后,最少连续探测成功多少次才被认定为成功,默认是1,对于liveness必须是1,最小值是1。
- 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
更多推荐