Kubernetes 应用健康检查
应用的状态可以被实时观测:
- 健康状态资源使用
- 实时日志
- Liveness Probe(就绪探针)
- Readness(存活探针)
应用健康状态
探测方式
- httpGet 发送 HTTP 请求返回200-399状态码表明容器健康
- Exec 通过执行命令来检查服务是否正常,命令返回0表示容器健康
- tcpSocket 通过容器的 IP 和端口执行 TCP 检查,如果能够建立 TCP 连接表示容器健康
探测结果
- Success 容器通过了检查
- Failure 容器未通过检查
- Unknown 未能执行检查,不采取任何操作
重启策略
- Always 总是重启
- OnFailure 失败才重启
- Never 永不重启
API 对象
exec
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: k8s.gcr.io/busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600;
livenessProb:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
httpGet
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
image: k8s.gcr.io/liveness
args:
- /server
livenessProb:
httpGet:
path: /healthz
port: 8000
httpHeaders:
- name: Custom-Header
value: Awesome
initialDelaySeconds: 5
periodSeconds: 5
tcpSocket
apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: k8s.gcr.io/goproxy:0.1
ports:
- containerPort: 8000
readnessProbe:
tcpSocket:
port: 8000
initialDelaySeconds: 5
periodSecond: 10
livenessProbe:
tcpSocket:
port: 8000
initialDelaySeconds: 5
periodSecond: 20
参数
- initialDelaySeconds Pod 启动后延迟多久进行检查
- periodSeconds 检查的间隔时间
- timeoutSeconds 探测的超时时间
- successThreshold 探测失败后再次判断成功的阈值
- failureThreshold 探测失败的重试次数
Liveness(存活探针) | Readness(就绪探针) | |
---|---|---|
作用 | 用于判断容器是否存活,即 Pod 状态是否为 Running,如果 Liveness 探针判断容器不健康,会触发 kubelet 杀掉容器,并根据配置的策略判断是否重启容器,如果不配置 Liveness 探针,则认为返回值默认为成功。 | 用于判断容器是否启动完成,即 Pod 是否为 Ready,如果探测结果不成功,会将 Pod 从 Endpoint 中移除,直至下次判断成功,再将 Pod 挂回到 Endpoint 上。 |
检测失败 | 杀掉 Pod | 切断上层流量到 Pod |
适用场景 | 支持重新拉起的应用 | 启动后无法立即对外服务的应用 |
注意事项
- 调大判断的超时阈值,防止在容器压力较高的情况下出现偶发超时
- 调整判断的次数阈值,3次默认值在短周期下不一定是最佳实践
- exec 如果执行的是 shell 脚本判断,在容器中可能调用时间会非常长
- 使用 tcpSocket 的方式遇到 TLS 场景,需要业务层判断是否有影响
应用故障排查
Pod 停留在 Pending❓
调度器没有介入,可以通过 kubectl describe pod
,查看事件排查,通常和资源使用相关
Pod 停留在 waiting❓
一般表示 Pod 的镜像没有正常拉取
Pod 不断被拉起且可以看到 crashing❓
通常表示 Pod 已经完成调度并启动,但是启动失败,通常是由于配置、权限造成,需要查看 Pod 日志
Pod 处在 Running 但是没有正常工作❓
通常是由于部分字段拼写错误造成的,可通过校验部署来排查 kubectl apply -validate -f pod.yaml
Service 无法正常工作❓
在排除网络插件自身的问题外,最可能的是 label 配置有问题,可以通过查看 endpoint 的方式进行检查
应用远程调试
进入一个正在运行的 Pod❓
$ kubectl exec -it pod_name /bin/bash
进入一个正在运行包含多容器的 Pod❓
$ kubectl exec -it pod_name -c container_name /bin/bash
Service 远程调试
当集群中应用依赖的应用需要本地调试时: 可以使用 Telepresence 将本地的应用代理到集群中的一个 Service 上
Telepresence --swap-deployment $DEPLOYMENT_NAME
当本地开发的应用需要调用集群中的服务时: 可以使用 Port-Forward 将远程的应用代理到本地的端口上
$ kubectl port-forward svc/app -n app_namespace
kubectl-debug 调试工具
https://github.com/aylei/kubectl-debug