Lazy loaded image
k8s 集群故障排查和备份恢复
Words 1913Read Time 5 min
2025-12-8
2025-12-8
date
related_level
slug
type
relate_date
summary
status
tags
category
last_updated
Dec 8, 2025 02:34 PM
是否已更新
orginal_page
是否推荐

kubernetes Pod 故障排查思路

排查常用指令
  • kubectl describe
  • kubectl logs
    • --previous 查看前一次 pod 的日志
  • sudo systemctl status kubelet
  • ps aux | grep etcd
    • 外部 etcd
  • 排障思路:从用户端开始排查
如果是 web 服务可以看看连接是否正常
  • DNS 解析是否正常
    • CoreDNS 是否正常
  • 用户层连接是否正常
    • 证书/TLS 是否配置正确
    • 入口控制器(Ingress/Gateway/Service Mesh)是否配置正常
    • 网络策略是否配置正常
    • Service 是否正常匹配 Pod
  • 网络层连接是否正常
    • CNI 插件是否正常
    • 是否能正常访问 Pod 对应节点
    • kube-proxy 是否正常运行
pod 是否在正常运行
  • 底层镜像是否正确配置,运行 command 和 args 是否正常
    • 私有镜像是否正确配置 secrets
  • pod 声明的容器探针是否正常配置
    • initialDelaySeconds 是否足够容器正常启动
  • pod 依赖的存储, configmap, secrets 等资源是否正确配置
    • 是否正确挂载
  • pod RBAC 权限(serviceAccount, role, rolebinding)是否正常
pod 调度是否正常(一直处于 Pending)
  • pod 资源请求和限制是否正常
    • 调度节点的资源是否充足
    • LimitRange 和 ResourceQuota 是否配置正确
  • pod 的节点调度策略是否正常
    • 是否存在 nodeSelector
    • toleration 是否匹配节点 taint
    • 亲和性(affinity)和拓扑约束(TopologySpreadConstraints)是否满足
  • kube-controller-manager 和 kube-scheduler 是否正常运行
调度节点是否正常
  • 节点状态是否正常
    • 非 NoSchedule 或 NoExecute
  • 对应节点的 kubelet 是否正常运行
  • 控制平面的 kube-apiserver 是否正常运行
  • 集群内或者外部配置的 etcd 是否正常运行
  • 节点计算资源和存储资源是否足够
  • 节点底层系统是否正常配置
    • sysctl 内核参数
    • 内核模块
    • SELinux 或 AppArmor
 

kubernetes 集群控制节点故障排查

集群配置文件位置
  • kubeconfig
    • $HOME/.kube/config
  • 静态 Pod 配置文件,一般含 kubectl 组件
    • /etc/kubernetes/manifests
      • 默认路径
    • cat /var/lib/kubelet/config.yaml | grep staticPodPath
      • 可能会被更改
  • kubelet 组件配置
    • /var/lib/kubelet/config.yaml
  • 集群外 etcd
    • /etc/etcd
  • CRI 文件目录
    • /etc/containerd/config.toml
  • CNI 文件目录
    • /etc/cni/net.d/
    • /opt/cni/bin/
集群证书位置
  • /etc/kubernetes/pki/etcd
    • 如果为内部 etcd
    • 外部 etcd 集群根据具体配置
      • /etc/etcd/pki
  • /etc/kubernetes/pki
  • /var/lib/kubelet/pki
  • 排查常用指令
    • crictl 常用调试命令
      • crictl pods 列出所有 Pod
      • crictl ps -a 列出所有容器
      • crictl images 列出容器镜像
      • crictl exec -i 在容器内运行特定指令
      • crictl logs 查看容器日志
      kubectl debug node 调试节点,当无法 SSH 连接到节点时
      • kubectl debug node/<nodename> -it --image=ubuntu
        • 节点根文件系统挂载在 Pod 的 /host 路径
          • cat /host/var/log/kubelet.log
      • 该 Pod 默认没有特权,需要 --profile=sysadmin
        • 或者添加 securityContext
      • 清理调试 Pod
        • kubectl delete pod node-debugger-<nodename>-<suffix>
kubectl config 检查当前 kubeconfig 配置
  • kubectl config get-context
    • 当前上下文
  • kubectl config view --minify
    • 仅显示当前上下文配置
  • kubectl get nodes 检查 kube-apiserver 是否正常
    • 无响应或连接,检查 kube-apiserver 是否在运行以及配置是否正常
      • crictl ps | grep kube-apiserve
        • 检查容器
      • ss -tulnp | grep 6443
        • 检查端口
      • curl -k https://127.0.0.1:6443/healthz
        • 检查是否正常运行
      • ls /etc/kubernetes/manifest | grep apiserver
        • 检查配置
      返回 Connection refused 可能是启动参数异常或者证书配置异常
      • crictl logs $CONTAINER_ID
        • 检查容器日志
      • journalctl -u kubelet
        • 检查 kubelet 日志
      • tail /var/log/kube-apiserver.log
        • 检查 kube-apiserver
      • cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep -A20 "command:"
        • 检查启动参数
      • openssl x509 -in <cert-file> -noout -text | grep -E "Issuer|Subject|Not After"
        • 检查证书是否过期,issuer 和 CN 是否正确
 

检查 kubernetes 集群网络

参考资料
检查 kubernete DNS 配置并调试 DNS
创建一个简单的 Pod 作为测试环境
  • kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml
    • 验证安装情况
      • kubectl get pods -n default dnsutils
    • 处于 running 状态后可以执行 nslookup
      • kubectl -n default exec -i -t dnsutils -- nslookup kubernetes.default
      • kubectl -n default exec -i -t dnsutils -- ping -c 4 kubernetes.default
    Coredns 服务开启 DNS 查询记录日志
    kubectl -n kube-system edit configmap coredns
    • 添加 log
    • kubectl logs -n kube-system -l k8s-app=kube-dns
      • 查看服务运行日志
    检查 DNS 配置
    查看 resolv.conf 文件的内容
    • kubectl exec -ti dnsutils -- cat /etc/resolv.conf
    官方样例,search 域可能根据云供应商变化
    检查 DNS 服务和 CoreDNS Pod 运行情况
    • kubectl get svc --namespace=kube-system
      • 查看 kube-dns 是否运行
    • kubectl get pods --namespace=kube-system -l k8s-app=kube-dns
      • 查看对应 DNS pods 是否运行
    • kubectl logs --namespace=kube-system -l k8s-app=kube-dns
      • 查看服务运行日志
    检查 DNS 端点公开情况
    • kubectl get endpointslices -l k8s.io/service-name=hostnames
      • 检查 pod 对应 endpointslices
      • 假设应用具有以下 label
        • k8s.io/service-name: hostnames
    检查 CoreDNS RBAC 权限
    • CoreDNS 必须能够列出 service 和 endpoint 相关的资源来正确解析服务名称
    • kubectl describe clusterrole system:coredns -n kube-system
    预期输出结果
    • 缺失权限时编辑 ClusterRole 来添加
      • kubectl edit clusterrole system:coredns -n kube-system
    部分 DNS 已知问题
    部分 Linux 发行版如 Ubuntu 本地 DNS 解析器 systemd-resolved 覆盖 /etc/resolv.conf 内容,可能导致在上游服务器中解析域名产生转发环
    • 可以手动指定 kubelet 的 --resolv-conf 标志为正确的 resolv.conf
      • systemd-resolved 对应路径为 /run/systemd/resolve/resolv.conf
    • 也可以禁用本地 DNS 解析器 stub
      • 如何禁用 nameserver 127.0.0.53
        • resolvectl status | grep resolv.conf
          • resolv.conf mode: stub 代表当前配置了 127.0.0.53 为域名服务器
        • vim /etc/systemd/resolved.conf
          • #DNSStubListener=yes 取消注释并改为 DNSStubListener=no 即可禁用
          • systemctl restart systemd-resolved
    Linux 的 libc 默认将 DNS nameserver 记录限制为 3, 而 Kubernetes 需要使用 1 条 nameserver 记录
    • 如果本地的安装已经使用了 3 个 nameserver,那么其中有些条目将会丢失
    • 可以手动指定 kubelet 的 --resolv-conf 标志为正确的 resolv.conf
      • systemd-resolved 对应路径为 /run/systemd/resolve/resolv.conf
    • 也可以运行  dnsmasq,以提供更多 nameserver 条目
    使用 Alpine 3.17 或更早版本作为你的基础镜像,DNS 可能会由于 Alpine 的设计问题而无法工作
    • 将镜像升级到 Alpine 3.18 或更高版本
    • 删除
      • kubectl delete -f ~/.config/k3s/dnsutils.yaml
     

    kubernete 集群备份和恢复

    kubectl 备份所有资源配置
    • kubectl get all --all-namespaces -o yaml > all-deploy-services.yaml
      • 但仍仅适用于少数资源组
    存储集群数据的外部 etcd 备份和恢复
    参考资料
    • 注意,etcd 的各种证书和凭据必须保持一致
    分为内部 etcd 和外部 etcd
    • 外部只需要直接修改 etcd 数据目录指向恢复后的数据目录即可
    • 内部要区分是否挂载 hostpath 或持久卷作为数据目录
      • 挂载了 hostpath 则参考外部 etcd 处理方法,修改挂载目录
      • 如果挂载了持久卷考虑使用 Velero 备份持久卷并恢复
    通过查看 kubectl-apiserver 配置项可以找到 etcd 的配置方式
    • vim /etc/kubernetes/manifests/kube-apiserver.yaml
    假设已设置 etcdctl 环境变量
    • kubectl port-forward --namespace default svc/etcd 2379:2379 &
      • 如果是内部 etcd
    • mkdir -p /data/backup /var/lib/etcd-from-backup
      • /data/backup 用于 etcd 备份数据
      • /var/lib/etcd-from-backup 用于存放恢复后的数据
    • sudo etcdctl snapshot save /data/backup/etcd-backup-$(date +%Y%m%d-%H%M%S).db
      • 备份到 /data/backup
    • sudo etcdctl snapshot status /data/backup/<backup-db-filename>.db -w table
      • 验证备份 db
    • sudo etcdctl snapshot restore /data/backup/<backup-db-filename>.db --data-dir /var/lib/etcd-from-backup
      • 恢复备份文件到 /var/lib/etcd-from-backup
      • 需要注意文件夹权限
    • 修改 etcd 服务以使用新的数据目录并重启
      • 可能需要删除重启控制平面对应 pod
    使用 velero 工具备份 k8s 集群
     
    上一篇
    k8s 工作负载管理
    下一篇
    k8s 使用 Job 和 CronJob 一次性或定期运行 Pod

    Comments
    Loading...