Top 10 Kubernetes故障排除技巧

引言

无论Kubernetes多么流行,它仍可能让最资深的 DevOps 工程师感到棘手。尽管它在大规模处理容器化应用方面表现出色,但也带来了独特的故障排除挑战。本文翻译总结来middleware官网,探讨每位DevOps工程师都应掌握的十大Kubernetes故障排除技巧,这些技巧源自实际场景,可帮助快速、可靠地解决常见及关键问题。

https://middleware.io/blog/kubernetes-troubleshooting-techniques

本文包含哪些内容

1.修复 Pod 中的 CrashLoopBackOff 错误2.Kubernetes 故障排除:部署失败之 ImagePullBackOff3.Kubernetes 故障排除:修复节点未就绪(NotReady)错误4.诊断服务和网络问题:Pending 错误5.Kubernetes 高资源使用率故障排除:解决 OOMKilled 错误6.Kubernetes 存储故障排除:解决 PVC 挂起(Pending)错误7.使用事件和审计日志:深入系统分析8.使用 Kubernetes Dashboard 及可视化工具9.实现健康检查和探针(Probe)10.高级调试技术使用:Middleware 等监控和追踪工具

1.修复Pod中的CrashLoopBackOff错误

CrashLoopBackOff 是 Kubernetes 中最常见且令人沮丧的问题之一:Pod 在重启过程中反复崩溃,原因是容器无法正确启动,Kubernetes 持续尝试重启导致失败循环。

步骤1:列出所有Pod

首先通过以下命令了解命名空间中所有 Pod 的状态,定位异常 Pod:

kubectl get pods

输出会显示每个Pod的状态重启次数运行时长,状态为 CrashLoopBackOff 的 Pod 需优先处理。

步骤2:描述受影响的Pod

确定问题 Pod 后,使用 describe 命令查看其内部细节(配置、近期事件、错误信息):

kubectl describe pod <pod-name>

重点关注 Events(事件) 部分,可定位镜像拉取失败、配置缺失、权限错误等问题。

步骤3:查看容器日志

日志是理解容器内部故障的关键,若 Pod 崩溃前未生成日志,可通过 --previous 查看上一次失败实例的日志:

kubectl logs <pod-name> --previous

示例场景

  1. 运行kubectl get pods发现异常:
my-webapp-pod   0/1   CrashLoopBackOff   5 (2m ago)
  1. 查看上一次失败日志:
kubectl logs my-webapp-pod --previous
# 输出:Error: DATABASE_URL environment variable is not set; Process exiting with code 1
  1. 根因:容器缺少 DATABASE_URL 环境变量,补充配置后即可修复。

2.Kubernetes故障排除部署失败之ImagePullBackOff

当 Kubernetes 因认证问题镜像名称错误无法拉取容器镜像时,会触发 ImagePullBackOff 错误。

步骤 1:识别有问题的部署

先通过以下命令检查部署状态,重点关注 READY(就绪) 列(如“0/3”表示无 Pod 成功启动):

kubectl get deployments

如需更详细信息(Pod 模板、事件),运行:

kubectl describe deployment <deployment-name>

步骤2:监控部署状态和历史

  • 实时跟踪部署进度:
kubectl rollout status deployment <deployment-name>
  • 查看部署历史(定位哪个版本引入问题):
kubectl rollout history deployment <deployment-name>

步骤3:调查ImagePullBackOff根因

  1. 列出Pod并确认错误状态:
kubectl get pods
# 输出:my-app-7d4b8c8f-xyz   0/1   ImagePullBackOff   0   2m
  1. 描述Pod查看具体错误:
kubectl describe pod my-app-7d4b8c8f-xyz
# 输出:Failed to pull image "private-registry.com/my-app:v1.2.3": pull access denied

根因:私有镜像仓库认证失败。

步骤4:使用Secret修复ImagePullBackOff

  1. 创建存储私有仓库凭据的Secret:
kubectl create secret docker-registry my-registry-secret \
  --docker-server=private-registry.com \
  --docker-username=<your-username> \
  --docker-password=<your-password> \
  --docker-email=<your-email>
  1. 更新部署以引用该Secret:
kubectl patch deployment my-app -p '{"spec":{"template":{"spec":{"imagePullSecrets":[{"name":"my-registry-secret"}]}}}}'
  1. 监控修复后的部署:
kubectl rollout status deployment my-app

3.Kubernetes故障排除修复节点未就绪(NotReady)错误

节点出现 NotReady 状态会阻碍 Pod 调度、干扰工作负载,通常原因是 kubelet 与服务器通信失败 或 节点健康检查未通过

步骤1:检查节点状态

通过以下命令查看所有节点的状态、容器运行时、IP 等信息:

kubectl get nodes -o wide

-o wide 可显示额外上下文(如 OS 版本、子网信息),帮助定位节点级问题。

步骤2:检查节点资源和健康状态

查看节点的资源容量(CPU、内存)和健康条件,识别资源过载问题:

kubectl describe node <node-name> | grep -A 5 "Capacity\|Allocatable"

步骤3:示例:修复磁盘压力(DiskPressure)问题

  1. 发现节点 worker-node-1 状态为 NotReady
kubectl get nodes
# 输出:worker-node-1   NotReady   5d   v1.28.0
  1. 描述节点查看根因:
kubectl describe node worker-node-1
# 输出:Conditions: DiskPressure True (KubeletHasDiskPressure: kubelet has disk pressure)
  1. 清理系统日志释放磁盘空间:
sudo journalctl --vacuum-time=3d  # 删除 3 天前的日志

清理后,kubelet 会自动将节点恢复为 Ready 状态。

4.诊断服务和网络问题Pending错误

Pod 或服务卡在 Pending 状态通常源于 标签选择器不匹配网络配置错误 或 DNS 解析失败

步骤1:验证服务配置

  1. 列出所有服务,查看网络详情(IP、端口):
kubectl get services --all-namespaces
  1. 检查服务的Endpoint(若为空,说明无 Pod 匹配服务的选择器):
kubectl get endpoints <service-name>
  1. 描述服务,确认选择器标签与 Pod 标签一致:
kubectl describe service <service-name>

步骤2:检查集群DNS问题

若微服务间通信失败,需验证 DNS 解析:

  1. 在 od内部运行 nslookup 测试服务解析:
kubectl exec -it <pod-name> -- nslookup <service-name>
kubectl exec -it <pod-name> -- nslookup <service-name>.<namespace>.svc.cluster.local

若无法解析到IP,说明集群 DNS 配置异常。

  1. 测试HTTP连通性:
kubectl exec -it <pod-name> -- wget -qO- <service-name>:<port>/health

若请求失败,需检查服务配置、网络策略或选择器匹配问题。

5. Kubernetes高资源使用率故障排除解决OOMKilled错误

当容器超出分配的内存限制时,Kubernetes 会强制终止容器,触发 OOMKilled 错误,可能导致 Pod 驱逐、应用 downtime。

步骤1:检查资源使用率

  1. 查看节点级资源使用情况(识别高内存节点):
kubectl top nodes

内存使用率超过 80% 的节点易触发 OOMKilled 错误。

  1. 查看 Pod 级资源使用,按 CPU/内存排序:
kubectl top pods --all-namespaces --sort-by=cpu
kubectl top pods --all-namespaces --sort-by=memory

步骤2:检查资源配额和自动扩缩容

  1. 查看所有命名空间的资源配额:
kubectl describe quota --all-namespaces
  1. 监控 Pod 实时内存消耗(每 5 秒刷新,识别内存泄漏):
watch -n 5 'kubectl top pod <pod-name>'

步骤3:检查Pod资源请求和限制

查看 Pod 是否配置了合理的内存限制(无限制可能导致资源滥用):

kubectl describe pod <pod-name> | grep -A 10 "Requests\|Limits"

步骤4:缓解资源问题

通过 Horizontal Pod Autoscaling(HPA) 自动扩缩容,避免资源过载:

  1. 基于CPU使用率(70%)配置HPA:
kubectl autoscale deployment <deployment-name> --cpu-percent=70 --min=2 --max=10
  1. 验证HPA状态:
kubectl get hpa
kubectl describe hpa <deployment-name>

6.Kubernetes存储故障排除解决PVC挂起(Pending)错误

PersistentVolumeClaim(PVC)处于 Pending 状态意味着应用无法访问持久化数据,通常原因是 存储类配置错误卷供应器缺失 或 集群存储不足

步骤1:检查PV和PVC状态

列出所有 PersistentVolume(PV)和 PVC,查看其 状态(是否绑定)、访问模式 和 容量

kubectl get pv,pvc --all-namespaces

步骤2:排查PVC挂起原因

描述 PVC,重点关注 Events 部分,定位根因(如无匹配 PV、存储类不存在):

kubectl describe pvc <pvc-name>

步骤3:验证存储类

  1. 列出所有可用存储类:
kubectl get storageclass
  1. 描述存储类,确认供应器和参数配置正确:
kubectl describe storageclass <storageclass-name>

步骤4:示例:修复存储类不匹配问题

  1. 描述 PVC 发现错误:
kubectl describe pvc my-data-pvc
# 输出:Warning ProvisioningFailed  storageclass.storage.k8s.io "fast-ssd" not found
  1. 确认可用存储类:
kubectl get storageclass
# 输出:standard (default), gp2
  1. 更新PVC,引用存在的存储类(如 gp2),问题解决。

7.使用事件和审计日志:深入系统分析

Kubernetes 事件和审计日志是调试的核心工具,可追踪“发生了什么、何时发生、为何发生”,为根因分析提供时间线。

步骤1:使用Kubernetes事件

事件记录集群内部活动,可按时间排序、过滤警告类型或实时监控:

  • 按时间排序查看所有事件(最新事件在末尾):
kubectl get events --all-namespaces --sort-by='.metadata.creationTimestamp'
  • 过滤特定时间后的事件:
kubectl get events --field-selector='lastTimestamp>2023-10-01T10:00:00Z'
  • 仅查看警告事件:
kubectl get events --field-selector type=Warning
  • 实时监控事件:
kubectl get events --watch
  • 过滤特定 Pod/服务的事件:
kubectl get events --field-selector involvedObject.name=<pod-name>
  • 定位Pod调度失败原因:
kubectl get events --field-selector reason=FailedScheduling

步骤2:使用审计日志进行深度排查

审计日志记录 API 层面的“谁做了什么”,适用于安全调查或追踪管理员操作(默认未启用,需配置审计策略)。

示例审计策略配置

apiVersion: audit.k8s.io/v1
kind:Policy
rules:
-level:RequestResponse# 记录请求和响应详情
resources:
-group:""
    resources:["pods","services"]
-group:"apps"
    resources:["deployments","replicasets"]
-level:Request# 仅记录请求
resources:
-group:""
    resources:["configmaps","secrets"]

审计日志示例(关键信息)

{
  "auditID": "4d2c8b7a-f3e1-4b2a-9c8d-1e3f5a7b9c2d",
  "verb": "delete",  # 操作类型
  "user": {"username": "admin@company.com"},  # 操作人
  "sourceIPs": ["192.168.1.100"],  # 来源 IP
  "objectRef": {"resource": "pods", "name": "web-app-7d4b8c9f-xyz"},  # 目标资源
  "responseStatus": {"code": 200}  # 操作结果
}

8. 使用Kubernetes Dashboard及可视化工具

kubectl 等命令行工具功能强大,但可视化工具(如 Kubernetes Dashboard、Middleware)可简化集群管理,直观展示指标、日志和事件的关联模式。

步骤1:部署和使用Kubernetes Dashboard

Kubernetes Dashboard 是基于 Web 的 UI,默认未安装(出于安全考虑),部署步骤如下:

  1. 部署 Dashboard:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
  1. 创建管理员服务账户:
kubectl create serviceaccount dashboard-admin -n kubernetes-dashboard
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:dashboard-admin
  1. 生成访问令牌:
kubectl create token dashboard-admin -n kubernetes-dashboard
  1. 访问Dashboard:
    • 运行 kubectl proxy,通过浏览器访问:http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
    • 输入步骤 3 生成的令牌登录。

Dashboard核心功能

  • 实时监控 CPU/内存使用率趋势
  • 可视化事件时间线
  • 查看资源间依赖关系
  • 浏览器内流式查看应用日志·

步骤2:使用Middleware等第三方可视化工具

Kubernetes Dashboard 缺乏完整的可观测性,Middleware 等工具可整合 指标、日志、追踪和告警,提供统一视图。

部署MiddlewareAgent(DaemonSet 方式)

apiVersion: apps/v1
kind:DaemonSet
metadata:
name:middleware-agent
namespace:middleware
spec:
selector:
    matchLabels:
      app:middleware-agent
template:
    metadata:
      labels:
        app:middleware-agent
    spec:
      containers:
      -name:middleware-agent
        image:middleware/agent:latest
        env:
        -name:MW_API_KEY
          valueFrom:
            secretKeyRef:
              name:middleware-secret
              key:api-key
        -name:MW_TARGET

集成后,你可以可视化你的容器组,从各种来源收集指标,还能监控部署状态。

9. 实施健康检查和探针

Kubernetes 中的健康检查类似常规体检,可帮助及早发现问题并确保所有组件按预期运行。Kubernetes 通过探针(Probes) 监控应用容器的健康状态与可用性,当检测到异常时,集群能自动执行重启容器、停止流量路由等操作,避免故障扩散。

9.1 了解就绪探针和存活探针

Kubernetes 提供三种探针,每种探针在维护容器健康中承担特定角色,需根据应用场景组合使用:

探针类型(Probe Type)核心作用触发动作适用场景
存活探针(Liveness Probe)检查容器是否“存活”(正常运行)连续失败时,自动重启容器应用死锁、进程挂起等无法自我恢复的场景
就绪探针(Readiness Probe)检查容器是否“就绪”(可接收流量)失败时,将容器从服务端点移除应用启动中(如加载配置、初始化数据库)、临时依赖不可用(如缓存宕机)的场景
启动探针(Startup Probe)为启动慢的应用提供额外初始化时间失败时,重启容器;成功后,激活其他探针大型应用、数据库(如 MySQL、Elasticsearch)等启动耗时超过默认阈值的场景

9.2 Example: Configuring All Three Probes(示例:配置所有三种探针)

以下是在单个 Deployment 中组合三种探针的完整配置,可根据应用特性调整参数:

apiVersion: apps/v1
kind:Deployment
metadata:
name:web-application
spec:
replicas:3
selector:
    matchLabels:
      app:web-application
template:
    metadata:
      labels:
        app:web-application
    spec:
      containers:
      -name:web-app
        image:my-app:v1.2.3
        ports:
        -containerPort:8080
        
        # 1. 启动探针:给应用足够的初始化时间
        startupProbe:
          httpGet:
            path:/health/startup# 应用自定义的启动健康检查接口
            port:8080
          initialDelaySeconds:10# 容器启动后,延迟10秒再开始检查
          periodSeconds:5        # 每5秒检查一次
          timeoutSeconds:3       # 每次检查超时时间(超过视为失败)
          failureThreshold:30    # 允许30次失败(30*5=150秒启动窗口期)
          successThreshold:1     # 1次成功即视为启动完成
        
        # 2. 存活探针:确保容器持续健康
        livenessProbe:
          httpGet:
            path:/health/live     # 应用自定义的存活检查接口
            port:8080
          initialDelaySeconds:30# 等待启动探针成功后,再延迟30秒开始检查
          periodSeconds:10       # 每10秒检查一次
          timeoutSeconds:5
          failureThreshold:3     # 连续3次失败则重启容器
          successThreshold:1
        
        # 3. 就绪探针:确保容器可接收流量
        readinessProbe:
          httpGet:
            path:/health/ready    # 应用自定义的就绪检查接口
            port:8080
          initialDelaySeconds:5   # 容器启动后5秒开始检查(无需等待启动探针)
          periodSeconds:5        # 每5秒检查一次
          timeoutSeconds:3
          failureThreshold:3     # 连续3次失败则移除流量
          successThreshold:1
        
        # 资源限制(配合探针避免资源耗尽)
        resources:
          requests:
            memory:"256Mi"
            cpu:"250m"
          limits:
            memory:"512Mi"
            cpu:"500m"

9.3 探针协同工作逻辑

  1. 启动探针优先执行:容器启动后,启动探针每5秒检查一次,允许150秒内完成初始化(如加载依赖、创建数据库连接)。此阶段,存活探针和就绪探针会暂停,避免误判“未启动完成”为故障。
  2. 存活探针接管健康监控:启动探针成功后,存活探针每10秒检查一次。若应用死锁(如线程阻塞)导致/health/live接口返回非200状态,连续3次失败后,Kubernetes 会自动重启容器,恢复服务。
  3. 就绪探针控制流量路由:就绪探针独立运行,若应用因临时依赖(如 Redis 缓存宕机)导致/health/ready接口失败,Kubernetes 会将该容器从 Service 负载均衡中移除,避免流量发送到“无法处理请求”的实例;当依赖恢复后,探针成功,容器会重新加入流量池。

10. 高级调试技术

标准调试方法(如kubectl logskubectl describe)可解决大部分日常问题,但面对复杂场景(如性能瓶颈、网络深层问题、生产环境无重启调试),需使用更高级的技术,在不影响业务的前提下定位根因。

10.1 使用临时容器进行实时调试

临时容器(Ephemeral Containers) 是 Kubernetes 1.23+ 支持的特性,可在不重启 Pod、不修改原有容器状态的前提下,临时注入调试容器到运行中的 Pod 内,尤其适合生产环境调试(避免停机)。

10.1.1 基础使用:注入调试容器

场景1:注入轻量调试容器(Busybox)

适用于简单命令(如pingls)调试:

# 格式:kubectl debug <Pod名> -it --image=<调试镜像> --target=<目标容器名>
kubectl debug web-app-7d4b8c9f-xyz -it --image=busybox --target=web-app
  • -it:交互式终端,允许输入命令;
  • --target=web-app:指定调试目标容器(共享网络、PID 命名空间,可查看目标容器的进程和网络);
  • 进入容器后,可执行ps aux(查看目标容器进程)、netstat -tuln(查看端口占用)等命令。

场景2:注入带完整工具的容器(Ubuntu/Netshoot)

若需复杂工具(如curltcpdumpdig),使用ubuntu或专门的网络调试镜像nicolaka/netshoot

# 注入 Netshoot 容器(适合网络问题调试)
kubectl debug web-app-7d4b8c9f-xyz -it --image=nicolaka/netshoot --target=web-app

10.1.2 实战示例:排查网络连接问题

问题现象:Web 应用间歇性无法连接数据库服务(database-service:5432

  1. 注入 Netshoot 调试容器:
kubectl debug web-app-7d4b8c9f-xyz -it --image=nicolaka/netshoot --target=web-app
  1. 在调试容器内执行诊断命令:
    • 检查 DNS 解析:
nslookup database-service.default.svc.cluster.local  # 验证服务域名是否解析到正确IP
dig database-service  # 查看DNS服务器返回结果,排查解析延迟/失败
- 测试端口连通性:
telnet database-service 5432  # 检查端口是否开放(连接成功则端口正常)
nc -zv database-service 5432  # 更简洁的端口测试(-z:只检测端口,不发送数据)
- 抓包分析流量:
tcpdump -i any port 5432 -w db-traffic.pcap  # 抓取数据库端口流量到文件
# 后续可通过 kubectl cp 下载文件分析:
kubectl cp web-app-7d4b8c9f-xyz:/db-traffic.pcap ./local-pcap/
- 查看网络接口和路由:
ip addr show  # 查看Pod内网络接口(确认IP是否在正确网段)
ip route  # 查看路由表(确认到数据库服务的路由是否存在)

10.2 kubectl debug扩展场景

kubectl debug 除了注入临时容器,还支持更灵活的调试模式,覆盖节点级、Pod 复制等场景。

10.2.1 场景1:创建Pod调试副本(避免影响原 Pod)

若原 Pod 是生产核心实例,可复制一个完全相同的 Pod 用于调试(修改镜像或配置,不影响原服务):

# 格式:kubectl debug <原Pod名> --copy-to=<新Pod名> --set-image=<原容器名>=<调试镜像> -- sleep 1d
kubectl debug web-app-7d4b8c9f-xyz \
  --copy-to=web-app-debug \
  --set-image=web-app=ubuntu \  # 将原应用镜像替换为Ubuntu(方便调试)
  -- sleep 1d  # 让新Pod持续运行1天(足够调试时间)
  • 新 Pod 会继承原 Pod 的所有配置(环境变量、挂载卷、资源限制),但使用调试镜像;
  • 进入新 Pod 调试:
kubectl exec -it web-app-debug -- bash
# 可执行任意命令(如检查配置文件、测试依赖连接),无需担心影响原服务

10.2.2 场景2:节点级调试(排查节点底层问题)

当节点出现 NotReady、资源异常(如磁盘满、kubelet 故障)时,可通过 kubectl debug 启动特权容器,直接访问节点的文件系统和系统服务:

# 格式:kubectl debug node/<节点名> -it --image=<调试镜像>
kubectl debug node/worker-node-1 -it --image=ubuntu
  • 进入容器后,通过 chroot /host 切换到节点的根文件系统,访问节点级资源:
chroot /host  # 切换到节点根目录(相当于直接操作节点)
systemctl status kubelet  # 查看kubelet服务状态(排查节点NotReady原因)
journalctl -u kubelet -f  # 实时查看kubelet日志(定位启动失败问题)
df -h  # 查看节点磁盘使用情况(排查DiskPressure问题)
free -m  # 查看节点内存使用(排查MemoryPressure问题)

10.2.3 场景3:性能分析(注入 profiling 容器)

若应用存在 CPU 高占用、内存泄漏,可注入带性能分析工具的容器(如 Go 语言 pprof):

# 注入 Golang 容器(用于分析 Go 应用性能)
kubectl debug web-app-7d4b8c9f-xyz -it --image=golang:1.21 --target=web-app
  • 进入容器后,使用 pprof 分析目标容器的进程:
# 1. 找到目标容器的进程ID(共享PID命名空间,可直接查看)
ps aux | grep web-app  # 假设目标进程PID为1234
# 2. 启动pprof,监听端口供本地分析
go tool pprof -http=0.0.0.0:6060 http://localhost:6060/debug/pprof/profile?seconds=30
# 3. 本地端口转发,访问pprof可视化界面
kubectl port-forward web-app-7d4b8c9f-xyz 6060:6060
# 4. 浏览器访问 http://localhost:6060,查看CPU/内存占用热点

10.3 高级调试技术的价值

  • 无停机调试:临时容器、Pod 副本等技术避免了生产环境重启,保障业务连续性;
  • 深层问题定位:通过tcpdump抓包、节点级系统日志查看,可定位网络丢包、kubelet 底层故障等标准工具无法触及的问题;
  • 上下文保留:调试容器共享目标容器的网络、PID、文件系统命名空间,确保调试环境与实际运行环境一致,避免“本地能复现、生产无法复现”的问题。

总结

Kubernetes 故障排除的核心,从来不是死记硬背命令,而是 “对症下药”,用kubectl describe抓事件、用日志定位容器内部问题、用临时容器避免生产停机,再配合健康检查提前预防故障,每一步都需要结合场景灵活运用。

声明:来自木讷大叔爱运维,仅代表创作者观点。链接:https://eyangzhen.com/3340.html

木讷大叔爱运维的头像木讷大叔爱运维

相关推荐

关注我们
关注我们
购买服务
购买服务
返回顶部