容器探测用于检测容器中的应用实例是否正常工作,通过向目前容器周期性发出不同方式的探针,以检测目标实例的健康状态,k8s环境下微服务应用的健康监控是必不可少的环节,本章节也将结合springboot健康检查插件来整合支持k8s的容器探测
存活探针- LivenessProbe
kubelet 使用存活探针来检测应用实例当前是否处于正常运行状态,确定什么时候要重启容器。 例如,存活探针可以探测到应用死锁(应用程序在运行,但是无法继续执行后面的步骤)情况。重启探测失败状态的容器有助于提高应用的可用性
就绪探针- ReadinessProbe
kubelet 使用就绪探针可以知道容器何时准备好接受请求流量,当一个 Pod 内的所有容器都就绪时,才能认为该 Pod 就绪。 这种信号的一个用途就是控制哪个 Pod 作为 Service 的后端,若 Pod 尚未就绪,会被从 Service 的负载均衡器中剔除
启动探针- StartupProbe
kubelet 使用启动探针来了解应用容器何时启动。 如果配置了这类探针,就可以控制容器在启动成功后再进行存活性[liveness]和就绪态[readiness]检查, 确保这些存活、就绪探针不会影响应用的启动。 启动探针可以用于对慢启动容器进行存活性检测,避免它们在启动运行之前就被杀掉
探针有很多配置字段,可以使用这些字段精确地控制启动、存活和就绪检测的行为
initialDelaySeconds:容器启动后要等待多少秒后才启动启动、存活和就绪探针, 默认是 0 秒,最小值是 0periodSeconds:执行探测的时间间隔(单位是秒)。默认是 10 秒,最小值是 1timeoutSeconds:探测的超时后等待多少秒。默认值是 1 秒,最小值是 1successThreshold:探针在失败后,被视为成功的最小连续成功数,默认值是 1。存活和启动探测的这个值必须是 1,最小值是 1failureThreshold:当探测失败时,Kubernetes 的重试次数。 对于存活探测而言,放弃就意味着重新启动容器。 对就绪探测而言,放弃意味着 Pod 会被打上未就绪的标签。默认值是 3,最小值是 1Exec命令 - 以存活探针为例
创建文件exec-liveness.yaml
apiVersion: v1
kind: Pod
metadata:labels:app: livenessname: liveness-execnamespace: probe
spec:containers:- name: nginximage: nginx:latestargs: - /bin/sh- -c- touch /tmp/liveness; sleep 30; rm -f /tmp/liveness; sleep 300livenessProbe:exec:command:- cat- /tmp/livenessinitialDelaySeconds: 5periodSeconds: 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-node1Normal Pulling 37s kubelet Pulling image "nginx:latest"Normal Pulled 22s kubelet Successfully pulled image "nginx:latest" in 15.416721868sNormal Created 22s kubelet Created container nginxNormal 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,容器被重启
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Scheduled 3m26s default-scheduler Successfully assigned probe/liveness-exec to k8s-node1Normal Pulled 3m11s kubelet Successfully pulled image "nginx:latest" in 15.416721868sNormal Pulled 104s kubelet Successfully pulled image "nginx:latest" in 15.370383805sWarning Unhealthy 60s (x6 over 2m40s) kubelet Liveness probe failed: cat: /tmp/healthy: No such file or directoryNormal Killing 60s (x2 over 2m30s) kubelet Container nginx failed liveness probe, will be restartedNormal Pulling 30s (x3 over 3m26s) kubelet Pulling image "nginx:latest"Normal Created 14s (x3 over 3m11s) kubelet Created container nginxNormal Started 14s (x3 over 3m11s) kubelet Started container nginxNormal 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: livenessname: liveness-httpnamespace: probe
spec:containers:- name: nginximage: nginx:latestlivenessProbe:httpGet:path: /port: 80scheme: HTTPhttpHeaders:- name: Acceptvalue: application/jsoninitialDelaySeconds: 5periodSeconds: 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-node1Normal Pulling 42s kubelet Pulling image "nginx:latest"Normal Pulled 26s kubelet Successfully pulled image "nginx:latest" in 16.461481089sNormal Created 26s kubelet Created container nginxNormal 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: nginximage: nginx:latestlivenessProbe:httpGet:#修改路径为/abcpath: /abcport: 80scheme: 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-node1Normal Pulled 19s kubelet Successfully pulled image "nginx:latest" in 15.467613921sNormal Created 19s kubelet Created container nginxNormal Started 18s kubelet Started container nginxNormal 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: 404Normal Killing 3s kubelet Container nginx failed liveness probe, will be restarted
TcpSocket - 以就绪探针和存活探针为例
TCP 检测的配置和 HTTP 检测方式相近,只需要配置端口即可。如果能建立连接,这个容器就被看作是健康的,脚本片断如下:
containers:- name: nginximage: nginx:latestreadinessProbe:tcpSocket:port: 8080initialDelaySeconds: 5periodSeconds: 10livenessProbe:tcpSocket:port: 8080initialDelaySeconds: 15periodSeconds: 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: nginximage: nginx:latestlivenessProbe:grpc:port: 2379initialDelaySeconds: 10
一、配置pom.xml,引入actuator模块
org.springframework.boot spring-boot-starter-actuator
二、配置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: 3periodSeconds: 30successThreshold: 1timeoutSeconds: 6httpGet:path: /actuator/health/livenessport: 8080scheme: HTTP
readinessProbe:failureThreshold: 3periodSeconds: 15successThreshold: 3timeoutSeconds: 3httpGet:path: /actuator/health/readinessport: 8080scheme: HTTP
1、存活探针不会等待就绪性探针成功
2、如果就绪态探针实现不正确,可能会导致容器中进程的数量不断上升
3、如果要在执行存活探针之前等待,可以使用 initialDelaySeconds 或 startupProbe
4、针对 HTTP 或 TCP 探测,通过将启动探针 failureThreshold * periodSeconds 参数设置为足够长的时间来保护慢启动容器
(完)