资讯详情

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

前言

在之前的一系列文章之后,我们对k8s应该算是简单的入门。在这篇文章的开头,我们将逐渐开始解释一些先进的知识点。在前面的文章中,我们主要关注如何完全发布一个可访问的服务。重点是以springboot vuejs前后分离项目为主。后续文章也将围绕springboot vuejs,然而,一些新的服务将基于其扩展,如redis、rabbitmq、elk等。

关于健康检测

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

默认情况下,当 Pod 当所有容器启动时,Kubernetes 开始向 Pod 在崩溃时发送流量并重新启动容器。如果Pod启动后立即提供外部服务是不合理的。因为Pod启动成功并不意味着容器中部署的服务可以为外部服务,例如springboot项目,容器启动成功后,springboot启动需要一些初始化的工作,真正的外部访问需要几秒钟,慢需要十秒、二十秒甚至更长时间。 Kubernetes 这一点在设计中得到了考虑,可以通过创建自定义运行状态检查来使部署更加强大 。这里有一个关键词:

容器探针

探针是由 kubelet 定期诊断容器。kubelet 调用由容器实现的 Handler。处理程序有三种:

  • ExecAction:在容器中执行指定的命令。如果命令退出,返回代码为 0 认为诊断成功。
  • CPSocketAction:指定端口上的容器 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。
  • HTTPGetAction:容器在指定的端口和路径上 IP 地址执行 HTTP Get 请求。如果响应状态码大于或等于200 且小于 400,诊断被认为是成功的。

每次探测都会得到以下三个结果之一:

  • 成功:通过诊断容器。
  • 失败:容器未被诊断。
  • 未知:诊断失败,不采取行动。

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"                 # hst: 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
    
  2. /etc/hosts新增一行,即1中配置的host

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

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

    kubectl apply -f v2.yaml
    

    效果如下:

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

最后清一下空间

kubectl delete -f v2.yaml

项目源码地址

  • 后端

https://gitee.com/mldong/mldong

  • 前端

https://gitee.com/mldong/mldong-vue

小结

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

标签: 连接器eins探针deins探针连接器d

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台