Pod 状态是 Running,但服务其实不可用;或者应用只是启动慢、依赖暂时异常,却被反复重启。这类问题大多与探针配置有关。Kubernetes 提供三种探针:存活探针(liveness)、就绪探针(readiness)和启动探针(startup),它们的职责不同,配错的代价也不同。
一句话总结:liveness 管“要不要重启”,readiness 管“要不要给流量”,startup 管“给启动留多久”。
httpGet:对指定路径和端口发 HTTP 请求,状态码在 200 到 399 之间视为成功。tcpSocket:尝试建立 TCP 连接,能连上即成功。exec:在容器内执行命令,退出码为 0 视为成功。每次检测都会创建进程,频率高时开销较大。grpc:对支持 gRPC 健康检查协议的服务进行检测,需要所用版本支持,请查阅对应版本文档。apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: myrepo/web:1.0.0
ports:
- containerPort: 8080
startupProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 5
failureThreshold: 30
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3参数含义:
periodSeconds:检测间隔。timeoutSeconds:单次检测超时,默认 1 秒,应用响应偶尔变慢时容易误判。failureThreshold:连续失败多少次才判定失败。initialDelaySeconds:容器启动后等多久开始检测。有了 startupProbe 通常不再需要设置较大的初始延迟。让 liveness 去检查数据库、缓存是否可用,一旦数据库短暂抖动,所有 Pod 同时 liveness 失败,被集体重启,反而把故障放大成雪崩。liveness 只检查进程自身是否健康,依赖状态放到 readiness 里,或者干脆只做降级处理。
应用短时间过载时,检测超时,liveness 失败导致重启,加重压力形成循环。给 liveness 设置更宽松的超时和失败次数,并让它的检查逻辑比 readiness 更简单。
为了避免启动阶段被 liveness 杀掉,只能把 initialDelaySeconds 设得很大,导致真正死锁时也要等很久才被重启。用 startupProbe 更合适:启动期间宽松,启动后恢复灵敏。
容器进程起来就被认为就绪,请求打过去时应用还在初始化,出现 502 或超时。务必为对外服务配置 readiness。
健康检查接口里做复杂查询、调用下游服务,本身就消耗资源,在高并发时反而成为负担。健康检查应当轻量、快速。
# 查看 Pod 事件,探针失败会有记录
kubectl describe pod <pod名>
# 查看容器重启次数与上一次终止原因
kubectl get pod <pod名> -o wide
kubectl get pod <pod名> -o jsonpath='{.status.containerStatuses[0].lastState}'
# 查看服务的后端是否包含该 Pod
kubectl get endpoints <service名>事件里出现 Liveness probe failed 或 Readiness probe failed,并附带失败原因(超时、状态码、连接被拒绝)。如果 Endpoints 中缺少某个 Pod 的地址,说明它未通过 readiness。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。