k8s进阶-容器探测

前言

容器探测用于检测容器中的应用实例是否正常工作,通过向目前容器周期性发出不同方式的探针,以检测目标实例的健康状态,k8s环境下微服务应用的健康监控是必不可少的环节,本章节也将结合springboot健康检查插件来整合支持k8s的容器探测

探针类型

存活探针- LivenessProbe

kubelet 使用存活探针来检测应用实例当前是否处于正常运行状态,确定什么时候需要重启容器。 例如,存活探针可以探测到应用死锁(应用程序在运行,但是无法继续执行后面的步骤)情况。重启探测失败状态的容器有助于提高应用的可用性

就绪探针- ReadinessProbe

kubelet 使用就绪探针可以知道容器何时准备好接受请求流量,当一个 Pod 内的所有容器都就绪时,才能认为该 Pod 就绪。这种信号的一个用途就是控制哪个 Pod 作为 Service 的后端,若 Pod 就绪探测失败,会被从 Service 的负载均衡列表中剔除

启动探针- StartupProbe

kubelet 使用启动探针来了解应用容器何时启动。 如果配置了这类探针,就可以控制容器在启动成功后再进行存活性[liveness]和就绪态[readiness]的检查, 确保存活、就绪探针不会影响应用的启动。 启动探针可以用于对慢启动容器进行存活性检测,避免它们在启动运行之前就被杀掉

探针参数

探针有很多配置参数,可以使用这些参数精确地控制启动、存活和就绪检测的行为

  • initialDelaySeconds:容器启动后要等待多少秒后才启动存活、就绪和启动探针, 默认是 0 秒,最小值是 0
  • periodSeconds:执行探测的时间间隔(单位是秒),默认是 10 秒,最小值是 1
  • timeoutSeconds:探测的超时后等待多少秒,默认值是 1 秒,最小值是 1
  • successThreshold:连续探测成功多少次才被认定为执行成功,默认值是 1,存活和启动探测的这个值必须是 1,最小值是 1
  • failureThreshold:连续探测失败多少次才被认定为执行失败。 对于存活探测而言,失败就意味着重新启动容器。 对就绪探测而言,失败意味着 Pod 会被打上未就绪的标签,默认值是 3,最小值是 1

探测方式

Exec命令 - 以存活探针为例

创建文件exec-liveness.yaml

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: liveness
  name: liveness-exec
  namespace: probe
spec:
  containers:
  - name: nginx
    image: nginx:latest
	args: 
    - /bin/sh
    - -c
    - touch /tmp/liveness; sleep 30; rm -f /tmp/liveness; sleep 100
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/liveness
      initialDelaySeconds: 5
      periodSeconds: 5

在配置文件中,periodSeconds 字段指定了 kubelet 每 5 秒执行一次存活探测。initialDelaySeconds 指定 kubelet 在执行第一次探测前应该等待 5 秒。 kubelet 在容器内执行命令 cat /tmp/liveness 来进行探测, 如果命令执行成功并且返回值为 0,kubelet 就会认为这个容器是健康存活的,如果这个命令返回非0值,kubelet 会杀死这个容器并重新启动它

在容器启动时,将执行如下命令:
/bin/sh -c "touch /tmp/liveness; sleep 30; rm -f /tmp/liveness; sleep 300"

容器生命的前 30 秒,/tmp/liveness 文件是存在的,即在容器启动后的 30 秒内,执行命令 cat /tmp/liveness 会返回成功,30 秒之后文件被删除,再次执行命令 cat /tmp/liveness 时就会返回失败,kubectl则会对容器进行重启操作

创建Pod

$ kubectl apply -f ./exec-liveness.yaml

30秒内查看pod的状态

$ kubectl describe pod liveness-exec -n probe

输出结果显示pod创建成功

Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  38s   default-scheduler  Successfully assigned probe/liveness-exec to k8s-node1
  Normal  Pulling    37s   kubelet            Pulling image "nginx:latest"
  Normal  Pulled     22s   kubelet            Successfully pulled image "nginx:latest" in 15.416721868s
  Normal  Created    22s   kubelet            Created container nginx
  Normal  Started    22s   kubelet            Started container nginx

等到35秒再次查看pod的状态,显示liveness探测失败,Container nginx failed liveness probe, will be restarted\n Container nginx failed liveness probe, will be restarted,容器被重启

$ kubectl describe pod liveness-exec -n probe
----------------------------------------------
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Scheduled  3m26s                default-scheduler  Successfully assigned probe/liveness-exec to k8s-node1
  Normal   Pulled     3m11s                kubelet            Successfully pulled image "nginx:latest" in 15.416721868s
  Normal   Pulled     104s                 kubelet            Successfully pulled image "nginx:latest" in 15.370383805s
  Warning  Unhealthy  60s (x6 over 2m40s)  kubelet            Liveness probe failed: cat: /tmp/healthy: No such file or directory
  Normal   Killing    60s (x2 over 2m30s)  kubelet            Container nginx failed liveness probe, will be restarted
  Normal   Pulling    30s (x3 over 3m26s)  kubelet            Pulling image "nginx:latest"
  Normal   Created    14s (x3 over 3m11s)  kubelet            Created container nginx
  Normal   Started    14s (x3 over 3m11s)  kubelet            Started container nginx
  Normal   Pulled     14s                  kubelet            Successfully pulled image "nginx:latest" in 15.368988721s

此时查看pod状态,显示容器重启次数增加了1

$ kubectl get pod liveness-exec -n probe
--------------------------------------------------------
NAME            READY   STATUS             RESTARTS   AGE
liveness-exec   0/1     CrashLoopBackOff   1          1m

HttpGet - 以存活探针为例

创建文件http-liveness.yaml

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: liveness
  name: liveness-http
  namespace: probe
spec:
  containers:
  - name: nginx
    image: nginx:latest
    livenessProbe:
      httpGet:
        path: /
        port: 80
        scheme: HTTP
        httpHeaders:
        - name: Accept
          value: application/json
      initialDelaySeconds: 5
      periodSeconds: 5

在配置文件中,periodSeconds 指定了 kubelet 应该每 5 秒执行一次存活探测,initialDelaySeconds 指定 kubelet 在容器启动后等待 5 秒再开始探测。kubelet 会向容器内运行的服务(host-默认为pod的ip,port为80)发送一个HTTP GET 请求来执行探测, 如果服务器上 "/" 路径下的处理程序返回成功,则 kubelet 认为容器是健康存活的,如果处理程序返回失败,则 kubelet 会杀死这个容器并将其重启

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

创建pod

$ kubectl apply -f ./http-liveness.yaml

容器启动后,控测的地址http://podid:80/为nginx服务的首页,即能正常返回200状态码,pod状态显示创建成功

$ kubectl describe pod -n probe
----------------------------------------------------------------------
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  42s   default-scheduler  Successfully assigned probe/liveness-http to k8s-node1
  Normal  Pulling    42s   kubelet            Pulling image "nginx:latest"
  Normal  Pulled     26s   kubelet            Successfully pulled image "nginx:latest" in 16.461481089s
  Normal  Created    26s   kubelet            Created container nginx
  Normal  Started    26s   kubelet            Started container nginx
----------------------------------------------------------------------
$ kubectl get pod -n probe
NAME            READY   STATUS    RESTARTS   AGE
liveness-http   1/1     Running   0          1m

接着修改yaml文件,指定path路径为 "/abc",脚本片断如下:

containers:
  - name: nginx
    image: nginx:latest
    livenessProbe:
      httpGet:
        #修改路径为/abc
        path: /abc
        port: 80
        scheme: HTTP

此时,kubelet访问的探测地址为http://podid:80/abc,因容器内nginx服务不存在该路径地址,则会返回404状态码,查看pod状态显示健康检查失败,Liveness probe failed: HTTP probe failed with statuscode: 404,kubelet 会杀死容器并再次重新启动容器

$ kubectl describe pod liveness-http -n probe
------------------------------------------------------------------
Events:
  Type     Reason     Age               From               Message
  ----     ------     ----              ----               -------
  Normal   Scheduled  34s               default-scheduler  Successfully assigned probe/liveness-http to k8s-node1
  Normal   Pulled     19s               kubelet            Successfully pulled image "nginx:latest" in 15.467613921s
  Normal   Created    19s               kubelet            Created container nginx
  Normal   Started    18s               kubelet            Started container nginx
  Normal   Pulling    3s (x2 over 34s)  kubelet            Pulling image "nginx:latest"
  Warning  Unhealthy  3s (x3 over 13s)  kubelet            Liveness probe failed: HTTP probe failed with statuscode: 404
  Normal   Killing    3s                kubelet            Container nginx failed liveness probe, will be restarted

TcpSocket - 以就绪探针和存活探针为例

TCP 检测的配置和 HTTP 检测方式相近,只需要配置端口即可。如果能建立连接,这个容器就被看作是健康的,脚本片断如下:

 containers:
  - name: nginx
    image: nginx:latest
    readinessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20

gRPC - 以存活探针为例

在 Kubernetes 1.23 之前,gRPC 健康探测通常使用 grpc-health-probe 来实现。v1.24版本以后就可以使用内置gRPC探针,但必须先启用 GRPCContainerProbe 特性门控才能配置依赖于 gRPC 的检查机制。因gRPC探测容器存活的方式比较少见,这里暂不做详细描述,参考博客地址:https://kubernetes.io/blog/2018/10/01/health-checking-grpc-servers-on-kubernetes/

脚本片断如下:

 containers:
  - name: nginx
    image: nginx:latest
    livenessProbe:
      grpc:
        port: 2379
      initialDelaySeconds: 10

集成SpringBoot Actuator

一、配置pom.xml,引入actuator模块

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

二、配置application.properties,定义liveness和readiness分组

management.endpoint.health.probes.enabled=true
management.endpoint.health.group.liveness.include=livenessState,ping
management.endpoint.health.group.readiness.include=readinessState
#配置health Endpoints暴露在web环境下(即可通过url访问)
management.endpoints.web.exposure.include=health,info
#默认为/actuator
management.endpoints.web.basePath=/actuator

样例中liveness分组会执行LivenessStateHealthIndicator和PingHealthIndicator两个检查器,当两个检查器状态同时为UP时,liveness分组状态为UP,访问路径http://localhost:8080/actuator/health/liveness

响应:{"status":"UP","components":{"livenessState":{"status":"UP"},"ping":{"status":"UP"}}}

样例中readiness分组只执行ReadinessStateHealthIndicator检查器,访问路径http://localhost:8080/actuator/health/readiness

响应:{"status":"UP","components":{"readinessState":{"status":"UP"}}}

三、配置K8S容器检测 - 存活探针和就绪探针,yaml文件片断如下:

livenessProbe:
  failureThreshold: 3
  periodSeconds: 30
  successThreshold: 1
  timeoutSeconds: 6
  httpGet:
    path: /actuator/health/liveness
    port: 8080
    scheme: HTTP
readinessProbe:
  failureThreshold: 3
  periodSeconds: 15
  successThreshold: 3
  timeoutSeconds: 3
  httpGet:
    path: /actuator/health/readiness
    port: 8080
    scheme: HTTP

总结

1、存活探针不会等待就绪性探成功后再开始探测
2、如果就绪态探针实现不正确,可能会导致容器中进程的数量不断上升
3、如果要在执行存活探针之前等待,可以使用 initialDelaySeconds参数 或 startupProbe探针
4、针对 HTTP 或 TCP 探测,通过将启动探针 failureThreshold * periodSeconds 参数设置为足够长的时间来保护慢启动容器

(完)

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值