K8S-Pod资源对象——Pod探针
目录
Kubernetes Pod 探针类型详解
Pod探针
kubelet检查机制
探针返回结果
探针的类型
1. 存活探针 (Liveness Probe)
2. 就绪探针 (Readiness Probe)
3. 启动探针 (Startup Probe)
探针检测方式详解
探针对比矩阵
探针配置黄金法则
常见错误与避免
最佳实践总结
livenessProbe存活探针和kubelet-exec
livenessProbe存活探针和kubelet-httpGet
readinessProbe就绪探针
readinessProbe和kubelet-exec
Kubernetes Pod 探针类型详解
Pod探针
在K8S集群中,为了测试pod是否正常运行,可以通过kubelet定期对pod进行健康检查,从而保证服务正常运行。
kubelet检查机制
-
exec: 在容器内执行指定命令,当返回码为0表示检测成功。在 Kubernetes 1.20 版本之前,exec 探针会忽略 timeoutSeconds: 探针会无限期地持续运行,甚至可能超过所配置的限期,直到返回结果为止。
-
httpGet:对容器的IP和URL进行HTTP的GET请求,当响应码(状态码)为大于等于200且小于400,表示容器正常运行。
-
tcpSocket:对容器内的端口或socket进行TCP检查,如果端口成功打开,证明容器正常运行。
探针返回结果
-
Success:表示通过检测。成功pod检测
-
Failure:表示未通过检测。失败pod挂起
-
Unknown:表示检测没有正常进行。
探针的类型
-
livenessProbe(存活探针):判断容器是否正常运行。如果存活探测失败,那么kubelet就会把老的容器删除,然后根据重启策略对容器做操作。如果容器没有存活探针,默认状态为Success。
-
readinessProbe(就绪探针):判断容器的是否就绪。比如:应用在启动时可能需要加载大量的数据或配置文件,或是启动后要依赖等待外部服务。在这种情况下,既不想杀死应用,也不想给它发送请求。这个时候就需要用到这个探针。当就绪探测失败,端点控制器将从与 Pod匹配的所有服务的端点列表中删除该 Pod 的 IP 地址(如果是用nodeport映射端口到外网,这个时候就不能访问网站了,但是容器不会被删除),初始延迟之前的就绪态的状态值默认为 Failure。 如果容器不提供就绪态探针,则默认状态为 Success。(生命周期是直至成功为止)
-
startupProbe(启动探针):指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被禁用,直到此探针成功为止。如果启动探测失败,kubelet 将删除容器,而容器依其重启策略进行重启。如果容器没有提供启动探测,则默认状态为 Success。
注意:startupProbe 和 livenessProbe 最大的区别就是startupProbe在探测成功之后就不会继续探测了,而livenessProbe在pod的生命周期中一直在探测!
在 Kubernetes 中,Pod 支持三种健康探针类型,每种类型都有独特的用途和运行机制。以下是全面解析:
1. 存活探针 (Liveness Probe)
核心功能:监测容器是否正常运行 关键行为:
-
失败 → 重启容器
-
成功 → 保持容器运行
解析:
-
设计目的:解决"进程存在但应用卡死"的状态
-
重启原理: 触发 Pod 的
containerStatuses
状态变更,Kubelet 执行容器重启 -
失败影响: 增加 Pod 的
restartCount
,但 Pod 不会被替换 -
特殊限制:
successThreshold
必须为 1(一次成功即视为正常)
使用场景:
YAML 示例:
livenessProbe:httpGet:path: /healthzport: 8080httpHeaders:- name: X-Custom-Headervalue: liveness-checkinitialDelaySeconds: 30 # 给容器启动时间periodSeconds: 20 # 每20秒检查一次timeoutSeconds: 5 # 5秒无响应即失败failureThreshold: 3 # 连续3次失败才重启
2. 就绪探针 (Readiness Probe)
核心功能:判断容器是否准备好接收流量 关键行为:
-
失败 → 从 Service 端点移除
-
成功 → 重新加入 Service 端点
解析:
-
网络层影响: 修改 Endpoint 对象的
notReadyAddresses
列表 -
与 Service 关系: 直接影响 kube-proxy 的 iptables/IPVS 规则
-
零停机更新: 滚动更新期间保证流量只路由到就绪实例
-
失败不重启: 容器不会被重启,只是停止接收流量
使用场景:
YAML 示例:
readinessProbe:exec:command:- sh- -c- 'test $(curl -s http://localhost:8080/ready) = "OK"'initialDelaySeconds: 5periodSeconds: 5successThreshold: 2 # 需要连续2次成功才标记就绪failureThreshold: 3 # 连续3次失败才被标记未就绪
3. 启动探针 (Startup Probe)
核心功能:检查容器是否完成启动过程 关键行为:
-
成功 → 激活存活探针和就绪探针
-
失败 → 延迟其他探针激活
解析:
-
Kubernetes 版本:v1.16+ 引入
-
解决痛点: 替代存活探针中的
initialDelaySeconds
应对慢启动容器 -
时间计算: 最大等待时间 =
initialDelaySeconds
+periodSeconds
×failureThreshold
-
与存活探针关系: 启动探针运行期间,存活探针不会激活
使用场景:
YAML 示例:
startupProbe:tcpSocket:port: 3306failureThreshold: 30 # 最多尝试30次periodSeconds: 5 # 每5秒检查一次# 最大等待时间 = 30 × 5 = 150秒
探针检测方式详解
所有探针类型都支持三种检测方法:
检测方式 | 配置示例 | 最佳实践场景 |
---|---|---|
HTTP GET | httpGet: {path: /health, port: 8080} | Web服务、API服务 |
TCP Socket | tcpSocket: {port: 9200} | 数据库、Redis、Elasticsearch |
Exec Command | exec: {command: ["pgrep", "java"]} | 检查进程存在、脚本复杂逻辑 |
📌 探测逻辑说明:
HTTP:响应状态码 200-399 视为成功
TCP:能建立连接即为成功
Exec:命令返回状态码 0 视为成功
探针对比矩阵
特性 | 存活探针 | 就绪探针 | 启动探针 |
---|---|---|---|
影响容器生命周期 | ✅ 触发重启 | ❌ 不影响容器 | ❌ 不影响容器 |
影响网络流量 | ❌ | ✅ 控制流量接入 | ❌ |
失败阈值灵活性 | ≥1 (通常3) | ≥1 (通常3) | ≥1 (根据启动时间定) |
成功阈值灵活性 | 固定为1 | ≥1 | 固定为1 |
默认激活时间 | 容器启动后立即开始 | 容器启动后立即开始 | 容器启动后立即开始 |
核心监控指标 | kubelet_containers_restarts | kube_endpoint_address_not_ready | kubelet_prober_probe_total |
探针配置黄金法则
-
启动顺序: 总是优先配置启动探针 → 然后配置就绪探针 → 最后配置存活探针
-
时间配置:
启动探针周期(periodSeconds) ≥ 就绪探针周期 ≥ 存活探针周期
-
失败阈值:
-
存活探针:3(避免过于敏感导致频繁重启)
-
就绪探针:2-3(容忍短暂抖动)
-
启动探针:根据
maxStartupTime = failureThreshold × periodSeconds
计算
-
-
生产推荐值:
# 慢启动应用配置模板
startupProbe:failureThreshold: (最大启动时间/5)+2periodSeconds: 5
readinessProbe:periodSeconds: 5failureThreshold: 2successThreshold: 2
livenessProbe:periodSeconds: 30failureThreshold: 3
常见错误与避免
错误类型 | 错误示例 | 后果 | 解决方案 |
---|---|---|---|
存活探针过于敏感 | failureThreshold: 1, periodSeconds: 5 | 频繁重启导致服务中断 | 增加failureThreshold 至3+ |
启动时间不足 | 启动需要120秒,但配置startup: failureThreshold: 10, periodSeconds: 10 | 启动中被存活探针重启 | 计算 failureThreshold >= 120/10 + 缓冲值 |
就绪探针和存活探针使用同一端点 | /health 同时用于活跃和就绪 | 健康检查失败导致双重惩罚 | 使用不同端点:/livez 、/readyz |
未考虑外部依赖 | 探针检查依赖数据库的服务 | 数据库故障导致所有容器重启 | 探针检查内部状态,不用外部依赖 |
最佳实践总结
-
所有生产容器必须配置就绪探针
-
关键应用配置存活探针 + 启动探针组合
-
HTTP/TCP 探测优于 Exec 探测(更少资源消耗)
-
区分检查端点
/startup → 启动探针 /readyz → 就绪探针 /livez → 存活探针
-
压力测试期间临时禁用存活探针(避免误重启)
通过合理配置这三种探针,您的 Kubernetes 应用将具备: ✅ 自动故障恢复能力 ✅ 无中断滚动更新能力 ✅ 慢启动应用支持能力 ✅ 过载自我保护能力
livenessProbe存活探针和kubelet-exec
#pod探针
#livenessProbe探针案例[root@k8s-master ~]# kubectl delete pod pod-test1 删除pod
pod "pod-test1" deleted
#删除test命名空间
[root@k8s-master ~]# kubectl delete ns test
namespace "test" deleted
#查看pod
[root@k8s-master ~]# kubectl get pod
No resources found in test namespace.
#设置default为当前上下文
[root@k8s-master ~]# kubectl config set-context --current --namespace default
Context "kubernetes-admin@kubernetes" modified.
#查看pod
[root@k8s-master ~]# kubectl get pod
No resources found in default namespace.
#创建myns1命名空间
[root@k8s-master ~]# kubectl create ns myns1
namespace/myns1 created
#编辑pod文件
[root@k8s-master ~]# vim nginx-pod-liveness-exec.yaml
apiVersion: v1
kind: Pod #类型
metadata:name: nginx-podsnamespace: myns1 #命名空间labels:app: nginx
spec:containers:- name: nginx image: nginx #镜像imagePullPolicy: IfNotPresentlivenessProbe:exec: #定义探测方式command: #不断查看文件是否存在,文件必须是镜像原本存在的文件- cat #查看index.html文件是否存在- /usr/share/nginx/html/index.htmlinitialDelaySeconds: 5 #指定探针5秒后启动periodSeconds: 5 #指定探针探测周期时间5秒#提交pod文件
[root@k8s-master ~]# kubectl create -f nginx-pod-liveness-exec.yaml
pod/nginx-pods created
#-n指定myns1命名空间查看pod有哪些
[root@k8s-master ~]# kubectl -n myns1 get pod
NAME READY STATUS RESTARTS AGE
nginx-pods 1/1 Running 0 18s#查看指定命名空间中 Pod 的详细信息
#-n myns1 指定命名空间为 myns1
#get pod 查询 Pod 资源(可简写为 po)
#-o wide 宽格式输出(显示额外字段)
[root@k8s-master ~]# kubectl -n myns1 get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-pods 1/1 Running 0 11m 10.244.36.76 k8s-node1 <none> <none>
#知道pod中的nginx-pods 的IP 就可以访问这个ip
[root@k8s-master ~]# curl 10.244.36.76
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p><p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p>
</body>
</html>#现在我们可以进行测试测试 livenessProbe和 exec
#测试
#现在是初始状态,重启零次
[root@k8s-master ~]# kubectl -n myns1 get pod
NAME READY STATUS RESTARTS AGE
nginx-pods 1/1 Running 0 18s
#测试定义方式是查看文件是否存在,而触发livenessProbe(存活探针)
#如果文件不存在就是存活探针探测失败,kubelet就会删除老容器,然后根据重启策略对容器进行操作,重启容器
#如果文件存在就是存活探针探测成功,就会保持容器运行
#这里我们删除所定义的文件
[root@k8s-master ~]# kubectl -n myns1 exec pods/nginx-pods -- rm -rf /usr/share/nginx/html/index.html
#查看pod里容器,此时存活探针探测失败,重启容器 (RESTARTS 显示1次重启)
[root@k8s-master ~]# kubectl -n myns1 get po
NAME READY STATUS RESTARTS AGE
nginx-pods 1/1 Running 1 (8s ago) 22m
#再次删除定义的文件
[root@k8s-master ~]# kubectl -n myns1 exec pods/nginx-pods -- rm -rf /usr/share/nginx/html/index.html
#查看pod里容器,此时存活探针探测失败,重启容器 (RESTARTS 显示2次重启)
[root@k8s-master ~]# kubectl -n myns1 get po
NAME READY STATUS RESTARTS AGE
nginx-pods 1/1 Running 2 (1s ago) 22m
livenessProbe存活探针和kubelet-httpGet
#接着上面的文档操作#删除nginx-pods 容器
[root@k8s-master ~]# kubectl -n myns1 delete pod nginx-pods
pod "nginx-pods" deleted
#复制一份pod的yaml文件
[root@k8s-master ~]# cp nginx-pod-liveness-exec.yaml nginx-pod-liveness-http.yaml
#编辑pod的yaml文件
[root@k8s-master ~]# vim nginx-pod-liveness-http.yaml
apiVersion: v1
kind: Pod
metadata:name: nginx-podsnamespace: myns1labels:app: nginx
spec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentlivenessProbe:httpGet: #指定探针探测方式path: /index.html #定义请求的URLport: 80 #定义GET的端口initialDelaySeconds: 3 #指定探针多少秒后启动periodSeconds: 3 #指定探针的探测周期#创建pod的yaml文件 -f是加载配置文件
[root@k8s-master ~]# kubectl create -f nginx-pod-liveness-http.yaml
pod/nginx-pods created
#指定myns1命名空间中查询pod资源
[root@k8s-master ~]# kubectl -n myns1 get pods
NAME READY STATUS RESTARTS AGE
nginx-pods 1/1 Running 0 15s
#删除定义文件
[root@k8s-master ~]# kubectl -n myns1 exec pods/nginx-pods -- rm -rf /usr/share/nginx/html/index.html
#指定myns1命名空间中查询pod资源
[root@k8s-master ~]# kubectl -n myns1 get pods
NAME READY STATUS RESTARTS AGE
nginx-pods 1/1 Running 0 2m16s
#指定myns1命名空间中查询pod资源
#查看pod里容器,此时存活探针探测失败,重启容器 (RESTARTS 显示1次重启)
[root@k8s-master ~]# kubectl -n myns1 get pods
NAME READY STATUS RESTARTS AGE
nginx-pods 1/1 Running 1 (0s ago) 2m24s
readinessProbe就绪探针
readinessProbe和kubelet-exec
[root@k8s-master01 ~]# vim nginx-re-exec.ymlapiVersion: apps/v1 #api版本: apps/v1
kind: Deployment #资源类型: Deployment # 部署控制器
metadata: #元数据:labels: #标签:app: nginx #应用: nginx # 标签:nginx应用name: nginx #名称: nginx # 部署名称:nginxnamespace: default #命名空间: default # 命名空间:默认
spec: #规格:replicas: 3 #副本数: 3 # 运行3个相同的Pod副本selector: #选择器:matchLabels: #匹配标签:app: nginx #应用: nginx # 选择标签为nginx的Podtemplate: #模板:metadata: #元数据:labels: #标签:app: nginx #应用: nginx # Pod标签:nginxspec: #规格:containers: #容器:- name: nginx #- 名称: nginx # 容器名称:nginximage: nginx #镜像: nginx # 镜像:官方nginx镜像imagePullPolicy: IfNotPresent #镜像拉取策略: IfNotPresent # 本地存在则不拉取ports: #端口:- containerPort: 80 #- 容器端口: 80 # 容器监听端口## 就绪探针配置readinessProbe: #指定探针 就绪探针: # 容器就绪状态检查exec: #指定探针探测方式 执行命令: # 通过执行命令检查command: #命令: # 执行的命令- cat #- cat # 查看文件命令- /usr/share/nginx/html/index.html # 检查的文件路径initialDelaySeconds: 5 #初始延迟秒数: 5 # 容器启动后等待5秒开始检查periodSeconds: 5 #探测周期秒数: 5 # 每5秒检查一次
---
# 服务配置
apiVersion: v1 #api版本: v1
kind: Service #资源类型: Service # 服务资源
metadata: #元数据:labels: #标签:svc: nginx-svc-nodepor #服务: nginx-svc-nodeport # 服务标签name: nginx-svc-nodeport #名称: nginx-svc-nodeport # 服务名称
spec: #规格:type: NodePort #类型: NodePort # 节点端口类型(外部可访问)ports: #端口:- port: 8000 ##pod的端口 # 服务端口(集群内部访问端口)targetPort: 80 ##容器内部暴露的端口 # 容器实际端口nodePort: 30080 ##对外访问端口 # 节点暴露端口(外部访问端口)selector: #选择器:app: nginx #应用: nginx # 选择标签为nginx的Pod#端口映射 30080映射8000映射80
#Deployment可以控制pod创建副本得数量
#由replicas创建,被Depolyment管理[root@k8s-master ~]# vim nginx-pod-readiness-exec.yamlapiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx1name: nginxnamespace: default
spec:replicas: 2selector:matchLabels:app: nginxtemplate:metadata:labels: #这个标签要定义好app: nginxspec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentports:- containerPort: 80readinessProbe: #指定探针httpGet: #指定探针方式path: /index.html port: 80 initialDelaySeconds: 5periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:labels:svc: nginx-svc-nodeportname: nginx-svc-nodeport
spec:type: NodePortports:- port: 80targetPort: 80nodePort: 30080selector:app: nginx#生产环境下不建议这样做
#提交
[root@k8s-master ~]# kubectl apply -f nginx-pod-readiness-exec.yaml
deployment.apps/nginx created
service/nginx-svc-nodeport created
#查询pod资源
#8595754649是为当前Deployment控制器分配得编号,
[root@k8s-master ~]# kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-8595754649-4nrzx 1/1 Running 0 14s
nginx-8595754649-ztgnk 1/1 Running 0 14s
#replicasets俩个副本
[root@k8s-master ~]# kubectl get replicasets.apps
NAME DESIRED CURRENT READY AGE
nginx-8595754649 2 2 2 103s
#两个同属于一个deployment,4nrzx和ztgnk区分这两个副本
#查看deployment
#创建成功
[root@k8s-master ~]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 2/2 2 2 116s
#查看service,类型是Nodeport
#显示有,创建成功,可以去网页访问30080端口,会显示nginx页面
[root@k8s-master ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 41h
nginx-svc-nodeport NodePort 10.101.52.101 <none> 8000:30080/TCP 2m53s[root@k8s-master ~]# iptables -t nat -nL | grep 30080
KUBE-EXT-XKWTKZBTDCMU3FHC 6 -- 0.0.0.0/0 0.0.0.0/0 /* default/nginx-svc-nodeport */ tcp dpt:30080
[root@k8s-master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-8595754649-4nrzx 1/1 Running 0 4m6s 10.244.169.150 k8s-node2 <none> <none>
nginx-8595754649-ztgnk 1/1 Running 0 4m6s 10.244.36.80 k8s-node1 <none> <none>[root@k8s-node1 ~]# iptables -t nat -nL | grep 30080
KUBE-EXT-XKWTKZBTDCMU3FHC 6 -- 0.0.0.0/0 0.0.0.0/0 /* default/nginx-svc-nodeport */ tcp dpt:30080
[root@k8s-node2 ~]# iptables -t nat -nL | grep 30080
KUBE-EXT-XKWTKZBTDCMU3FHC 6 -- 0.0.0.0/0 0.0.0.0/0 /* default/nginx-svc-nodeport */ tcp dpt:30080#[root@k8s-master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-8595754649-4nrzx 1/1 Running 0 4m6s 10.244.169.150 k8s-node2 <none> <none>
nginx-8595754649-ztgnk 1/1 Running 0 4m6s 10.244.36.80 k8s-node1 <none> <none>
[root@k8s-master ~]# kubectl exec -it pods/nginx-8595754649-ztgnk -- bash
root@nginx-8595754649-ztgnk:/#
root@nginx-8595754649-ztgnk:/# echo web1 > /usr/share/nginx/html/index.html
root@nginx-8595754649-ztgnk:/# exit
exit#Service能实现负载均衡
[root@k8s-master ~]# kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 192.168.158.33:6443 41h
nginx-svc-nodeport 10.244.169.150:80,10.244.36.80:80 34m
#查看nginx-svc-nodeport 详细信息
[root@k8s-master ~]# kubectl describe svc nginx-svc-nodeport
Name: nginx-svc-nodeport
Namespace: default
Labels: svc=nginx-svc-nodeport
Annotations: <none>
Selector: app=nginx
Type: NodePort
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.101.52.101
IPs: 10.101.52.101
Port: <unset> 8000/TCP
TargetPort: 80/TCP
NodePort: <unset> 30080/TCP
Endpoints: 10.244.169.150:80,10.244.36.80:80
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>