实战案例和工具
实战案例和工具
本节通过真实案例演示故障排查过程,并介绍常用的调试工具。
实战案例
案例 1:应用突然无法访问
症状:
# 用户反馈应用无法访问
curl https://app.example.com
# curl: (7) Failed to connect to app.example.com port 443: Connection refused
排查过程:
# 1. 检查 Ingress
kubectl get ingress -n production
NAME HOSTS ADDRESS PORTS
myapp app.example.com 10.0.1.100 80, 443
# 2. 检查 Ingress Controller
kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS
ingress-nginx-controller-abc 0/1 Running 5
# 发现 Controller 频繁重启!
# 3. 查看日志
kubectl logs -n ingress-nginx ingress-nginx-controller-abc --previous
# Error: Failed to list *v1.Endpoints: endpoints is forbidden
# 根因:RBAC 权限问题
# 4. 检查 ServiceAccount 权限
kubectl get clusterrolebinding | grep ingress-nginx
# 发现 ClusterRoleBinding 被误删除
# 5. 修复
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
# 6. 验证
kubectl get pods -n ingress-nginx
# 正常运行
curl https://app.example.com
# 恢复正常
总结:
- 根因:RBAC ClusterRoleBinding 被误删
- 影响:Ingress Controller 无法监听 Endpoints 变化
- 预防:使用 GitOps 管理基础设施,避免手动操作
案例 2:Pod 内存持续增长导致 OOM
症状:
# Pod 频繁重启
kubectl get pods
NAME READY STATUS RESTARTS
api-server 0/1 OOMKilled 8
排查过程:
# 1. 查看资源限制
kubectl get pod api-server -o yaml | grep -A 5 resources
resources:
limits:
memory: 512Mi
requests:
memory: 256Mi
# 2. 查看历史内存使用
# 在 Grafana 中查询
container_memory_usage_bytes{pod="api-server"}
# 发现内存持续增长,最终达到 512Mi 被 OOM
# 3. 生成堆快照(Node.js 应用)
kubectl exec -it api-server -- kill -USR2 $(pidof node)
# 4. 复制堆快照
kubectl cp api-server:/tmp/heapdump-*.heapsnapshot ./heap.heapsnapshot
# 5. 使用 Chrome DevTools 分析
# 发现大量的 Socket 对象未释放
# 6. 检查代码
# 发现 HTTP 客户端连接未正确关闭
// 问题代码
app.get('/api/data', async (req, res) => {
const response = await axios.get('http://external-api');
res.json(response.data);
// 缺少错误处理,连接池耗尽
});
// 修复后
const axiosInstance = axios.create({
timeout: 5000,
maxRedirects: 5,
httpAgent: new http.Agent({
keepAlive: true,
maxSockets: 50 // 限制连接池大小
})
});
app.get('/api/data', async (req, res) => {
try {
const response = await axiosInstance.get('http://external-api');
res.json(response.data);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
总结:
- 根因:HTTP 连接池泄漏
- 影响:内存持续增长直至 OOM
- 预防:
- 正确管理连接池
- 设置内存告警
- 定期进行内存分析
案例 3:网络间歇性超时
症状:
# 用户反馈 API 偶尔超时
# 监控显示 P99 延迟异常高
排查过程:
# 1. 查看 Service Endpoints
kubectl get endpoints api-service
NAME ENDPOINTS
api-service 10.244.1.5:8080,10.244.2.8:8080,10.244.3.9:8080
# 3 个 Endpoints,看起来正常
# 2. 测试每个 Pod
for pod in $(kubectl get pods -l app=api -o name); do
echo "Testing $pod"
kubectl exec -it $pod -- time curl -s http://localhost:8080/health
done
# 发现其中一个 Pod 响应慢
# 3. 检查慢的 Pod
kubectl exec -it api-abc123 -- top
# CPU 使用率异常高
# 4. 查看该 Pod 的节点
kubectl get pod api-abc123 -o wide
NODE
node-worker-2
# 5. 检查节点
kubectl describe node node-worker-2
# 发现节点上运行了大量 Pod,资源耗尽
# 6. 临时解决:驱逐慢的 Pod
kubectl delete pod api-abc123
# 新的 Pod 调度到其他节点,问题解决
# 7. 长期解决:配置 Pod 反亲和性
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-service
spec:
template:
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- api
topologyKey: kubernetes.io/hostname
总结:
- 根因:Pod 分布不均,某个节点资源耗尽
- 影响:该节点上的 Pod 响应变慢
- 预防:
- 配置 Pod 反亲和性
- 配置资源配额
- 监控节点资源使用
案例 4:DNS 解析失败导致服务不可用
症状:
# 应用日志显示大量 DNS 错误
kubectl logs api-server
# Error: getaddrinfo ENOTFOUND database-service
排查过程:
# 1. 在 Pod 内测试 DNS
kubectl exec -it api-server -- nslookup database-service
# Server: 10.96.0.10
# ** server can't find database-service: NXDOMAIN
# 2. 检查 Service 是否存在
kubectl get svc database-service
# Error from server (NotFound): services "database-service" not found
# 发现 Service 不存在!
# 3. 检查 Deployment 历史
kubectl rollout history deployment api-server
# 发现最近有一次更新
# 4. 查看配置变更
kubectl get deployment api-server -o yaml | grep DATABASE_SERVICE
# DATABASE_SERVICE_HOST=database-service
# 配置正确,但 Service 确实不存在
# 5. 检查是否被误删
kubectl get events --sort-by='.lastTimestamp' | grep database-service
# 发现有删除事件
# 6. 从 Git 恢复 Service 配置
git checkout database-service.yaml
kubectl apply -f database-service.yaml
# 7. 验证
kubectl exec -it api-server -- nslookup database-service
# 正常解析
总结:
- 根因:Service 被误删除
- 影响:应用无法通过 DNS 访问数据库
- 预防:
- 使用 GitOps 管理配置
- 配置 RBAC 防止误删
- 定期备份集群配置
调试工具集
kubectl 插件
kubectl-debug
# 安装
kubectl krew install debug
# 使用临时调试容器
kubectl debug <pod-name> -it --image=nicolaka/netshoot
# 在节点上运行调试容器
kubectl debug node/<node-name> -it --image=ubuntu
kubectl-tree
# 查看资源树
kubectl krew install tree
kubectl tree deployment myapp
# 输出:
# NAMESPACE NAME KIND
# default Deployment/myapp Deployment
# default └─ReplicaSet/myapp-abc123 ReplicaSet
# default ├─Pod/myapp-abc123-xyz Pod
# default └─Pod/myapp-abc123-qwe Pod
kubectl-neat
# 清理输出(移除管理字段)
kubectl krew install neat
kubectl get pod myapp -o yaml | kubectl neat
stern
# 多 Pod 日志聚合
brew install stern
# 查看所有匹配的 Pod 日志
stern myapp
# 过滤
stern myapp --since 1h
stern myapp -n production
stern myapp --exclude-container istio-proxy
网络调试工具
netshoot 容器
# 运行调试容器
kubectl run netshoot --rm -it --image=nicolaka/netshoot -- /bin/bash
# 包含工具:
# - curl, wget, httpie
# - nslookup, dig, host
# - ping, traceroute, mtr
# - tcpdump, nmap, netcat
# - iperf3, ab (Apache Bench)
使用示例:
# DNS 诊断
nslookup myapp-service
dig myapp-service.default.svc.cluster.local
# HTTP 测试
curl -v http://myapp-service:8080/health
httpie http://myapp-service:8080/api/data
# 端口扫描
nmap -p 1-65535 myapp-service
# 网络性能测试
iperf3 -c myapp-service -p 5001 -t 30
# 抓包分析
tcpdump -i eth0 -nn port 8080 -w capture.pcap
性能分析工具
kubectl-top
# 查看资源使用
kubectl top nodes
kubectl top pods --sort-by=memory
kubectl top pods --sort-by=cpu
# 持续监控
watch -n 1 kubectl top pods
kube-capacity
# 安装
kubectl krew install resource-capacity
# 查看集群容量
kubectl resource-capacity
# 按节点查看
kubectl resource-capacity --node-labels=node-role.kubernetes.io/worker
日志分析工具
kubetail
# 安装
brew tap johanhaleby/kubetail && brew install kubetail
# 实时查看多个 Pod 日志
kubetail myapp
# 带颜色区分
kubetail myapp --colored-output
k9s
# 安装
brew install k9s
# 启动(TUI 界面)
k9s
# 快捷键:
# :pod - 查看 Pods
# :svc - 查看 Services
# :deploy - 查看 Deployments
# / - 过滤
# l - 查看日志
# d - 描述资源
# e - 编辑
集群分析工具
kubectl-doctor
# 健康检查
kubectl doctor
# 输出:
# ✓ Cluster is reachable
# ✓ API server is responding
# ✓ All nodes are ready
# ⚠ CoreDNS has 1 replica (recommended: 2)
# ⚠ High pod restart rate detected
Polaris
# 运行 Polaris 审计
kubectl apply -f https://github.com/FairwindsOps/polaris/releases/latest/download/dashboard.yaml
# 端口转发
kubectl port-forward -n polaris svc/polaris-dashboard 8080:80
# 访问 http://localhost:8080
# 查看最佳实践建议
kube-score
# 安装
brew install kube-score
# 分析 YAML 文件
kube-score score deployment.yaml
# 输出:
# apps/v1/Deployment myapp
# [CRITICAL] Container Resources
# The container does not have a resource limit set
# [WARNING] Container Image Tag
# The container is using the latest tag
故障排查清单
快速检查清单
# 1. 集群整体状态
kubectl get nodes
kubectl get componentstatuses
# 2. 核心组件
kubectl get pods -n kube-system
# 3. 应用状态
kubectl get pods --all-namespaces
kubectl get deployments --all-namespaces
# 4. 网络
kubectl get svc --all-namespaces
kubectl get ingress --all-namespaces
# 5. 存储
kubectl get pv
kubectl get pvc --all-namespaces
# 6. 事件
kubectl get events --all-namespaces --sort-by='.lastTimestamp' | tail -50
# 7. 资源使用
kubectl top nodes
kubectl top pods --all-namespaces
详细排查脚本
#!/bin/bash
# k8s-troubleshoot.sh
echo "=== Kubernetes Cluster Health Check ==="
echo -e "\n1. Cluster Info"
kubectl cluster-info
echo -e "\n2. Node Status"
kubectl get nodes -o wide
echo -e "\n3. Unhealthy Pods"
kubectl get pods --all-namespaces --field-selector=status.phase!=Running,status.phase!=Succeeded
echo -e "\n4. Recent Events"
kubectl get events --all-namespaces --sort-by='.lastTimestamp' | tail -20
echo -e "\n5. Resource Usage"
kubectl top nodes
kubectl top pods --all-namespaces | sort -k3 -h | tail -10
echo -e "\n6. PVC Status"
kubectl get pvc --all-namespaces | grep -v Bound
echo -e "\n7. Service Endpoints"
kubectl get endpoints --all-namespaces | grep "<none>"
echo "=== Health Check Complete ==="
常用命令速查
# Pod 相关
kubectl get pods -o wide
kubectl describe pod <name>
kubectl logs <name> --tail=100 -f
kubectl exec -it <name> -- /bin/sh
kubectl delete pod <name> --force --grace-period=0
# Deployment 相关
kubectl get deployments
kubectl rollout status deployment/<name>
kubectl rollout history deployment/<name>
kubectl rollout undo deployment/<name>
kubectl scale deployment/<name> --replicas=5
# Service 相关
kubectl get svc
kubectl get endpoints <svc-name>
kubectl describe svc <name>
# 调试
kubectl run debug --rm -it --image=busybox -- sh
kubectl port-forward <pod-name> 8080:8080
kubectl proxy --port=8001
# 资源
kubectl top nodes
kubectl top pods
kubectl describe node <name>
# 事件
kubectl get events --sort-by='.lastTimestamp'
kubectl get events --field-selector type=Warning
小结
本节通过实战案例和工具介绍了故障排查:
✅ 实战案例:应用不可用、OOM、网络超时、DNS 失败
✅ kubectl 插件:debug、tree、neat、stern
✅ 网络工具:netshoot、tcpdump、iperf3
✅ 性能工具:top、k9s、kube-capacity
✅ 分析工具:Polaris、kube-score
✅ 排查清单:快速检查和详细脚本
至此,故障排查章节全部完成!🎉
下一章:安全最佳实践。