Kubernetes(K8s)集群内的 Pod 探针(Probe)是一种健康检查机制,用于监控容器的运行状态并据此执行相应操作,确保应用的可用性和稳定性。探针通过执行指定的检查(如命令执行、HTTP 请求或 TCP 连接)来评估容器的健康状况。
使用 Kubernetes(K8s)的 Pod 探针能带来多方面的好处,显著提升应用的可靠性、可用性和运维效率。此外,探针的自定义配置能力(如调整检查周期、超时时间)使运维团队能够根据应用特性定制监控策略,实现精细化管理。通过自动化的健康检查和恢复机制,Pod 探针降低了系统故障概率,提高了资源利用率,是构建弹性云原生应用的重要基石。
当然,我们最终都只有一个目的,就是让提供服务的pod节点,能够稳定,健康,按照正常的轨迹运行下去,让用户在访问的时候尽量减少因为pod的突然出错而影响了正常的体验。
startupProbe
(启动探针)是为解决长启动时间应用的监控难题而设计的。对于一些需要加载大量数据、执行复杂初始化或依赖外部资源的应用(如数据仓库、机器学习模型服务),传统的存活探针可能会在应用尚未完全启动时就误判为失败,导致容器频繁重启。启动探针通过设置较长的超时时间和重试机制,专门监控应用的启动过程,在此期间会暂时禁用存活探针和就绪探针。一旦启动探针检测到应用成功启动(如特定端口开始接受连接、健康检查接口返回200状态码),后续监控工作将交由其他探针接管。这种分阶段监控策略有效避免了对启动缓慢应用的误杀,确保资源合理利用,提升了系统的稳定性和可靠性。
livenessProbe
(存活探针)是保障容器持续运行的核心机制。它通过定期执行指定的检查(如执行容器内命令、发送HTTP请求或尝试TCP连接)来验证容器是否处于健康状态。当探测失败(如命令返回非零退出码、HTTP请求超时、TCP连接拒绝)时,Kubernetes会自动重启容器,就像自动医生一样,及时发现并处理应用程序内部的故障(如死锁、无限循环),确保服务始终可用。这种自动化恢复机制大大减少了人工干预,特别适合长时间运行且需要高可用性的服务,如数据库、消息队列等。例如,对于一个Node.js应用,存活探针可以定期向应用的健康检查端点发送HTTP请求,若连续多次失败,则触发容器重启,避免服务中断。
readinessProbe
(就绪探针)负责控制流量分发的精确性。它的核心作用是判断容器是否已经完全准备好接收用户请求,只有当探针检测成功时,Kubernetes才会将该容器添加到Service的负载均衡池中。这在应用启动、升级或依赖服务故障恢复等场景中尤为重要。例如,一个微服务应用启动时需要连接数据库、加载配置文件等操作,就绪探针可以在这些初始化步骤完成后才允许流量进入,避免用户请求被转发到未完全初始化的容器,从而提高整体服务质量。当容器因资源不足或临时故障导致处理能力下降时,就绪探针也能及时将其从流量池中移除,保护系统稳定性。
Kubernetes(K8s)的Pod探针(Probe)支持三种实现方式,分别是exec
、httpGet
和tcpSocket
,每种方式针对不同的监控场景提供了差异化的检测手段:
exec
方式通过在容器内部执行指定命令来判断容器状态。当命令返回状态码为0时,表示容器健康;非零状态码则视为失败。这种方式的优势在于灵活性高,可以执行任何容器内可用的脚本或命令,适合自定义检查逻辑(如验证应用内部状态、检查文件完整性)。例如,通过执行curl localhost:8080/health
命令检查应用健康端点,或使用ps -ef | grep myapp
验证进程是否运行。但exec
方式依赖容器内环境的完整性,若基础工具缺失(如curl
、bash
)可能导致误判,且需要在容器镜像中额外安装监控工具,增加了镜像复杂度。
httpGet
方式向容器内的指定HTTP路径发送GET请求,根据响应状态码判断健康状态。当返回200-399之间的状态码时视为成功,否则为失败。这种方式的优势在于直接验证应用层响应,无需额外工具,与Web应用天然契合,广泛用于REST API服务的健康检查。例如,向Spring Boot应用的/actuator/health
端点发送请求,或检查Nginx服务器的/status
页面。此外,httpGet
支持自定义请求头(如添加认证信息)和TLS配置,适用于安全要求较高的场景。但它仅能检测HTTP服务,对于非HTTP应用(如TCP服务器、数据库)则不适用。
tcpSocket
方式通过尝试与容器内的指定端口建立TCP连接来判断容器状态。若连接成功建立,探针视为成功;否则失败。这种方式适用于任何基于TCP协议的服务(如MySQL、Redis、SSH),无需应用层提供专门的健康检查接口,只需服务监听在指定端口即可。例如,检查MySQL服务是否正常可通过尝试连接3306端口实现。tcpSocket
的优势在于实现简单、开销小,不依赖应用内部逻辑,但它只能验证端口可达性,无法检测服务内部状态(如数据库是否可正常执行查询)。
三种实现方式的核心区别在于检测层次和适用场景:exec
基于命令执行结果,适合自定义脚本检查;httpGet
聚焦于HTTP应用层响应,直接验证业务逻辑;tcpSocket
则关注底层网络连接,适用于所有TCP服务。在实际应用中,需根据容器内运行的应用类型选择合适的探针方式,必要时可组合使用多种方式以实现更全面的监控。
在本模块中,我们将集中探讨启动探针与存活探针的搭配使用,以实现pod节点的自愈功能
apiVersion: apps/v1
kind: Deployment
metadata:
name: mytest1
labels:
app: nginx1
spec:
replicas: 1
selector:
matchLabels:
app: nginx1
template:
metadata:
labels:
app: nginx1
spec:
containers:
- name: centos7
image: centos:7
command: ["/bin/bash","-c","touch /tmp/live;sleep 3600"]
startupProbe:
exec:
command: ["/bin/bash","-c","test -e /tmp/live"]
#initialDelaySeconds: 1
#表示容器启动之后多少秒之内开启探测
#periodSeconds: 3
#表示探针执行的间隔时间,即多少秒执行一次
#failureThreshold: 3
#在pod被标记为不健康时,探测运行的失败次数
#timeoutSeconds: 3
#探测的超时时间,在多少秒内必须完成探测
#successThreshold: 1
#判断成功几次任务容器就已就绪
实现的效果,先用命令创建一个live文件,然后用启动探针去检测它,检测成功则能正常启动,检测失败则不能正常启动,检测失败之后经过一定时间会重启pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: mytest1
labels:
app: nginx1
spec:
replicas: 1
selector:
matchLabels:
app: nginx1
template:
metadata:
labels:
app: nginx1
spec:
containers:
- name: centos7
image: centos:7
command: ["/bin/bash","-c","touch /tmp/live;sleep 3600"]
startupProbe:
exec:
command: ["/bin/bash","-c","test -e /tmp/live"]
livenessProbe:
exec:
command: ["/bin/bash","-c","test -e /tmp/live"]
initialDelaySeconds: 1
#表示容器启动之后多少秒之内开启探测
periodSeconds: 3
#表示探针执行的间隔时间,即多少秒执行一次
failureThreshold: 3
#在pod被标记为不健康时,探测运行的失败次数
timeoutSeconds: 3
#探测的超时时间,在多少秒内必须完成探测
successThreshold: 1
#判断成功几次任务容器就已就绪
通过启动探针和存活探针检测命令相同可以实现pod的自愈机制,存活探针检测失败会重启pod,从而重新生成配置文件
我们通过存活探针来检验一下,yaml文件如下
apiVersion: apps/v1
kind: Deployment
metadata:
name: mytest1
labels:
app: nginx1
spec:
replicas: 1
selector:
matchLabels:
app: nginx1
template:
metadata:
labels:
app: nginx1
spec:
containers:
- name: nginx
image: nginx:1.22
livenessProbe:
httpGet:
scheme: HTTP
port: 80
path: /index.html
initialDelaySeconds: 1
#表示容器启动之后多少秒之内开启探测
periodSeconds: 3
#表示探针执行的间隔时间,即多少秒执行一次
failureThreshold: 3
#在pod被标记为不健康时,探测运行的失败次数
timeoutSeconds: 3
#探测的超时时间,在多少秒内必须完成探测
successThreshold: 1
#判断成功几次任务容器就已就绪
检验操作:我们进入容器中删除index.html文件,观察pod容器是否会重启,以及是否会重新生成nginx的index.html的配置文件。
至于就绪探针的实现我们把它放在下一个模块即pod节点服务的高可用中讲解
通过 resources.requests
和 resources.limits
配置资源分配:
requests
:定义 Pod 容器启动时需预留的资源量。limits
:定义 Pod 容器可使用的最大资源量。资源类型:
m
(毫核,如 1000m=1核
)或浮点数(如 0.5
)。Ki
、Mi
、Gi
(2 的幂次)或 k
、M
、G
(10 的幂次),默认单位为字节。nvidia.com/gpu
)。关键规则:
limits.memory
,会触发 OOM(内存不足)错误,进程被终止。apiVersion: v1 # Kubernetes API版本
kind: Pod # Kubernetes资源类型,这里是Pod
metadata:
name: frontend # Pod的名称
spec:
containers: # Pod中的容器列表
- name: web # 容器的名称
image: nginx # 容器使用的镜像
env: # 容器内的环境变量列表
- name: WEB_ROOT_PASSWORD
value: "password" # 环境变量的名称和值
resources: # 容器资源请求和限制
requests:
memory: "64Mi" # 请求的内存量
cpu: "250m" # 请求的CPU量(250毫核)
limits:
memory: "128Mi" # 限制的内存量
cpu: "500m" # 限制的CPU量(500毫核)
- name: db # 第二个容器的名称
image: mysql # 第二个容器使用的镜像
env: # 第二个容器内的环境变量列表
- name: MYSQL_ROOT_PASSWORD
value: "abc123" # 第二个环境变量的名称和值
resources: # 第二个容器的资源请求和限制
requests:
memory: "512Mi" # 请求的内存量
cpu: "0.5" # 请求的CPU量(半个核)
limits:
memory: "1Gi" # 限制的内存量
cpu: "1" # 限制的CPU量(一个核)
kubectl apply -f pod2.yaml # 应用YAML文件中定义的Pod到Kubernetes集群
kubectl describe pod frontend # 显示Pod的详细信息,包括状态、事件和资源使用情况
kubectl get pods -o wide # 显示集群中所有Pod的详细信息,包括IP地址、所在节点等
# 输出示例:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
frontend 2/2 Running 5 15m 10.244.2.4 node02 <none> <none>
kubectl describe nodes node02 # 显示指定节点的详细信息,包括资源分配情况
# 输出中的资源分配部分示例(已添加注释):
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
--------- ---- ------------ ---------- --------------- ------------- ---
default frontend 500m (25%) 1 (50%) 128Mi (3%) 1024Mi (25%) # 注意:这里的Memory Limits应为1Gi(1024Mi),可能是输出时的格式问题
kube-system kube-flannel-ds-amd64-f4pbp 100m (5%) 100m (5%) 50Mi (1%) 50Mi (1%) 19h
kube-system kube-proxy-pj4wp 0 (0%) 0 (0%) 0 (0%) 0 (0%) 19h
# 节点资源分配汇总(已添加注释):
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.) # 总限制可能超过100%,表示资源可能已过度分配
Resource Requests Limits
-------- -------- ------
cpu 600m (30%) 1100m (55%) # CPU请求和限制占总资源的百分比
memory 178Mi (4%) 1076Mi (26%) # 注意:这里的Memory Limits应为306Mi(frontend的256Mi + 其他的小量)+ kube-flannel和kube-proxy的50Mi = 约306Mi,但frontend的Memory Limits应为1Gi,可能是输出时的汇总问题或格式调整
ephemeral-storage 0 (0%) 0 (0%) # 临时存储空间未使用
QoS 等级 | 条件 | 优先级 |
---|---|---|
Guaranteed | 所有容器均设置 requests 和 limits ,且二者相等(如 CPU、内存)。 |
最高 |
Burstable | 至少一个容器设置了 requests 。 |
中 |
BestEffort | 所有容器均未设置 requests 或 limits 。 |
最低 |
驱逐顺序:BestEffort > Burstable > Guaranteed
Guaranteed
Pod 在资源不超限时不会被终止。Burstable
Pod 在资源紧张且超过 requests
时可能被终止。BestEffort
Pod 优先级最低,资源不足时优先被终止。通过 lifecycle
配置容器启动和终止时的操作:
postStart
:容器启动后执行(非主进程)。preStop
:容器终止前执行(常用于优雅关闭应用)。spec.containers[*].lifecycle.postStart
字段配置。spec.containers[*].lifecycle.preStop
字段配置。