手把手带你玩转k8s-健康检查之存活探针与就绪探针

微信扫一扫,分享到朋友圈

手把手带你玩转k8s-健康检查之存活探针与就绪探针

前言

经过前面的一系列文章,我们对k8s应该也算是简单的入门了。本文开始,会逐步开始讲解一些进阶的知识点。在前面的文章中,我们主要是围绕如何完整地发布一个可对外访问的服务。其中重点是以springboot+vuejs前后端分离项目为主的。后续的文章也会是围绕springboot+vuejs,不过会基于其扩展一些新的服务,如redis、rabbitmq、elk等。

关于健康检测

健康检查(Health Check)是让系统知道您的应用实例是否正常工作的简单方法。 如果您的应用实例不再工作,则其他服务不应访问该应用或向其发送请求。 相反,应该将请求发送到已准备好的应用程序实例,或稍后重试。 系统还应该能够使您的应用程序恢复健康状态。

默认情况下,当 Pod 中的所有容器启动时,Kubernetes 开始向 Pod 发送流量,并在崩溃时重新启动容器。如果Pod启动后就立即对外服务,其实是不太合理的。因为Pod启动成功并不代表容器里面部署的服务就能对外服务了,比如springboot项目,容器启动成功后,springboot启动需要一些初始化工作,真正要能对外访问,快则需要几秒,慢则需要十几、二十秒,甚至更久。 Kubernetes 在设计上已经考虑到了这点,它可以通过创建自定义运行状况检查来使部署更加健壮 。这里涉及到一个关键字: 容器探针

容器探针

探针是由 kubelet 对容器执行的定期诊断。要执行诊断, kubelet 调用由容器实现的 Handler 。有三种类型的处理程序:

ExecAction
CPSocketAction
HTTPGetAction

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

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

Kubelet 可以选择是否执行在容器上运行的两种探针执行和做出反应:

  • livenessProbe (存活探针):指示容器是否正在运行。如果存活探测失败,则 kubelet 会杀死容器,并且容器将受到其 重启策略的影响。如果容器不提供存活探针,则默认状态为 Success
  • readinessProbe (就绪探针):指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与 Pod 匹配的所有 Service 的端点中删除该 Pod 的 IP 地址。初始延迟之前的就绪状态默认为 Failure 。如果容器不提供就绪探针,则默认状态为 Success

高级 liveness 探针示例

探针的定义,也是k8s编排的重要内容。

apiVersion: apps/v1
kind: Deployment
metadata:
name: mldong-admin
namespace: mldong-admin-test
spec:
selector:
matchLabels:
app: mldong-admin
replicas: 1
template:
metadata:
labels:
app: mldong-admin
spec:
containers:
- name: mldong-admin
env:
- name: TZ
value: Asia/Shanghai
image: registry.cn-zhangjiakou.aliyuncs.com/mldong/java/mldong-admin:202007220017_c608761
livenessProbe:
httpGet:
# 当没有定义 "host" 时,使用 "PodIP"
# host: my-host
# 当没有定义 "scheme" 时,使用 "HTTP" scheme 只允许 "HTTP" 和 "HTTPS"
# scheme: HTTPS
path: /healthz # 这要求服务得有这个接口地址
port: 8080     # 服务对应的端口
httpHeaders:   # 可以携带请求头
- name: X-Custom-Header
value: Awesome
initialDelaySeconds: 30   #第一次健康检查的时间
periodSeconds: 5    #检查周期
timeoutSeconds: 5   #检查超时时间
successThreshold: 1 #成功次数判定成功
failureThreshold: 1 #失败次数判定失败
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: port
protocol: TCP
command: ["/bin/sh"]
args: ["-c", "set -e && java -jar app.jar --spring.profiles.active=test --server.port=8080"]
复制代码

探针类型 livenessProbereadinessProbe ,与容器定义的image同级,两者可同时存在,前者是定义存活探针, 健康状态检查,周期性检查服务是否存活,检查结果失败,将重启容器 。后者是定义就绪探针, 可用性检查,周期性检查服务是否可用,不可用将从service的endpoints中移除 。

如上,定义了一个存活探针 livenessProbe ,其使用的 httpGet 的方式去检查的,请求路径为 /healthz ,端口为 8080 ,请求头 httpHeadersX-Custom-Header=Awesome 。第一次健康检查的时间 initialDelaySeconds 为pod启动后30s后进行检测;检查周期 periodSeconds 为5s;检查超时时间 timeoutSeconds 为5s;成功次数 successThreshold 为1判定成功;失败次数 failureThreshold 为1判定失败。

检查方式说明:

  • httpGet 检测某个 http 请求的返回状态码 2xx,3xx正常, 4xx,5xx错误

参数说明

参数 默认值 说明
host 当没有定义 “host” 时,使用 “PodIP” 请求域名
scheme HTTP 只允许 “HTTP” 和 “HTTPS”
path / 请求地址,这需要接口服务中有该请求地址
port 80 服务对应的端口
httpHeaders 请求头name/value

样例:

httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: X-Custom-Header
value: Awesome
复制代码
  • exec 执行一段命令 返回值为0, 非0

参数说明:

参数 默认值 说明
command 要执行的命令,数组

样例:

exec: #执行方式
command:  #初始命令
- cat
- /tmp/healthy
复制代码
  • tcpSocket 测试某个端口是否能够连接

参数说明:

参数 默认值 说明
port 80 端口

样例:

tcpSocket:
port: 80
复制代码

检查规则说明

参数 默认值 说明
initialDelaySeconds 第一次健康检查的时间,太小的话,可能会造成pod无限重启。
periodSeconds 检查周期
timeoutSeconds 检查超时时间
successThreshold 1 成功次数判断成功
failureThreshold 1 失败次数判断失败

实战演示

在实战前,先学习如下命令:

for a in {1..10};do curl http://vueadmin.mldong.com/api/login;date +"%Y%m%d%H%M%S";sleep 2;done;

每隔2秒钟进行一次接口访问,循环10次。

效果图如下:

存活探针

  1. 新建 v1.yaml
cat << EOF > /mldong/k8s/mldong-probe/v1.yaml
apiVersion: v1
kind: Namespace
metadata:
name: mldong-probe
---
apiVersion: v1
kind: Service
metadata:
name: mldong-admin-nodeport
namespace: mldong-probe
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8080
selector:
app: mldong-admin
---
apiVersion: v1
kind: Service
metadata:
name: mldong-admin
namespace: mldong-probe
spec:
type: ClusterIP
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
app: mldong-admin
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mldong-admin
namespace: mldong-probe
spec:
selector:
matchLabels:
app: mldong-admin
replicas: 1
template:
metadata:
labels:
app: mldong-admin
spec:
containers:
- name: mldong-admin
env:
- name: TZ
value: Asia/Shanghai
image: registry-vpc.cn-zhangjiakou.aliyuncs.com/mldong/java/mldong-admin:202007220017_c608761
livenessProbe:
tcpSocket:
port: 8080     # 服务对应的端口
initialDelaySeconds: 15  #第一次健康检查的时间
periodSeconds: 5    #检查周期
timeoutSeconds: 5   #检查超时时间
successThreshold: 1 #成功次数判定成功
failureThreshold: 1 #失败次数判定失败
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: port
protocol: TCP
command: ["/bin/sh"]
args: ["-c", "set -e && java -jar app.jar --spring.profiles.active=test --server.port=8080"]
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
name: mldong-admin-ingress
namespace: mldong-probe
spec:
rules:
- host: a.test.com
http:
paths:
- backend:
serviceName: mldong-admin
servicePort: 8080
path: /
EOF
复制代码
  1. 另外开启一个终端,执行如下命令:
kubectl get pods -A -w | grep mldong-probe
复制代码
  1. 旧终端执行如下命令:
kubectl apply -f v1.yaml
复制代码

正常启动效果如下:

4. 删除重来

kubectl delete -f v1.yaml
复制代码

​ 修改成其他非服务端口

tcpSocket:
port: 8081
复制代码
  1. 重新运行
kubectl apply -f v1.yaml
复制代码

效果如下:

其实就是监听的服务不存在,重启容器。

最后清一下空间

kubectl delete -f v1.yaml
复制代码

就绪探针

  1. 新建 v2.yaml

    cat << EOF > /mldong/k8s/mldong-probe/v2.yaml
    apiVersion: v1
    kind: Namespace
    metadata:
    name: mldong-probe
    ---
    apiVersion: v1
    kind: Service
    metadata:
    name: mldong-admin-nodeport
    namespace: mldong-probe
    spec:
    type: NodePort
    ports:
    - port: 8080
    targetPort: 8080
    selector:
    app: mldong-admin
    ---
    apiVersion: v1
    kind: Service
    metadata:
    name: mldong-admin
    namespace: mldong-probe
    spec:
    type: ClusterIP
    ports:
    - port: 8080
    protocol: TCP
    targetPort: 8080
    selector:
    app: mldong-admin
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: mldong-admin
    namespace: mldong-probe
    spec:
    selector:
    matchLabels:
    app: mldong-admin
    replicas: 1
    template:
    metadata:
    labels:
    app: mldong-admin
    spec:
    containers:
    - name: mldong-admin
    env:
    - name: TZ
    value: Asia/Shanghai
    image: registry-vpc.cn-zhangjiakou.aliyuncs.com/mldong/java/mldong-admin:202007220017_c608761
    readinessProbe:
    tcpSocket:
    port: 8080     # 服务对应的端口
    initialDelaySeconds: 15  #第一次健康检查的时间
    periodSeconds: 5    #检查周期
    timeoutSeconds: 5   #检查超时时间
    successThreshold: 1 #成功次数判定成功
    failureThreshold: 1 #失败次数判定失败
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
    name: port
    protocol: TCP
    command: ["/bin/sh"]
    args: ["-c", "set -e && java -jar app.jar --spring.profiles.active=test --server.port=8080"]
    ---
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    annotations:
    name: mldong-admin-ingress
    namespace: mldong-probe
    spec:
    rules:
    - host: a.test.com
    http:
    paths:
    - backend:
    serviceName: mldong-admin
    servicePort: 8080
    path: /
    EOF
    复制代码
  1. /etc/hosts 新增一行,即1中配置的host

  2. 另外开启一个终端,执行如下命令

    for a in {1..30};do curl http://a.test.com/api/login;date +"%Y%m%d%H%M%S";sleep 2;done;
    复制代码
  3. 旧终端执行如下命令

    kubectl apply -f v2.yaml
    复制代码

    效果如下:

    开始服务不存在,访问的是nginx-ingress的默认服务。服务正常启动后,接口访问正常。这里只是演示单个服务启动的样例。其实在我们做系统版本升级的时候也是这样子的。比如现在服务版本1要升级到服务版本2,我们只需要修改一下镜像的版本,然后再执行 kubectl apply -f k8s.yaml 。这样新的服务版本就可以做到不停服更新了。

最后清一下空间

kubectl delete -f v2.yaml
复制代码

小结

本文简单介绍了k8s的健康检查-存活探针与就绪探针,并简单地做了一下案例演示。使用存活探针与就绪探针的目的都是为了让我们的服务更健壮。大家可以根据自身服务的情况去选择使用哪一种类型的探针和检查方式。据说Spring Boot 2.3提供K8s活性和就绪性探针,感兴趣的同学可以去了解一下。

项目源码地址

Go 语言学习之错误处理

上一篇

腾讯蓝鲸自动化运维平台简介部署及常见报错解决

下一篇

你也可能喜欢

手把手带你玩转k8s-健康检查之存活探针与就绪探针

长按储存图像,分享给朋友