Kubernetes 探针
在 Kubernetes 中 Pod 是最小的计算单元,而一个 Pod 又由多个容器组成,相当于每个容器就是一个应用,应用在运行期间,可能因为某也意外情况致使程序挂掉。那么如何监控这些容器状态稳定性,保证服务在运行期间不会发生问题,发生问题后进行重启等机制,就成为了重中之重的事情,考虑到这点 kubernetes 推出了活性探针机制。有了存活性探针能保证程序在运行中如果挂掉能够自动重启,但是还有个经常遇到的问题,比如说,在 Kubernetes 中启动 Pod,显示明明 Pod 已经启动成功,且能访问里面的端口,但是却返回错误信息。还有就是在执行滚动更新时候,总会出现一段时间,Pod对外提供网络访问,但是访问却发生 404,这两个原因,都是因为 Pod 已经成功启动,但是 Pod 的的容器中应用程序还在启动中导致,考虑到这点 Kubernetes 推出了就绪性探针机制。
Kubernetes 探针类型
| 探针类型 | 检查时机 | 失败后果 | 典型应用场景 |
|---|---|---|---|
| Startup:启动探针 | 容器启动阶段 | 阻塞后续探针执行 | 慢启动应用初始化 |
| Liveness:存活探针 | 运行期间定期检查 | 重启容器(kubelet) | 检测死锁/内存泄漏 |
| Readiness:就绪探针 | 服务就绪检查 | 从Service端点移除 | 流量切换/依赖检查 |
启动探针 Startup Probe :用于判断容器内应用程序是否启动,如果配置了startupProbe,就会先禁止其他的探针,直到它成功为止,成功后将不再进行探测。(1.16版本后加入,针对容器内应用服务是否已经启动监控)
就绪探针 Readiness Probe :判断容器是否已经就绪,若未就绪,容器将会处于未就绪,未就绪的容器,不会进行流量的调度。 Kubernetes 会把 Pod 从 service endpoints 中剔除。
存活探针 Liveness Probe :判断容器内的应用程序是否正常,若不正常,根据 Pod 的restartPolicy 重启策略操作,如果没有配置该探针,默认就是success
探针的检查方法
exec:通过在容器内执行指定命令,来判断命令退出时返回的状态码,返回状态码是0表示正常。
httpGet:通过对容器的 IP 地址、端口和 URL 路径来发送 GET 请求;如果响应的状态码在 200 ~399 间,表示正常。
tcpSocket:通过对容器的 IP 地址和指定端口,进行 TCP 检查,如果端口打开,发起 TCPSocket 建立成功,表示正常。
配置说明表
| 参数 | 推荐值 | 作用说明 |
|---|---|---|
initialDelaySeconds | 慢启动应用:30+ | 延迟多少秒开始探测。避免应用未完成启动时被误判 |
periodSeconds | 生产环境≥5 | 检查间隔,高频检查会增加应用负载,默认是10s最少是1秒 |
timeoutSeconds | 1-3 | 超时时间,超过即视为失败 |
failureThreshold | 3-5 | 连续失败次数,过大延长故障恢复时间,过小易误判,默认3次最少1次 |
successThreshold | 1(Readiness可设2) | 要求连续成功次数,防止偶发成功,只能1 |
经典案例
Startup Probe 启动探针
Nginx 挂载示例
场景:Nginx前端挂载宿主机目录检测
apiVersion: v1
kind: Namespace
metadata:
name: demo-probe
labels:
app: demo
app: probe
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-start-probe
namespace: demo-probe
labels:
app: demo
app: probe
spec:
volumes:
- name: html
hostPath:
path: /data/html
containers:
- name: nginx-start-probe
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: html
mountPath: /html
startupProbe:
exec:
command: ["/bin/sh","-c","cat /html/index.html"]
initialDelaySeconds: 3
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3Tomcat 示例
场景:Tomcat 应用需要长时间初始化(加载大型配置文件)
apiVersion: v1
kind: Pod
metadata:
name: tomcat-app
spec:
containers:
- name: tomcat
image: tomcat:9.0
ports:
- containerPort: 8080
# Startup Probe 配置
startupProbe:
httpGet:
path: /manager/html
port: 8080
initialDelaySeconds: 10 # 容器启动后等待10秒开始检查
periodSeconds: 5 # 每5秒检查一次
failureThreshold: 20 # 允许最多20次失败(总等待100秒)
timeoutSeconds: 2 # 每次检查超时时间
# 其他探针(仅在startup成功后生效)
livenessProbe:
httpGet:
path: /manager/status
port: 8080
periodSeconds: 10
readinessProbe:
httpGet:
path: /manager/health
port: 8080
periodSeconds: 5Liveness Probe 存活探针
Nginx 检测
apiVersion: v1
kind: Namespace
metadata:
name: demo-probe
labels:
app: demo
app: probe
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-liveness-probe
namespace: demo-probe
labels:
app: demo
app: probe
spec:
volumes:
- name: conf
hostPath:
path: /data/nginx/conf
containers:
- name: nginx-liveness-probe
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: conf
mountPath: /etc/nginx/conf.d
ports:
- name: nginx-port
containerPort: 8080
livenessProbe:
httpGet:
port: 8080
path: /health
scheme: HTTP
initialDelaySeconds: 15 # 等待应用完成启动
periodSeconds: 10 # 每10秒检查一次
timeoutSeconds: 3 # 超时时间
failureThreshold: 3 # 连续失败3次即重启Node.js 检测
场景:检测 Node.js 应用内存泄漏(进程存在但无响应)
apiVersion: v1
kind: Pod
metadata:
name: nodejs-api
spec:
containers:
- name: nodejs
image: node:18
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: production
# Liveness Probe 配置
livenessProbe:
httpGet:
path: /health/live
port: 3000
httpHeaders:
- name: X-Liveness-Token
valueFrom:
secretKeyRef:
name: app-secrets
key: liveness-token
initialDelaySeconds: 30 # 等待应用完成启动
periodSeconds: 15 # 每15秒检查一次
failureThreshold: 2 # 连续失败2次即重启
timeoutSeconds: 3 # 超时时间
resources:
limits:
memory: "512Mi"
requests:
memory: "256Mi"Readiness Probe 服务就绪探针
场景:MySQL 服务依赖检查(确保可接受新连接)
apiVersion: v1
kind: Pod
metadata:
name: mysql-primary
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
value: '123456'
ports:
- containerPort: 3306
# Readiness Probe 配置
readinessProbe:
exec:
command:
- sh
- -c
- "mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e 'SELECT 1' && test -f /var/lib/mysql/ready"
initialDelaySeconds: 10
periodSeconds: 5
successThreshold: 1
failureThreshold: 3
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-pvc三探针组合
场景:Spring Boot 微服务(包含数据库初始化)
apiVersion: v1
kind: Pod
metadata:
name: order-service
spec:
initContainers:
- name: db-migration
image: flyway/flyway
command: ["flyway", "migrate"]
envFrom:
- configMapRef:
name: db-config
containers:
- name: java-app
image: springboot-order:2.7
ports:
- containerPort: 8080
# 三探针组合配置
startupProbe:
httpGet:
path: /actuator/health/startup
port: 8080
failureThreshold: 30 # 最长等待30 * 5=150秒
periodSeconds: 5
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
periodSeconds: 5
failureThreshold: 3
env:
- name: JAVA_OPTS
value: "-Xms512m -Xmx512m"
volumeMounts:
- name: config
mountPath: "/app/config"
volumes:
- name: config
configMap:
name: app-config