Kubernetes容器编排故障排查手册:从Pod CrashLoop到网络策略的实战诊断

Kubernetes故障排查为什么需要结构化方法论

K8s集群的故障表现往往与根因不在同一层级——Pod报CrashLoopBackOff可能是应用代码问题,也可能是资源配置错误或Secret挂载失败。无头排查容易在错误方向浪费时间。结构化排查的顺序是:集群级→节点级→Pod级→容器级→应用级,逐层缩小范围。

Pod CrashLoopBackOff的五种常见根因与诊断命令

CrashLoopBackOff是最常见也最令人困惑的Pod状态,本质是容器反复启动后退出。逐条排查:

1. 应用启动失败(退出码非0)

# 查看容器退出码和上次日志
kubectl get pod <pod-name> -o jsonpath='{.status.containerStatuses[0].lastState.terminated.exitCode}'
kubectl logs <pod-name> --previous

# 退出码1:应用错误,看日志定位具体异常
# 退出码137:OOMKilled,内存不足被杀
# 退出码139:Segfault,通常是C库或JNI问题

2. 存活探针配置过于激进

# 检查探针配置
kubectl get pod <pod-name> -o yaml | grep -A10 livenessProbe

# 常见问题:initialDelaySeconds太短,应用还没初始化完就被探测
# 修复:把initialDelaySeconds设为应用实际启动耗时的1.5倍
livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 30   # 根据实际启动时间调整
  periodSeconds: 10
  failureThreshold: 3

3. ConfigMap或Secret挂载失败

# 查看Events中的挂载错误
kubectl describe pod <pod-name> | grep -A5 Warning

# 典型错误:"secret <name> not found"——Secret在另一个namespace
# 修复:确保Secret与Pod在同一个namespace,或使用cross-namespace引用

4. 资源Limit设置不合理

# 查看实际资源使用vs限制
kubectl top pod <pod-name> --containers
kubectl get pod <pod-name> -o jsonpath='{.spec.containers[0].resources}'

# CPU Throttle误判:limits.cpu设太低,应用看起来慢但不报错
# 区分OOM和CPU throttle:OOM会重建容器,throttle只是变慢

5. Init容器执行失败

# 查看Init容器状态
kubectl get pod <pod-name> -o jsonpath='{.status.initContainerStatuses}'
kubectl logs <pod-name> -c <init-container-name>

Service与网络策略的连通性诊断

服务不可达是第二大类故障。排查链路:Service→Endpoint→NetworkPolicy→DNS。

# 1. 检查Service是否有后端Endpoint
kubectl get endpoints <svc-name>
# 如果ENDPOINTS是<none>,说明selector匹配不到Pod

# 2. 在集群内测试连通性
kubectl run tmp-shell --rm -i --tty --image busybox -- sh
# 在临时Pod内:
wget -qO- <svc-name>.<namespace>.svc.cluster.local:8080
nslookup <svc-name>.<namespace>.svc.cluster.local

# 3. 检查NetworkPolicy是否阻断流量
kubectl get networkpolicy -n <namespace>
kubectl describe networkpolicy <policy-name> -n <namespace>

NetworkPolicy的坑在于默认行为——如果namespace中存在任何允许入站的Policy,未匹配的流量会被拒绝而不是允许。排查时用kubectl describe逐条检查规则是否遗漏了必要的端口或来源。

节点NotReady的排查路径

节点NotReady通常由kubelet问题引起,排查顺序:

# 1. SSH到故障节点,检查kubelet状态
systemctl status kubelet
journalctl -u kubelet --since "1 hour ago" | tail -50

# 2. 检查节点资源压力(磁盘/内存/PID)
df -h /var/lib/kubelet    # 磁盘使用率超过85%会触发驱逐
free -h
ps -e --no-headers | wc -l  # PID数量

# 3. 检查节点条件
kubectl describe node <node-name> | grep -A5 Conditions

# 4. 常见修复
# 磁盘满:清理旧容器镜像
crictl rmi --prune
# PID耗尽:调整kubelet的pidLimit
# kubelet证书过期:重新签发证书

集群级故障的应急响应流程

etcd不可用是集群级故障中最严重的场景——所有写操作都会失败。应急步骤:

# 检查etcd集群健康
ETCDCTL_API=3 etcdctl endpoint health \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

# 如果多数节点不可用,集群已丧失写入能力
# 不要尝试重启所有etcd节点——会造成数据丢失
# 正确做法:保留一个数据最完整的节点,移除故障节点后逐一恢复
ETCDCTL_API=3 etcdctl member remove <failed-member-id>

故障排查的关键不是记住所有命令,而是掌握分层诊断的方法论。从集群到应用逐层缩小范围,每一层用对应的诊断工具确认状态,避免盲目猜测。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-rong-qi-bian-pai-gu-zhang-pai-cha-shou-ce-cong/

(0)
小编小编
上一篇 17小时前
下一篇 17小时前

相关推荐

Kubernetes容器编排故障排查手册:从Pod CrashLoopBackOff到节点NotReady的诊断链路

K8s故障排查的核心思路:从事件到根因的递进式诊断

Kubernetes容器编排环境的故障排查和传统单机运维完全不同。一个服务不可用,可能涉及Pod、Deployment、Service、Ingress、节点等多个层级。DevOps实践中最有效的诊断路径是自底向上:先看Pod状态,再看节点状态,最后排查网络和存储。这条诊断链路覆盖了90%以上的K8s生产故障场景。SRE稳定性工程的核心就是把这条链路标准化、工具化,把平均故障恢复时间(MTTR)压到最低。

Pod CrashLoopBackOff:最常见也最容易误判的故障

Pod反复崩溃重启,kubectl get pods显示CrashLoopBackOff状态。排查步骤:

# 第一步:查看Pod事件
kubectl describe pod <pod-name> -n <namespace>

# 第二步:查看容器日志(前一次崩溃的日志)
kubectl logs <pod-name> -n <namespace> --previous

# 第三步:查看当前日志
kubectl logs <pod-name> -n <namespace>

# 第四步:检查容器退出码
kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.status.containerStatuses[0].lastState.terminated.exitCode}'

常见退出码含义:

  • Exit Code 0:进程正常退出(检查是否缺少前台阻塞进程导致容器立即退出)
  • Exit Code 137:OOMKilled,内存超限被杀,需要调大resources.limits.memory
  • Exit Code 139:Segfault,应用本身内存越界,需要检查代码或依赖库版本
  • Exit Code 1:应用启动失败,通常是配置文件错误或依赖服务不可达
# 快速定位OOM问题
kubectl describe pod <pod-name> -n <namespace> | grep -A5 "Last State"

# 临时调大内存限制验证
kubectl set resources deployment <deploy-name> -n <namespace> \
  --containers=<container-name> \
  --limits=memory=1Gi \
  --requests=memory=512Mi

ImagePullBackOff:镜像拉取失败的系统性排查

镜像拉取失败在生产环境中往往不是镜像本身的问题,而是网络、认证或存储驱动层面的故障。

# 查看详细错误信息
kubectl describe pod <pod-name> -n <namespace> | grep -A10 Events

# 在节点上直接测试镜像拉取
crictl pull <registry>/<image>:<tag>

# 检查节点上的容器运行时配置
cat /etc/containerd/config.toml | grep -A5 registry

根因分类:

  1. 认证失败:私有Registry未配置imagePullSecrets,或Secret过期
  2. 网络不通:节点无法访问Registry,检查DNS解析和防火墙策略
  3. 镜像不存在:Tag拼写错误或镜像已被删除
  4. 存储驱动:节点磁盘满或overlayfs异常
# 创建Registry认证Secret
kubectl create secret docker-registry regcred \
  --docker-server=registry.example.com \
  --docker-username=robot\$pull \
  --docker-password=<token> \
  --docker-email=admin@example.com \
  -n <namespace>

# 在Deployment中引用
kubectl patch serviceaccount default -n <namespace> \
  -p '{"imagePullSecrets": [{"name": "regcred"}]}'

节点NotReady:从kubelet到基础设施的逐层排查

节点变为NotReady状态,意味着kubelet无法正常向API Server上报节点状态。Docker自动化部署和容器管理的底层依赖出问题,上层所有Pod都会受影响。

# 查看节点状态和条件
kubectl describe node <node-name> | grep -A15 "Conditions"

# SSH到节点检查kubelet
systemctl status kubelet
journalctl -u kubelet --since "10 minutes ago"

# 检查节点资源使用
df -h        # 磁盘
free -h      # 内存
top          # CPU

# 检查容器运行时
systemctl status containerd
crictl ps

NotReady的常见根因:

  • 磁盘满:kubelet无法写入日志和数据,Docker image目录占满磁盘
  • PLEG超时:容器运行时响应慢,通常是docker/containerd的日志文件过大
  • 网络插件异常:CNI Pod崩溃导致节点网络配置丢失
  • 内核问题:内核死锁或cgroup内存泄漏
# 清理节点磁盘空间(紧急处理)
crictl rmi --prune  # 清理无用镜像
journalctl --vacuum-size=200M  # 清理系统日志
find /var/log/containers -name "*.log" -size +100M -delete

# 重启kubelet恢复节点
systemctl restart kubelet

Service与Ingress连通性问题

Pod正常但Service不可达,排查链路:

# 1. 检查Endpoints是否正常
kubectl get endpoints <svc-name> -n <namespace>

# 2. 在集群内测试Service连通性
kubectl run test --image=busybox -it --rm -- wget -qO- <svc-name>:<port>

# 3. 检查kube-proxy
kubectl logs -n kube-system -l k8s-app=kube-proxy
iptables -t nat -L KUBE-SERVICES | grep <svc-cluster-ip>

# 4. Ingress Controller日志
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx

Service没有Endpoints通常是selector标签不匹配。Ingress 404/502则需要检查后端Pod的readinessProbe配置。

监控告警体系:故障预警与自动化诊断

故障排查不能全靠人工巡检。完善的监控告警体系应该覆盖:

  1. Pod级别:RestartCount > 3 触发告警,CrashLoopBackOff 立即告警
  2. 节点级别:DiskPressure、MemoryPressure、NotReady 状态变更
  3. 集群级别:API Server延迟P99 > 500ms,etcd磁盘延迟 > 100ms
  4. 业务级别:Service错误率 > 1%,P99延迟 > 2s
# Prometheus规则示例:Pod重启告警
- alert: PodCrashLoopBackOff
  expr: rate(kube_pod_container_status_restarts_total[15m]) * 60 * 5 > 0
  for: 5m
  labels:
    severity: critical
  annotations:
    summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} is crash looping"
    runbook: "https://ops.internal/runbook/pod-crashloop"

K8s故障排查的效率取决于两个因素:对架构分层的理解深度,以及诊断工具链的完备度。把describe、logs、events这三板斧用熟练,配合监控告警体系做自动化预警,大部分故障都能在5分钟内定位到根因。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-rong-qi-bian-pai-gu-zhang-pai-cha-shou-ce-cong/

(0)
小编小编
上一篇 17小时前
下一篇 17小时前

相关推荐