健康检查详解与实战演示(就绪性探针 和 存活性探针)([云原生]

2023-02-08  本文已影响0人  s1mple

一、概述

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

图片

官方文档:https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
Kubernetes(k8s)环境部署可以参考我这篇文章:Kubernetes(k8s)最新版最完整版环境部署+master高可用实现(k8sV1.24.1+dashboard+harbor)

1)k8s中的探针种类

1、就绪检查(readinessProbe,就绪探针)

readiness probes 准备就绪检查,通过readiness是否准备接受流量,准备完毕加入到Endpoint,否则剔除。如果容器不提供就绪探针,则默认状态为 Success

2、存活检查(livenessProbe,存活探针)

liveness probes 在线检查机制,检查应用是否可用,如死锁,无法响应,异常时将根据restartPolicy来设置 Pod 状态会自动重启容器,如果容器不提供存活探针,则默认状态为 Success

restartPolicy有三个可选值:

3、启动检查(startupProbe,启动探针,1.17 版本新增)

就绪、存活两种探针的区别:

readinessProbelivenessProbe 可以使用相同探测方式,只是对 Pod 的处置方式不同。

2)k8s中的三种探测方式

每种探测机制支持三种健康检查方法,分别是命令行exec,httpGet和tcpSocket,其中exec通用性最强,适用与大部分场景,tcpSocket适用于TCP业务,httpGet适用于web业务。

探针探测结果有以下值:

二、readinessProbe(就绪性探针)

三、livenessProbe(存活性探针)

四、实战演示
常用的探针可选参数:


image.png

1)exec方式

cat >exec-liveness.yaml<<EOF
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  # 为了测试方便,指定调度机器
  nodeName: local-168-182-110
  containers:
  - name: liveness
    image: registry.aliyuncs.com/google_containers/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5
EOF

解释:

initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 5 秒。

periodSeconds 字段指定了 kubelet 应该每 5 秒执行一次存活探测。

kubelet 在容器内执行命令 cat /tmp/healthy 来进行探测。

如果命令执行成功并且返回值为 0,kubelet 就会认为这个容器是健康存活的。

如果这个命令返回非 0 值,kubelet 会杀死这个容器并重新启动它。

当容器启动时,执行如下的命令:

/bin/sh -c "touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600"

这个容器生命的前 30 秒,/tmp/healthy 文件是存在的。 所以在这最开始的 30 秒内,执行命令 cat /tmp/healthy 会返回成功代码。 30 秒之后,执行命令 cat /tmp/healthy 就会返回失败代码。

创建 Pod:

# 最好先拉取镜像,如果是使用docker,就换成docker就行
crictl pull registry.aliyuncs.com/google_containers/busybox

kubectl apply -f exec-liveness.yaml

【问题】ERRO[0000] unable to determine image API version: rpc error: code = Unavailable desc = connection error: desc = “transport: Error while dialing dial unix /var/run/dockershim.sock: connect: no such file or directory”
【解决】原因:未配置endpoints

crictl config runtime-endpoint unix:///run/containerd/containerd.sock
crictl config image-endpoint unix:///run/containerd/containerd.sock

查看

kubectl describe pod liveness-exec
image.png

【现象】30s之后检查失败后就重启pod了,又正常了。

2)httpGet 方式

cat >http-liveness.yaml<<EOF
apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget
  namespace: default
spec:
  # 为了测试方便,指定调度机器
  nodeName: local-168-182-110
  containers:
  - name: liveness-httpget-container
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - name: nginx
      containerPort: 80
    livenessProbe:
      httpGet:
        port: nginx
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 10
EOF

解释:

initialDelaySeconds字段告诉 kubelet 在执行第一次探测前应该等待 1 秒。

periodSeconds 字段指定了 kubelet 每隔 3 秒执行一次存活探测。

kubelet 会向容器内运行的服务(服务在监听 80 端口)发送一个 HTTP GET 请求来执行探测。

如果服务器上/index.html路径下的处理程序返回成功代码,则 kubelet 认为容器是健康存活的。

如果处理程序返回失败代码,则 kubelet 会杀死这个容器并将其重启。

返回大于或等于 200 并且小于 400 的任何代码都标示成功,其它返回代码都标示失败。

执行并查看

crictl pull nginx
kubectl apply -f http-liveness.yaml
kubectl describe pod liveness-httpget
image.png
image.png

删除 Pod 的 index.html 文件

kubectl exec -it liveness-httpget -- rm -rf /usr/share/nginx/html/index.html
# 再查看
kubectl describe pod liveness-httpget
kubectl get pod liveness-httpget

重启原因是 HTTP 探测得到的状态返回码是 404,Liveness probe failed: HTTP probe failed with statuscode: 404。

重启完成后,不会再次重启,因为重新拉取的镜像中包含了 index.html 文件。

HTTP Probes 允许针对 httpGet 配置额外的字段:

host:连接使用的主机名,默认是 Pod 的 IP。也可以在 HTTP 头中设置 “Host” 来代替。

scheme :用于设置连接主机的方式(HTTP 还是 HTTPS)。默认是 "HTTP"。

path:访问 HTTP 服务的路径。默认值为 "/"。

httpHeaders:请求中自定义的 HTTP 头。HTTP 头字段允许重复。

port:访问容器的端口号或者端口名。如果数字必须在 1~65535 之间。

你可以通过为探测设置 .httpHeaders 来重载默认的头部字段值;例如:

livenessProbe:
  httpGet:
    httpHeaders:
      - name: Accept
        value: application/json

startupProbe:
  httpGet:
    httpHeaders:
      - name: User-Agent
        value: MyUserAgent

3)tcpSocket 方式

cat >tcp-liveness-readiness.yaml<<EOF
apiVersion: v1
kind: Pod
metadata:
  name: liveness-readiness-tcpsocket
  labels:
    app: liveness-readiness-tcpsocket
spec:
  # 为了测试方便,指定调度机器
  nodeName: local-168-182-110
  containers:
  - name: liveness-readiness-tcpsocket
    image: nginx
    ports:
    - containerPort: 80
    readinessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 10
    livenessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 15
      periodSeconds: 20
EOF

解释:

kubelet 会在容器启动 5 秒后发送第一个就绪探测(livenessProbe)。

探测器会尝试连接 goproxy 容器的 80 端口。 如果探测成功,这个 Pod 会被标记为就绪状态,kubelet 将继续每隔 10 秒运行一次检测。

除了就绪探测,这个配置包括了一个存活探测(livenessProbe)。

kubelet 会在容器启动 15 秒后进行第一次存活探测(livenessProbe)。

与就绪探测类似,活跃探测器会尝试连接 goproxy 容器的 80 端口。 如果存活探测失败,容器会被重新启动。
执行

kubectl apply -f tcp-liveness-readiness.yaml
kubectl get pod liveness-readiness-tcpsocket
kubectl describe pod liveness-readiness-tcpsocket
image.png

4)使用命名端口
对于 HTTP 或者 TCP 存活检测可以使用命名的 port。

ports:
- name: nginx
  containerPort: 80
  hostPort: 80

livenessProbe:
  httpGet:
    path: /index.html
    port: nginx

完整版配置

ports:
- name: nginx
  containerPort: 80
  hostPort: 80

# readinessProbe,就绪探针
livenessProbe:
  httpGet:
    path: /index.html
    port: nginx
  # 延迟多久后开始探测
  initialDelaySeconds: 10
  # 执行探测频率(秒) 【 每隔秒执行一次 】
  periodSeconds: 10
  #  超时时间
  timeoutSeconds: 1
  # 处于成功状态时,探测连续失败几次可被认为失败。
  failureThreshold: 3
  # 处于失败状态时,探测连续成功几次,被认为成功。
  successThreshold: 1

# livenessProbe,存活探针
livenessProbe:
  httpGet:
    path: /index.html
    port: nginx
  # 延迟多久后开始探测
  initialDelaySeconds: 10
  # 执行探测频率(秒) 【 每隔秒执行一次 】
  periodSeconds: 10
  #  超时时间
  timeoutSeconds: 1
  # 处于成功状态时,探测连续失败几次可被认为失败。
  failureThreshold: 3
  # 处于失败状态时,探测连续成功几次,被认为成功。
  successThreshold: 1

# startupProbe,启动探针
startupProbe:
  httpGet:
    path: /index.html
    port: nginx
  # 延迟多久后开始探测
  initialDelaySeconds: 10
  # 执行探测频率(秒) 【 每隔秒执行一次 】
  periodSeconds: 10
  #  超时时间
  timeoutSeconds: 1
  # 处于成功状态时,探测连续失败几次可被认为失败。
  failureThreshold: 3
  # 处于失败状态时,探测连续成功几次,被认为成功。
  successThreshold: 1

一般使用控制器去创建管理pod,对k8s 控制器不清晰的小伙伴,可以参考我之前的文章:Kubernetes(k8s)Deployment、StatefulSet、DaemonSet、Job、CronJob五种控制器详解

下面是一个完整版的示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-probe
spec:
  replicas: 3
  selector:
    matchLabels:
     app: deployment-probe
  template:
    metadata:
      labels:
        app: deployment-probe
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        
        # readinessProbe,就绪探针
        readinessProbe:
          httpGet:
            path: /index.html
            port: nginx
          # 延迟多久后开始探测
          initialDelaySeconds: 10
          # 执行探测频率(秒) 【 每隔秒执行一次 】
          periodSeconds: 10
          #  超时时间
          timeoutSeconds: 1
          # 处于成功状态时,探测连续失败几次可被认为失败。
          failureThreshold: 3
          # 处于失败状态时,探测连续成功几次,被认为成功。
          successThreshold: 1
        
        # livenessProbe,存活探针
        livenessProbe:
          httpGet:
            path: /index.html
            port: nginx
          # 延迟多久后开始探测
          initialDelaySeconds: 10
          # 执行探测频率(秒) 【 每隔秒执行一次 】
          periodSeconds: 10
          #  超时时间
          timeoutSeconds: 1
          # 处于成功状态时,探测连续失败几次可被认为失败。
          failureThreshold: 3
          # 处于失败状态时,探测连续成功几次,被认为成功。
          successThreshold: 1
        
        # startupProbe,启动探针
        startupProbe:
          httpGet:
            path: /index.html
            port: nginx
          # 延迟多久后开始探测
          initialDelaySeconds: 10
          # 执行探测频率(秒) 【 每隔秒执行一次 】
          periodSeconds: 10
          #  超时时间
          timeoutSeconds: 1
          # 处于成功状态时,探测连续失败几次可被认为失败。
          failureThreshold: 3
          # 处于失败状态时,探测连续成功几次,被认为成功。
          successThreshold: 1

执行查看

crictl pull nginx:1.17.1
kubectl apply -f deployment-probe.yaml
kubectl get pod,deploy

Kubernetes(k8s)健康检查详解与实战演示就先到这里了,健康检查会伴随所有k8s编排任务,所以非常重要,其实也不难,小伙伴有什么疑问,欢迎给我留言哦~

上一篇 下一篇

猜你喜欢

热点阅读