引言
生产环境的Kubernetes集群运行久了,各种奇奇怪怪的问题都会冒出来。本文挑选10个日常运维中最高频的故障场景,从现象到根因到修复,手把手过一遍。每个案例都给出完整的排查路径、关键命令和验证方法,照着做能解决大部分常见问题。
集群环境说明:本文以Kubernetes 1.28版本为例,节点系统为CentOS 7.9或Ubuntu 22.04,容器运行时为containerd 1.7.x。多节点集群场景,包含3个控制面节点和若干工作节点。
问题一:Pod一直处于Pending状态
问题背景
Pod创建后一直卡在Pending状态,既不调度到节点,也不报错。这种情况在生产环境中很常见,新手往往不知道该从哪里入手。
适用场景
新建应用部署后发现Pod起不来
节点扩容后Pod仍然无法调度
资源紧张时应用无法重新调度
核心知识点
Pending状态的Pod意味着调度器无法将它分配到任何节点。常见原因有三类:资源不足、亲和性/污点限制、存储卷挂载等待。
实战步骤
第一步:查看Pod状态详情
kubectl get pod -n-o wide kubectl describe pod -n
describe输出中的Events部分最关键,看最后几行事件记录。
典型现象示例:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 3m default-scheduler 0/5 nodes are available: 1 Insufficient cpu, 3 node(s) had taints that the pod didn't tolerate, 1 resource allocation disabled.
第二步:检查集群资源状态
kubectl top nodes kubectl describe node
查看每个节点的CPU、内存、存储使用情况。特别注意Allocatable字段,它才是实际可调度的资源量。
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{" "}{.status.allocatable.cpu}{" CPU "}{.status.allocatable.memory}{" "}{.status.conditions[?(@.type=="Ready")].status}{"
"}{end}'
第三步:检查污点和容忍
kubectl get node -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
如果节点有污点,Pod没有对应的容忍配置就不会调度。
第四步:检查存储类和PVC状态
kubectl get pvc -nkubectl describe pvc
挂载迟迟不能完成的PVC会阻塞Pod调度。
根因定位与修复
原因一:资源不足
CPU或内存不够时,调度器找不到满足条件的节点。
修复方案:要么扩容节点,要么降低Pod资源请求值,要么清理现有低优先级Pod。
resources: requests: memory: "128Mi" cpu: "100m" limits: memory: "256Mi" cpu: "200m"
原因二:节点污点限制
kubectl taint nodekey=value:NoSchedule-
临时去掉污点让Pod调度进去,但生产环境建议通过添加容忍来解决问题。
tolerations: - key: "key" operator: "Exists" effect: "NoSchedule"
原因三:PVC挂载超时
检查StorageClass是否存在、PV是否正确绑定、存储后端是否正常。
验证方式
kubectl get pod -n# 状态变为 Running 表示调度成功 # 继续观察是否进入 Running 状态 kubectl logs -n --previous
风险提醒
修改污点会影响其他Pod的调度行为。移除污点前确认该节点是否专门用于特定 workloads。
回滚方案
如果是通过修改Pod YAML解决的问题,直接重新apply原配置即可。如果涉及节点污点修改,用taint命令恢复或打标签替代。
问题二:Pod一直处于CrashLoopBackOff状态
问题背景
Pod启动后立刻崩溃,反复重启,始终无法正常运行。这是线上最常见的Pod故障之一,往往意味着应用本身有问题。
适用场景
应用刚部署就报错
更新版本后突然无法启动
节点异常后应用无法恢复
核心知识点
CrashLoopBackOff是Kubernetes报告容器反复崩溃的状态。容器退出码非0,kubelet会按指数退避策略重启,每次等待时间翻倍:10秒、20秒、40秒...最长5分钟。
实战步骤
第一步:获取容器退出码和重启原因
kubectl get pod -n-o jsonpath='{.status.containerStatuses[*]}{" "}'
重点关注exitCode、lastState、restartCount字段。
kubectl describe pod -n| grep -A 20 "Last State"
第二步:查看应用日志
kubectl logs -n--previous
--previous参数拿的是上次崩溃前的容器日志,非常关键。
第三步:进入容器内部排查
kubectl exec -it -n-- /bin/sh
如果Pod内只有一个容器,可以省略-c参数。
第四步:检查容器启动命令和环境变量
kubectl get pod -n-o jsonpath='{.spec.containers[*].command}' kubectl get pod -n -o jsonpath='{.spec.containers[*].env}'
第五步:检查健康检查配置
kubectl describe pod -n| grep -A 5 "Liveness" kubectl describe pod -n | grep -A 5 "Readiness"
探针失败次数过多也会导致容器被认为不健康。
根因定位与修复
原因一:应用启动命令错误
检查command和args是否正确,镜像ENTRYPOINT和CMD是否有冲突。
command: ["/bin/sh", "-c"] args: ["node app.js && sleep infinity"]
原因二:依赖服务不可达
应用启动时需要连接数据库、Redis等,如果连接失败会直接退出。
# 在Pod内测试连接 kubectl exec -it -n-- nc -zv 3306 kubectl exec -it -n -- nslookup
原因三:配置文件错误或缺失
挂载的ConfigMap或Secret没有正确创建。
kubectl get configmap -nkubectl get secret -n
原因四:权限问题
容器内进程没有足够权限读写挂载的目录。
kubectl exec -it -n-- ls -la /data kubectl exec -it -n -- id
原因五:健康检查过早杀死进程
startupProbe配置不当会导致容器还在启动中就被杀掉。
startupProbe: httpGet: path: /healthz port: 8080 failureThreshold: 30 periodSeconds: 10
验证方式
# 观察重启次数是否归零 kubectl get pod -n-w # 确认容器运行稳定 kubectl exec -it -n -- ps aux
风险提醒
容器内的数据丢失无法恢复(无持久化存储时)。修复前先确认应用是否支持多次重启不丢数据。
回滚方案
如果是版本更新导致的问题,回滚镜像版本:
kubectl rollout undo deployment-n kubectl rollout status deployment -n
问题三:Pod无法通过Service访问
问题背景
Pod之间无法通过Service名称通信,curl或wget都超时。应用明明运行正常,但就是连不上。
适用场景
应用间调用失败
Ingress进来流量无法到达后端Pod
集群内部DNS解析异常
核心知识点
Service访问涉及三个环节:DNS解析、kube-proxy转发、Pod监听。任何一个环节出问题都会导致访问失败。
实战步骤
第一步:确认Pod和Service都存在
kubectl get pod -n-o wide | grep kubectl get svc -n | grep
第二步:从同命名空间其他Pod测试访问
kubectl exec -it -n-- curl -v http:// : /
第三步:检查Endpoints是否正常
kubectl get endpoints -n
Endpoints为空说明selector没有匹配到任何Pod。
kubectl describe svc -n
第四步:检查kube-proxy是否正常运行
kubectl get pod -n kube-system -o wide | grep kube-proxy kubectl logs -n kube-system--tail=50
第五步:测试ClusterIP连通性
kubectl exec -it -n-- curl -v http:// : /
第六步:检查iptables规则
kubectl exec -it-- iptables -L -t nat | grep
根因定位与修复
原因一:Endpoints为空
selector配置错误或匹配到的Pod还没ready。
spec: selector: app: my-app # 检查标签是否匹配
修复:确认Pod标签和Service selector一致。
kubectl get pod -n--show-labels | grep
原因二:kube-proxy异常
kube-proxy崩溃或watch资源出错。
systemctl status kube-proxy journalctl -u kube-proxy -n 50
重启kube-proxy:
kubectl delete pod -n kube-system
原因三:DNS解析失败
kubectl exec -it -n-- nslookup kubectl exec -it -n -- cat /etc/resolv.conf
CoreDNS相关问题:
kubectl get pod -n kube-system -o wide | grep dns kubectl logs -n kube-system--tail=50
原因四:Pod网络策略阻止
kubectl get networkpolicy -nkubectl describe networkpolicy
验证方式
# 多次测试确认稳定
for i in {1..10}; do kubectl exec -it -n -- curl -s http://:/healthz && echo " OK" || echo " FAIL"; done
# 检查sessionAffinity是否生效
kubectl exec -it -n -- ss -s
风险提醒
修改kube-proxy重启会影响所有Service流量,生产环境滚动操作。NetworkPolicy配置错误可能阻断所有流量。
回滚方案
kube-proxy是DaemonSet,不支持rollout undo。如果需要回滚配置,手动恢复之前的ConfigMap或重启kube-proxy Pod:
# 重启kube-proxy Pod触发配置重新加载 kubectl delete pod -n kube-system -l k8s-app=kube-proxy # 或者恢复之前的网络策略yaml kubectl apply -f
问题四:镜像拉取失败
问题背景
Pod调度到节点后,镜像下载失败,容器始终无法启动。这种问题在配置了私有镜像仓库但没做镜像拉取授权时特别常见。
适用场景
部署新应用时报错ImagePullBackOff
节点重启后原地重建Pod失败
更换镜像仓库地址后无法拉取
核心知识点
ImagePullBackOff表示kubelet反复尝试拉取镜像但持续失败。常见原因包括:镜像不存在、认证失败、网络不通、registry白名单限制。
实战步骤
第一步:查看Pod事件
kubectl describe pod -n| grep -A 10 "Events"
典型错误信息:
Failed to pull image "registry.example.com/app:latest": rpc error: code = Unknown desc = Error: Not Found
Failed to pull image "registry.example.com/app:latest": rpc error: code = Unknown desc = unauthorized: authentication required
Failed to pull image "registry.example.com/app:latest": rpc error: code = Unknown desc = http: server gave HTTP response to HTTPS client
第二步:确认镜像确实存在
# 在有网络权限的节点上直接测试 ctr -n k8s.io images ls | grepcrictl images | grep
第三步:检查镜像仓库认证信息
kubectl get secret -n| grep docker kubectl describe secret
Secret类型必须是kubernetes.io/dockerconfigjson。
第四步:检查节点hosts和证书
cat /etc/hosts | grepls -la /etc/docker/certs.d/ /
第五步:在节点上手动拉取测试
crictl pull/ : ctr -n k8s.io images pull / :
根因定位与修复
原因一:镜像不存在或tag错误
# 确认正确镜像地址 docker pull/ :
修复:更正镜像地址或tag。
原因二:认证凭据错误
创建或更新Secret:
kubectl create secret docker-registry--docker-server= --docker-username= --docker-password= --docker-email= -n
PodSpec引用Secret:
spec: imagePullSecrets: - name:
原因三:私有仓库证书问题
配置私有仓库CA证书。对于containerd 1.7.x版本,需要在/etc/containerd/config.toml中配置:
# 编辑containerd配置 vi /etc/containerd/config.toml # 在 [plugins."io.containerd.grpc.v1.cri".registry] 下添加: [plugins."io.containerd.grpc.v1.cri".registry.configs."".tls] ca_file = "/etc/ssl/certs/ .crt"
或者在节点上直接安装CA证书(适用于所有容器运行时):
# Debian/Ubuntu cp ca.crt /usr/local/share/ca-certificates/.crt update-ca-certificates # RHEL/CentOS cp ca.crt /etc/pki/ca-trust/source/anchors/ .crt update-ca-trust extract
配置修改后重启containerd:
systemctl restart containerd
原因四:网络访问限制
检查节点能否访问镜像仓库:
curl -I https:///v2/
验证方式
# 删除Pod触发重新调度 kubectl delete pod -n# 观察镜像拉取是否成功 kubectl get events -n --sort-by='.lastTimestamp' | tail -20
风险提醒
删除Pod会影响业务连续性,确认有足够副本数再操作。私密凭据更新需要同步到所有使用它的命名空间。
回滚方案
恢复到之前可用的镜像版本:
spec: containers: - name: app image:/ :
问题五:Node NotReady
问题背景
集群中某个节点状态变成NotReady,kubelet无法正常汇报节点状态。该节点上的Pod不会调度新实例,但现有Pod是否受影响取决于情况。
适用场景
节点异常后无法管理
节点上应用无响应
集群容量异常减少
核心知识点
节点进入NotReady状态是因为kubelet在40秒内没有向API Server发送心跳。常见原因包括:kubelet进程挂了、系统资源耗尽、网络不通、证书过期。
实战步骤
第一步:确认节点状态
kubectl get nodes kubectl describe node
kubectl get node-o jsonpath='{.status.conditions[*]}'
第二步:登录节点检查kubelet状态
systemctl status kubelet journalctl -u kubelet -n 50 --no-pager
第三步:检查节点资源
free -h df -h top -bn1 | head -20
第四步:检查容器运行时
systemctl status containerd # 或 docker systemctl status kubelet
第五步:检查证书是否过期
openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates openssl x509 -in /var/lib/kubelet/pki/kubelet-server-current.pem -noout -dates
根因定位与修复
原因一:kubelet进程崩溃或被杀死
systemctl restart kubelet systemctl enable kubelet
原因二:系统内存或磁盘耗尽
清理磁盘:
# 清理旧日志 journalctl --vacuum-size=500M # 清理containerd未使用镜像 crictl rmi $(crictl images -q) # 清理docker未使用镜像(如果使用docker运行时) docker system prune -af # 清理containerd旧镜像 # 先查看有哪些未使用的镜像 ctr -n k8s.io images ls -q | head -20 # 手动删除不需要的镜像(不要删除正在使用的) ctr -n k8s.io images rm# 清理/var/lib/kubelet目录下的临时文件 find /var/lib/kubelet -name "*.tmp" -delete
增加节点资源或调度更多Pod出去。
原因三:kubelet证书过期
自动轮转失败时需要手动更新。在故障节点上执行:
# 删除旧的kubelet证书和kubeconfig rm -rf /var/lib/kubelet/pki/ rm -f /var/lib/kubelet/kubelet.conf # 重启kubelet,kubelet会自动向API Server申请新证书 systemctl restart kubelet # 确认证书已重新申请 ls -la /var/lib/kubelet/pki/ openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates
原因四:网络不通
pingtelnet 6443 curl -k https:// :6443/healthz
检查节点防火墙:
systemctl status firewalld iptables -L -n | grep 6443
原因五:containerd或docker异常
systemctl restart containerd # 或 systemctl restart docker
验证方式
kubectl get node# 状态变为 Ready # 确认节点可调度 kubectl describe node | grep -A 5 "Allocatable" # 确认Pod可以调度到该节点 kubectl describe node | grep -A 5 "Taints"
风险提醒
重启kubelet会导致节点上Pod短暂网络中断。驱逐Pod会影响运行中的业务。操作前确认集群有足够冗余。
回滚方案
如果问题无法快速恢复,先隔离节点防止Pod继续调度:
kubectl cordonkubectl drain --ignore-daemonsets --delete-emptydir-data
等节点恢复后un cordon:
kubectl uncordon
问题六:存储卷挂载异常
问题背景
Pod挂载的PVC一直处于Pending状态,或者Pod启动后无法正常读写数据目录。存储问题是生产环境中后果最严重的故障之一。
适用场景
数据库Pod无法启动
有状态应用部署失败
日志写入报错
核心知识点
Kubernetes存储涉及StorageClass、PersistentVolumeClaim、PersistentVolume、CSI驱动四个组件。任何一个环节断裂都会导致挂载失败。
实战步骤
第一步:检查PVC状态
kubectl get pvc -nkubectl describe pvc -n
Pending状态的PVC说明还没有找到合适的PV。
第二步:检查PV状态
kubectl get pv kubectl describe pv
第三步:检查StorageClass
kubectl get storageclass kubectl describe storageclass
第四步:检查CSI驱动状态
kubectl get pod -n kube-system | grep csi kubectl logs -n kube-system--tail=50
第五步:检查节点挂载情况
# 在Pod所在节点执行 mount | grepdf -h | grep
根因定位与修复
原因一:StorageClass不存在
# 确认集群有哪些StorageClass kubectl get storageclass # 创建必要的StorageClass kubectl apply -f - <
原因二:PVC绑定到错误的PV
# 检查绑定状态 kubectl get pvc -n-o wide # 删除重建PVC(数据会丢失) kubectl delete pvc -n
原因三:CSI驱动问题
# 重启CSI驱动 kubectl delete pod -n kube-system# 检查驱动版本兼容性 kubectl get csidrivers
原因四:节点无法访问存储后端
NFS、Ceph、GlusterFS等网络存储需要节点能连通。
showmount -eceph -s
原因五:权限问题
# 检查FSGroup配置 kubectl get pod -n-o jsonpath='{.spec.securityContext.fsGroup}' kubectl get pod -n -o jsonpath='{.spec.initContainers[*].securityContext}'
修改Pod安全上下文:
spec: securityContext: fsGroup: 2000 runAsUser: 1000
验证方式
# 进入Pod测试读写 kubectl exec -it -n-- sh -c "echo test > /data/test.txt && cat /data/test.txt" # 确认挂载点正常 kubectl exec -it -n -- df -h | grep /data # 检查文件权限 kubectl exec -it -n -- ls -la /data
风险提醒
删除PVC会永久丢失数据。修改存储类不会影响已绑定的PV/VC。跨节点存储迁移需要先备份数据。
回滚方案
# 如果使用了错误的StorageClass,重新创建PVC指定正确的storageClassName # 如果是权限问题,恢复安全上下文配置 # 如果是CSI问题,回滚CSI驱动版本
问题七:资源配额耗尽导致Pod被驱逐
问题背景
集群或命名空间的ResourceQuota/LimitRange限制被触发,Pod被强制终止。应用无预警崩溃,影响业务可用性。
适用场景
多个团队共用集群时资源竞争
资源限制配置过于严格
应用内存泄漏逐渐逼近限制
核心知识点
Kubernetes通过ResourceQuota限制命名空间总资源、LimitRange限制单个Pod/容器的资源请求。超出限制会触发Evicted状态。
实战步骤
第一步:确认Pod被驱逐
kubectl get pod -n| grep Evicted kubectl describe pod -n
第二步:检查命名空间资源配额
kubectl get resourcequota -nkubectl describe resourcequota -n kubectl get limitrange -nkubectl describe limitrange -n
第三步:检查实际资源使用
kubectl top pod -nkubectl top nodes
第四步:分析配额消耗
# 计算当前命名空间总资源 kubectl api-resources --verbs=list --namespaced -o wide | grep -i quota
根因定位与修复
原因一:内存Limit不足
Pod实际使用超过limits设置,被OOMKilled。
resources: requests: memory: "512Mi" limits: memory: "1Gi"
增加limits或优化应用内存使用。
原因二:命名空间总CPU配额耗尽
检查当前ResourceQuota:
kubectl get resourcequota -n-o yaml
增加ResourceQuota:
apiVersion: v1 kind: ResourceQuota metadata: name: increase-quota spec: hard: requests.cpu: "20" requests.memory: 40Gi limits.cpu: "40" limits.memory: 80Gi
原因三:PVC数量超过限制
kubectl get pvc -n| wc -l
删除不需要的PVC:
kubectl delete pvc-n
原因四:Pod数量超过限制
apiVersion: v1 kind: ResourceQuota metadata: name: pod-quota spec: hard: pods: "100"
验证方式
# 持续监控资源使用 watch -n 5 'kubectl top pod -n' # 确认Pod不再被驱逐 kubectl get events -n --sort-by='.lastTimestamp' | grep -i evict
风险提醒
增加ResourceQuota需要集群层面有足够资源。删除PVC会丢失数据。修改LimitRange只影响新建的Pod。
回滚方案
# 恢复ResourceQuota到之前的值 kubectl apply -f# 如果是单个Pod问题,恢复limits配置 kubectl patch deployment -n --type merge -p '{"spec":{"template":{"spec":{"containers":[{"name":"app","resources":{"limits":{"memory":"512Mi"}}}]}}}}'
问题八:etcd集群故障
问题背景
etcd是Kubernetes的核心数据存储,集群状态全部保存在其中。etcd故障会导致API Server不可用,整个集群基本瘫痪。
适用场景
控制面节点异常
集群无法响应任何kubectl命令
证书验证失败
核心知识点
生产环境etcd应该至少3节点集群,容忍1节点故障。数据损坏、磁盘满、证书过期、网络分区是最常见的故障原因。
实战步骤
第一步:检查etcd服务状态
systemctl status etcd journalctl -u etcd -n 50 --no-pager
第二步:检查etcd健康状态
ETCDCTL_API=3 etcdctl --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 endpoint health
第三步:检查etcd成员状态
ETCDCTL_API=3 etcdctl --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 member list -w table
第四步:检查磁盘空间
df -h /var/lib/etcd du -sh /var/lib/etcd/*
第五步:检查证书
openssl x509 -in /etc/kubernetes/pki/etcd/server.crt -noout -dates openssl x509 -in /etc/kubernetes/pki/etcd/peer.crt -noout -dates
根因定位与修复
原因一:磁盘空间不足
etcd数据目录所在磁盘占满会导致写入失败,集群不可写。
清理方案:
# 先检查wal目录大小 du -sh /var/lib/etcd/member/wal # 执行defrag(不会丢数据) ETCDCTL_API=3 etcdctl defrag --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 # 清理旧快照 find /var/lib/etcd -name "*.snap" -mtime +7 -delete
如果磁盘确实满了,需要扩容或清理其他文件。
原因二:etcd启动失败
# 查看详细错误 journalctl -u etcd -n 100 | grep -i error # 检查配置文件 cat /etc/kubernetes/etcd.conf
原因三:节点证书过期
检查证书过期时间:
# 检查kubelet客户端证书 openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates # 检查kubelet服务器证书 openssl x509 -in /var/lib/kubelet/pki/kubelet-server-current.pem -noout -dates # 检查API Server访问证书(控制面节点) openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates
如果证书已过期,在控制面节点上使用kubeadm重新生成。首先备份旧证书:
# 备份旧证书 mkdir -p /backup/pki-$(date +%Y%m%d) cp -r /etc/kubernetes/pki/* /backup/pki-$(date +%Y%m%d)/
创建kubeadm配置文件指定证书有效期:
cat > /tmp/kubeadm-config.yaml <peerCertSANs: - <控制面节点IP> certificates: validityPeriod: 87600h # 10年 EOF
重新生成控制面证书:
# 重新生成apiserver证书 kubeadm init phase certs apiserver --config=/tmp/kubeadm-config.yaml # 重新生成etcd证书 kubeadm init phase certs etcd-server --config=/tmp/kubeadm-config.yaml kubeadm init phase certs etcd-peer --config=/tmp/kubeadm-config.yaml kubeadm init phase certs etcd-client --config=/tmp/kubeadm-config.yaml # 重启API Server systemctl restart kubelet
确认证书时间已更新:
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates openssl x509 -in /etc/kubernetes/pki/etcd/server.crt -noout -dates
原因四:单个节点故障恢复
先确认故障节点的member ID:
# 查看所有成员 ETCDCTL_API=3 etcdctl --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 member list
从集群移除故障节点(用实际member ID替换
):
ETCDCTL_API=3 etcdctl --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 member remove# 重新添回节点(如果节点恢复) ETCDCTL_API=3 etcdctl --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 member add <节点名称> --peer-urls=https://<节点IP>:2380 # 重启etcd服务 systemctl restart etcd
验证方式
# 确认所有节点健康 ETCDCTL_API=3 etcdctl --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 endpoint health --cluster # 测试写入 ETCDCTL_API=3 etcdctl --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 put test-key "test-value"
风险提醒
etcd数据损坏可能是不可逆的。操作前务必先备份:etcdctl snapshot save。修改etcd配置后必须重启服务,会有短暂不可用。
回滚方案
# 从快照恢复 ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot.db --data-dir=/var/lib/etcd --initial-cluster=--initial-advertise-peer-urls=https:// :2380 systemctl restart etcd
问题九:DNS解析异常
问题背景
集群内Pod之间无法通过Service名称通信,DNS查询超时或返回错误结果。CoreDNS是集群DNS的核心组件,它的健康直接决定服务发现是否正常。
适用场景
应用启动后连不上数据库
Pod间调用莫名超时
集群内网络时断时续
核心知识点
Kubernetes DNS基于CoreDNS实现,通过kube-dns服务暴露。Pod的/etc/resolv.conf指向kube-dns的ClusterIP进行查询。Service域名格式为
. .svc.cluster.local。 实战步骤
第一步:确认CoreDNS Pod状态
kubectl get pod -n kube-system -o wide | grep coredns kubectl logs -n kube-system--tail=50
第二步:进入测试Pod验证DNS
kubectl run -it --rm debug --image=busybox -n default --restart=Never -- nslookup kubernetes.default kubectl run -it --rm debug --image=busybox -n default --restart=Never -- nslookup.
如果不指定命名空间,默认使用default命名空间。测试完后Pod会自动删除。
第三步:检查Pod的resolv.conf
kubectl exec -it-n -- cat /etc/resolv.conf
确认nameserver指向正确的ClusterIP。
第四步:测试直接IP连通性
kubectl exec -it-n -- ping kubectl exec -it -n -- curl -v https:// :
第五步:检查CoreDNS配置
kubectl get configmap -n kube-system coredns -o yaml
根因定位与修复
原因一:CoreDNS Pod异常
# 重启CoreDNS kubectl delete pod -n kube-system# 确认副本数 kubectl get deployment -n kube-system coredns kubectl scale deployment coredns -n kube-system --replicas=3
原因二:upstream DNS配置错误
CoreDNS的forward配置决定了集群外域名查询走哪里。
# ConfigMap中检查 forward . /etc/resolv.conf # 或指定上游服务器 forward . 8.8.8.8
原因三:headless Service问题
kubectl get svc-n -o yaml | grep clusterIP
headless Service的clusterIP为None,这时DNS会返回Pod IP列表而不是单个IP。
原因四:busybox镜像版本问题
旧版本busybox的nslookup实现不完整。换用其他镜像测试:
kubectl run -it --rm debug --image=alpine --restart=Never -- sh # apk add bind-tools # nslookup
原因五:网络策略阻止DNS流量
kubectl get networkpolicy -n kube-system
确认没有规则阻止CoreDNS的53端口。
验证方式
# 持续测试DNS解析 kubectl exec -it-n -- sh -c 'for i in {1..10}; do nslookup kubernetes.default && break || sleep 1; done' # 检查解析延迟 kubectl exec -it -n -- time nslookup
风险提醒
CoreDNS是集群核心组件,修改配置和重启都会短暂影响DNS服务。滚动重启CoreDNS一般不会影响业务,但有短暂解析失败。
回滚方案
# 恢复CoreDNS ConfigMap kubectl apply -f coredns-configmap-backup.yaml # 如果是缩容问题,恢复副本数 kubectl scale deployment coredns -n kube-system --replicas=<原数量>
问题十:Pod安全策略导致权限不足
问题背景
应用运行在非root用户、强制安全上下文或限制性PodSecurityPolicy下,某些目录无法写入、某些端口无法监听、某些系统调用被拒绝。
适用场景
应用报Permission denied错误
容器内无法创建文件
特权操作被拒绝
核心知识点
Pod安全通过PSP(PodSecurityPolicy,已废弃)、Pod Security Standards、SecurityContext三层面控制。容器级别的runAsUser、capabilities、allowPrivilegeEscalation等设置会限制进程权限。
实战步骤
第一步:查看Pod安全上下文
kubectl get pod -n-o yaml | grep -A 20 securityContext kubectl describe pod -n | grep -A 10 "Security"
第二步:查看容器安全上下文
kubectl get pod -n-o jsonpath='{.spec.containers[*].securityContext}'
第三步:检查Pod所在节点的安全模块状态
# 检查是否启用SELinux getenforce # 检查AppArmor状态 apparmor_status # 检查seccomp配置文件 cat /proc/sys/kernel/seccomp/computer_mode
第四步:查看相关事件和日志
kubectl describe pod -n| grep -A 5 "Warning" # 检查audit日志 auditctl -l | grep
根因定位与修复
原因一:非root用户无法写入目录
修改安全上下文使用root运行(不推荐用于有漏洞的镜像):
spec: securityContext: runAsUser: 0
更好的方案是修改目录权限:
spec: securityContext: runAsUser: 1000 volumes: - name: data persistentVolumeClaim: claimName: my-pvc initContainers: - name: fix-permission image: busybox command: ["sh", "-c", "chown -R 1000:1000 /data"] volumeMounts: - name: data mountPath: /data
原因二:缺少必要capability
应用需要绑定低位端口(如80、443)但没有SYS_ADMIN capability。
spec: containers: - name: app securityContext: capabilities: add: - NET_BIND_SERVICE drop: - ALL
原因三:特权模式被禁用
运行特权容器被PSP或PSA拒绝:
spec: containers: - name: app securityContext: privileged: false allowPrivilegeEscalation: false
原因四:hostPath挂载被拒绝
spec: volumes: - name: host-sys hostPath: path: /sys type: Directory containers: - name: app volumeMounts: - name: host-sys mountPath: /host/sys readOnly: true
确保PSP允许hostPath类型。
验证方式
# 确认应用正常运行 kubectl exec -it -n-- id # 应该显示配置的runAsUser # 测试写入权限 kubectl exec -it -n -- touch /data/test-file kubectl exec -it -n -- rm /data/test-file # 确认非特权运行 kubectl exec -it -n -- cat /proc/self/status | grep Cap
风险提醒
给予容器过高权限(privileged、SYS_ADMIN)会增大安全风险。生产环境应遵循最小权限原则。hostPath访问节点文件系统可能导致容器逃逸。
回滚方案
# 恢复到之前的安全上下文配置 kubectl patch deployment-n --type merge -p '{"spec":{"template":{"spec":{"securityContext":{"runAsUser":1000}}}}}'
总结
高频问题排查矩阵
问题现象 首选排查命令 常见根因 Pod Pending kubectl describe pod 看Events 资源不足、污点、存储等待 CrashLoopBackOff kubectl logs --previous 启动命令错误、依赖不可达、权限问题 Service无法访问 kubectl get endpoints Selector不匹配、kube-proxy异常、网络策略 镜像拉取失败 kubectl describe pod 看错误 认证失败、镜像不存在、网络不通 Node NotReady systemctl status kubelet kubelet崩溃、资源耗尽、证书过期 存储卷异常 kubectl describe pvc StorageClass缺失、CSI驱动问题、权限 Pod被驱逐 kubectl describe pod 看配额 资源Limit不足、命名空间配额耗尽 etcd故障 etcdctl endpoint health 磁盘满、证书过期、成员不一致 DNS异常 nslookup 测试 CoreDNS异常、upstream配置错误 权限不足 kubectl describe pod 看安全上下文 runAsUser限制、capability缺失 日常巡检清单
# 节点健康 kubectl get nodes -o wide kubectl top nodes # Pod健康 kubectl get pods -A | grep -v Running kubectl get pods -A | grep -i evicted # 资源配额 kubectl get resourcequota -A kubectl describe limitrange -n# 存储状态 kubectl get pvc -A kubectl get pv # 核心组件 kubectl get pods -n kube-system # 事件 kubectl get events -A --sort-by='.lastTimestamp' | tail -50
预防性措施
资源规划:为每个命名空间设置合理的ResourceQuota,为每个Pod设置准确的resources requests和limits
高可用部署:关键应用使用反亲和性分布到不同节点,控制面节点至少3个
监控告警:对节点CPU、内存、磁盘、Pod重启、调度延迟等关键指标建立告警
定期演练:每个季度模拟一次故障,验证备份可用性和恢复流程
版本管理:保持kubelet、containerd、etcd等核心组件版本一致,升级前先在测试环境验证
日志收集:确保kubelet、containerd、etcd、CoreDNS日志汇聚到统一平台,便于事后复盘
遇到问题先看事件、再查日志、最后看配置,按这个顺序能覆盖80%以上的常见故障。复杂问题往往需要综合分析多个组件的状态,善用kubectl get和kubectl describe两个命令能快速定位问题边界。
全部0条评论
快来发表一下你的评论吧 !