Files
k8smanager-cli/故障报告/Kubernetes 集群故障分析报告.md
T

25 KiB

Kubernetes 集群故障分析报告

报告时间: 2026-07-25T07:36:59 集群健康评分: 0/100 (Critical) 问题严重程度: 4个严重问题, 30个警告问题


一、故障概述

本次集群故障表现为严重的控制平面组件异常,导致集群处于不可用状态。主要症状包括:

  • etcd (集群核心数据库) 完全不可用,两个节点均处于CrashLoopBackOff状态
  • kube-apiserver (API服务器) 三个节点全部异常,无法响应请求
  • kube-schedulerkube-controller-manager 也出现不稳定状态
  • 整个集群基本功能瘫痪,无法处理任何工作负载部署请求

二、根本原因分析 (Root Cause Analysis)

🔴 问题1: etcd集群完全崩溃

根本原因: etcd集群的持久化存储或网络配置出现问题

  • 两个etcd节点 (ansible-client-01/02) 均出现503状态码错误
  • 高频次重启 (38次/30次) 表明容器启动后立即失败
  • 启动探针失败返回503,表明etcd服务无法正常初始化

可能的技术原因:

  1. 存储问题: etcd数据目录损坏或磁盘空间不足
  2. 网络分区: etcd节点之间无法建立集群通信
  3. 证书过期: etcd的TLS证书可能已过期
  4. 资源不足: etcd容器内存或CPU资源不足

🔴 问题2: kube-apiserver无法启动

根本原因: kube-apiserver依赖的etcd集群不可用

  • 所有三个apiserver节点 (ansible-client-01/02, ubuntu2204) 都失败
  • 错误信息显示"connection reset by peer"和"connection refused"
  • 启动探针返回500错误,表明服务无法初始化

依赖链分析:

etcd不可用 → apiserver无法连接etcd → apiserver启动失败 → 其他组件依赖apiserver失败

🟡 问题3: kube-scheduler/kube-controller-manager不稳定

根本原因: 由于apiserver不可用,这些组件无法正常工作

  • 依赖apiserver获取集群状态和调度决策
  • 在等待apiserver恢复过程中进入BackOff状态

🟡 问题4: 节点存储异常

根本原因: ubuntu2204节点的Docker容器存储驱动配置错误

  • "invalid capacity 0 on image filesystem"错误
  • 容器运行时无法正确计算存储空间

三、影响评估

🔴 业务影响 (Critical)

  1. 集群完全不可用: 无法部署、更新或管理任何工作负载
  2. 现有应用可能受影响: 依赖Kubernetes API的所有服务将失败
  3. 数据丢失风险: etcd是集群状态存储,如果损坏会导致元数据丢失
  4. 恢复时间延长: 控制平面完全崩溃需要完整恢复流程

🟡 运维影响 (High)

  1. 无法进行任何kubectl操作: 所有API请求失败
  2. 自动修复失效: HPA、自愈等机制无法工作
  3. 监控告警风暴: 持续产生大量错误事件

四、优先级排序与修复方案

优先级1: 恢复etcd集群 (最紧急)

问题: etcd集群是Kubernetes的基础,必须首先恢复

修复步骤:

步骤1: 检查etcd节点状态

# SSH到ansible-client-01节点
ssh root@<ansible-client-01-ip>

# 检查etcd容器日志
docker logs etcd-ansible-client-01 --tail 100

# 检查etcd端点状态
ETCDCTL_API=3 etcdctl endpoint health \
  --endpoints=https://192.168.40.11:2379,https://192.168.40.12:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

步骤2: 检查存储和网络

# 检查磁盘空间
df -h /var/lib/etcd

# 检查网络连接
telnet 192.168.40.11 2379
telnet 192.168.40.12 2380  # etcd peer端口

# 检查证书是否过期
openssl x509 -in /etc/kubernetes/pki/etcd/server.crt -text -noout | grep "Not After"

步骤3: 修复方案

方案A: 如果存储损坏

# 备份现有数据目录
mv /var/lib/etcd /var/lib/etcd.backup.$(date +%s)

# 创建新的etcd数据目录
mkdir -p /var/lib/etcd
chown -R etcd:etcd /var/lib/etcd

# 重启etcd服务
systemctl restart etcd

方案B: 如果证书过期

# 重新生成etcd证书
kubeadm init phase certs etcd-server
kubeadm init phase certs etcd-peer
kubeadm init phase certs etcd-healthcheck-client

# 更新kube-apiserver的etcd客户端证书
kubeadm init phase certs apiserver-etcd-client

# 重启etcd和kube-apiserver
systemctl restart etcd
systemctl restart kubelet

方案C: 完全重建etcd集群 (最后手段)

# 在其中一个节点重建etcd集群
# 1. 停止所有etcd实例
systemctl stop etcd

# 2. 备份数据
mv /var/lib/etcd /var/lib/etcd.bak

# 3. 重新初始化集群
ETCDCTL_API=3 etcdctl member remove <member-id>
ETCDCTL_API=3 etcdctl member add ansible-client-01 --peer-urls=https://192.168.40.11:2380

# 4. 启动新的单节点etcd
etcd --name ansible-client-01 \
  --initial-advertise-peer-urls https://192.168.40.11:2380 \
  --listen-peer-urls https://192.168.40.11:2380 \
  --advertise-client-urls https://192.168.40.11:2379 \
  --listen-client-urls https://192.168.40.11:2379,https://127.0.0.1:2379 \
  --initial-cluster-token etcd-cluster-01 \
  --initial-cluster ansible-client-01=https://192.168.40.11:2380 \
  --initial-cluster-state new

优先级2: 恢复kube-apiserver

前提: etcd集群已恢复

修复步骤:

步骤1: 检查apiserver配置

# 检查kube-apiserver Pod规格
kubectl get pod kube-apiserver-ansible-client-01 -n kube-system -o yaml

# 检查启动命令参数
kubectl get pod kube-apiserver-ansible-client-01 -n kube-system -o jsonpath='{.spec.containers[0].command}'

步骤2: 检查资源限制

# 查看apiserver的资源使用
kubectl top pod kube-apiserver-ansible-client-01 -n kube-system

# 检查节点资源
kubectl describe node ansible-client-01

步骤3: 修复方案

增加启动探针超时时间 (临时方案):

# 编辑kube-apiserver Pod规范
kubectl edit pod kube-apiserver-ansible-client-01 -n kube-system

# 添加或修改以下字段:
spec:
  containers:
  - name: kube-apiserver
    startupProbe:
      failureThreshold: 60      # 增加失败阈值
      periodSeconds: 5           # 增加检查周期
      timeoutSeconds: 15         # 增加超时时间

检查并修复资源限制:

# 确保有足够的资源
resources:
  requests:
    cpu: "500m"
    memory: "2Gi"
  limits:
    cpu: "2000m"
    memory: "4Gi"

优先级3: 恢复kube-controller-manager和kube-scheduler

修复步骤:

# 检查这些组件的依赖
kubectl get event -n kube-system --field-selector reason=BackOff

# 重启这些组件 (如果etcd和apiserver已恢复)
systemctl restart kubelet

优先级4: 修复节点存储问题

问题: ubuntu2204节点的Docker存储驱动配置错误

修复步骤:

# SSH到ubuntu2204节点
ssh root@<ubuntu2204-ip>

# 检查Docker存储驱动
docker info | grep "Storage Driver"

# 检查存储空间
df -h /var/lib/docker

# 修复方案1: 重启Docker服务
systemctl restart docker

# 修复方案2: 如果存储驱动配置错误
# 编辑Docker配置文件
vi /etc/docker/daemon.json
# 确保包含正确的storage-driver配置,例如:
{
  "storage-driver": "overlay2"
}

# 重启Docker
systemctl restart docker
systemctl restart kubelet

五、验证修复

步骤1: 验证etcd健康状态

# 检查etcd集群状态
ETCDCTL_API=3 etcdctl endpoint health \
  --endpoints=https://192.168.40.11:2379,https://192.168.40.12: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 list \
  --endpoints=https://192.168.40.11:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

步骤2: 验证kube-apiserver状态

# 检查apiserver Pod状态
kubectl get pods -n kube-system | grep kube-apiserver

# 检查apiserver健康状态
kubectl get --raw='/readyz?verbose'

# 检查集群状态
kubectl cluster-info
kubectl get nodes

步骤3: 运行完整集群诊断

# 使用kubectl检查组件状态
kubectl get componentstatuses

# 检查所有系统Pod
kubectl get pods -n kube-system

# 检查集群事件
kubectl get events -n kube-system --sort-by='.lastTimestamp'

六、预防措施

1. 监控告警增强

# 添加以下Prometheus告警规则
groups:
- name: kubernetes-system
  rules:
  - alert: EtcdMembersDown
    expr: etcd_server_has_leader{job="etcd"} == 0
    for: 2m
    labels:
      severity: critical
    annotations:
      summary: "Etcd member has no leader"
      
  - alert: EtcdHighCommitDuration
    expr: etcd_disk_wal_fsync_duration_seconds{job="etcd"} > 1
    for: 10m
    labels:
      severity: warning

2. 定期维护任务

  • 每周: 检查etcd数据库大小,执行碎片整理

    etcdctl defrag --endpoints=<endpoint>
    
  • 每月: 检查证书过期时间

    kubeadm certs check-expiration
    
  • 每季度: 演练etcd备份恢复流程

3. 资源规划和配置优化

  • 为etcd分配专用存储和高性能磁盘
  • 设置合适的资源限制和请求
  • 启用etcd自动备份和远程存储

4. 网络策略优化

  • 确保etcd节点间网络延迟<10ms
  • 配置专用网络段给控制平面组件
  • 启用网络策略限制不必要的流量

5. 升级和补丁管理

# 定期升级Kubernetes版本
kubeadm upgrade plan
kubeadm upgrade apply

# 及时应用安全补丁
apt update && apt upgrade

6. 文档和演练

  • 维护详细的集群架构文档
  • 定期进行灾难恢复演练
  • 建立标准化的操作手册

七、附录

附录A: 关键命令参考

# etcd健康检查
ETCDCTL_API=3 etcdctl endpoint health --endpoints=<endpoint> --cacert=<ca> --cert=<cert> --key=<key>

# etcd备份
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-snapshot.db

# 集群证书检查
kubeadm certs check-expiration

# 节点资源检查
kubectl describe node <node-name>

附录B: 相关文件位置

  • etcd数据目录: /var/lib/etcd/
  • Kubernetes证书: /etc/kubernetes/pki/
  • etcd证书: /etc/kubernetes/pki/etcd/
  • kubelet配置: /var/lib/kubelet/config.yaml

附录C: 重要端口列表

| 组件 | 端口 | 协议 | 用途 | |------|

继续

附录C: 重要端口列表

组件 端口 协议 用途
kube-apiserver 6443 HTTPS API服务器安全端口
etcd 2379 HTTPS etcd客户端通信端口
etcd 2380 HTTPS etcd集群节点间通信端口
kubelet 10250 HTTPS kubelet API端口
kube-scheduler 10259 HTTPS 调度器端口
kube-controller-manager 10257 HTTPS 控制器管理器端口

附录D: 本次故障事件时间线(还原)

根据诊断报告中的重启次数和事件记录,推断出以下故障演进时间线:

时间线还原 (推测)

阶段1: etcd 首先出现异常
  ├── ansible-client-01 的 etcd 容器开始 CrashLoop
  ├── ansible-client-02 的 etcd 容器开始 CrashLoop  
  ├── 启动探针返回 HTTP 503
  └── etcd 集群丧失 quorum(多数派共识)

阶段2: kube-apiserver 因 etcd 不可用而连锁失败
  ├── ansible-client-01 apiserver: connection reset by peer
  ├── ansible-client-02 apiserver: connection refused
  ├── ubuntu2204 apiserver: HTTP 500 错误
  └── 所有 apiserver 进入 CrashLoopBackOff

阶段3: 控制平面其他组件受波及
  ├── kube-controller-manager 重启 6 次后进入 BackOff
  ├── kube-scheduler 重启 7 次后进入 BackOff
  └── TLS handshake timeout(因 apiserver 不可用)

阶段4: 业务层面影响显现
  ├── ubuntu2204 节点报告 InvalidDiskCapacity
  ├── 所有 kubectl 操作失败
  ├── 集群健康评分降至 0/100
  └── 集群完全不可用

附录E: etcd 数据备份与恢复 SOP(标准操作流程)

E.1 etcd 定期备份脚本

#!/bin/bash
# etcd-backup.sh - 定期备份 etcd 数据
# 建议通过 cron 每小时执行一次

BACKUP_DIR="/backup/etcd"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/etcd-snapshot-${DATE}.db"
ETCD_ENDPOINT="https://192.168.40.11:2379"
ETCD_CACERT="/etc/kubernetes/pki/etcd/ca.crt"
ETCD_CERT="/etc/kubernetes/pki/etcd/server.crt"
ETCD_KEY="/etc/kubernetes/pki/etcd/server.key"

# 创建备份目录
mkdir -p ${BACKUP_DIR}

# 执行备份
ETCDCTL_API=3 etcdctl snapshot save ${BACKUP_FILE} \
  --endpoints=${ETCD_ENDPOINT} \
  --cacert=${ETCD_CACERT} \
  --cert=${ETCD_CERT} \
  --key=${ETCD_KEY}

# 验证备份
ETCDCTL_API=3 etcdctl snapshot status ${BACKUP_FILE} --write-table

# 保留最近 30 个备份
ls -t ${BACKUP_DIR}/etcd-snapshot-*.db | tail -n +31 | xargs rm -f

echo "[${DATE}] etcd backup completed: ${BACKUP_FILE}"

E.2 etcd 灾难恢复流程

#!/bin/bash
# etcd-restore.sh - 从备份恢复 etcd

SNAPSHOT_FILE=$1  # 备份文件路径
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_NAME="ansible-client-01"
ETCD_INITIAL_CLUSTER="ansible-client-01=https://192.168.40.11:2380,ansible-client-02=https://192.168.40.12:2380"

if [ -z "${SNAPSHOT_FILE}" ]; then
    echo "Usage: $0 <snapshot-file>"
    exit 1
fi

echo "=== Step 1: 停止所有 etcd 实例 ==="
systemctl stop etcd
sleep 5

echo "=== Step 2: 备份当前数据目录 ==="
if [ -d "${ETCD_DATA_DIR}" ]; then
    mv ${ETCD_DATA_DIR} ${ETCD_DATA_DIR}.bak.$(date +%s)
fi

echo "=== Step 3: 从快照恢复数据 ==="
ETCDCTL_API=3 etcdctl snapshot restore ${SNAPSHOT_FILE} \
  --name ${ETCD_NAME} \
  --initial-cluster ${ETCD_INITIAL_CLUSTER} \
  --initial-advertise-peer-urls https://192.168.40.11:2380 \
  --data-dir ${ETCD_DATA_DIR}

echo "=== Step 4: 设置权限 ==="
chown -R etcd:etcd ${ETCD_DATA_DIR}

echo "=== Step 5: 启动 etcd ==="
systemctl start etcd

echo "=== Step 6: 验证恢复结果 ==="
sleep 10
ETCDCTL_API=3 etcdctl endpoint health \
  --endpoints=https://192.168.40.11:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

ETCDCTL_API=3 etcdctl member list \
  --endpoints=https://192.168.40.11:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  --write-table

echo "=== 恢复完成 ==="

E.3 etcd 快照恢复后恢复集群其余节点

#!/bin/bash
# 在恢复第一个 etcd 节点成功后,将其他节点加入集群

# Step 1: 在已恢复的节点上,移除旧成员
ETCDCTL_API=3 etcdctl member remove <old-member-id> \
  --endpoints=https://192.168.40.11:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

# Step 2: 添加新成员
ETCDCTL_API=3 etcdctl member add ansible-client-02 \
  --peer-urls=https://192.168.40.12:2380 \
  --endpoints=https://192.168.40.11:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

# Step 3: SSH到 ansible-client-02,清理数据目录并启动
# ssh root@192.168.40.12
# rm -rf /var/lib/etcd/*
# systemctl restart etcd

# Step 4: 验证集群成员
ETCDCTL_API=3 etcdctl member list \
  --endpoints=https://192.168.40.11:2379,https://192.168.40.12:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  --write-table

附录F: 推荐的 CronJob 定时备份配置

apiVersion: batch/v1
kind: CronJob
metadata:
  name: etcd-backup
  namespace: kube-system
spec:
  schedule: "0 */1 * * *"  # 每小时执行一次
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 3
  jobTemplate:
    spec:
      template:
        spec:
          nodeSelector:
            kubernetes.io/hostname: ansible-client-01
          hostNetwork: true
          tolerations:
          - key: node-role.kubernetes.io/master
            effect: NoSchedule
          containers:
          - name: etcd-backup
            image: bitnami/etcd:3.5.0
            command:
            - /bin/sh
            - -c
            - |
              DATE=$(date +%Y%m%d_%H%M%S)
              ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-snapshot-${DATE}.db \
                --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
              echo "Backup completed: etcd-snapshot-${DATE}.db"
            env:
            - name: ETCDCTL_API
              value: "3"
            volumeMounts:
            - name: etcd-certs
              mountPath: /etc/kubernetes/pki/etcd
              readOnly: true
            - name: backup-dir
              mountPath: /backup
          restartPolicy: OnFailure
          volumes:
          - name: etcd-certs
            hostPath:
              path: /etc/kubernetes/pki/etcd
              type: DirectoryOrCreate
          - name: backup-dir
            hostPath:
              path: /backup/etcd
              type: DirectoryOrCreate

附录G: 集群健康巡检 Checklist

序号 检查项 命令 正常状态 检查频率
1 etcd 集群健康 etcdctl endpoint health 所有节点 healthy 每5分钟
2 etcd 数据库大小 etcdctl endpoint status --write-table < 2GB 每小时
3 etcd 磁盘 fsync 延迟 Prometheus: etcd_disk_wal_fsync_duration_seconds < 10ms 实时
4 apiserver 可用性 kubectl get --raw='/readyz?verbose' 全部 ok 每分钟
5 证书过期时间 kubeadm certs check-expiration > 30天 每周
6 节点资源使用率 kubectl top nodes CPU<80%, Mem<80% 每小时
7 系统 Pod 状态 kubectl get pods -n kube-system 全部 Running 每5分钟
8 PVC 使用率 kubectl get pvc -A < 80% 每小时
9 控制平面组件重启次数 kubectl get pods -n kube-system -o wide 重启次数=0 每小时
10 集群事件异常 kubectl get events -n kube-system --field-selector type=Warning 无新增 Warning 每小时

附录H: 紧急联系人和应急流程

┌─────────────────────────────────────────────────────────┐
│                  集群故障应急响应流程                     │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  Level 1 (P0): 集群完全不可用                            │
│  ├── 控制平面全部异常                                    │
│  ├── etcd 集群丧失 quorum                               │
│  ├── 立即响应,全员介入                                  │
│  └── 预期恢复时间: < 1 小时                              │
│                                                         │
│  Level 2 (P1): 控制平面部分异常                          │
│  ├── 单个 apiserver 节点故障                             │
│  ├── 部分组件 CrashLoop                                 │
│  ├── 30分钟内响应                                       │
│  └── 预期恢复时间: < 2 小时                              │
│                                                         │
│  Level 3 (P2): Worker 节点异常                          │
│  ├── 单个节点 NotReady                                  │
│  ├── 工作负载自动迁移                                    │
│  ├── 1小时内响应                                        │
│  └── 预期恢复时间: < 4 小时                              │
│                                                         │
│  Level 4 (P3): 非关键告警                               │
│  ├── 证书即将过期(>30天)                               │
│  ├── 资源使用率偏高                                      │
│  ├── 24小时内响应                                       │
│  └── 计划性维护窗口处理                                  │
│                                                         │
└─────────────────────────────────────────────────────────┘

八、总结与行动项

📋 立即执行(今日内)

序号 行动项 负责人 优先级 预期完成时间
1 排查 etcd 崩溃根因并恢复集群 SRE团队 P0 立即
2 恢复 kube-apiserver 至正常状态 SRE团队 P0 etcd恢复后30分钟内
3 验证集群功能恢复正常 SRE团队 P0 apiserver恢复后
4 检查是否有数据丢失 DBA/平台团队 P0 集群恢复后

📋 短期执行(本周内)

序号 行动项 负责人 优先级 预期完成时间
5 部署 etcd 自动备份 CronJob SRE团队 P1 3天内
6 配置 etcd 监控告警规则 监控团队 P1 3天内
7 修复 ubuntu2204 节点存储问题 运维团队 P1 2天内
8 更新证书管理流程 SRE团队 P2 一周内

📋 中长期执行(本月内)

序号 行动项 负责人 优先级 预期完成时间
9 建立完整的灾难恢复预案 SRE团队 P1 两周内
10 实施 etcd 自动碎片整理 平台团队 P2 两周内
11 升级 Kubernetes 至最新稳定版 平台团队 P2 一个月内
12 建立定期巡检机制 SRE团队 P2 两周内
13 进行灾难恢复演练 全团队 P2 一个月内

📝 故障复盘要点

本次故障的核心教训:

  1. etcd 是集群的心脏:etcd 故障会导致整个集群瘫痪,必须将其作为最高优先级保护对象
  2. 缺少自动备份机制:如果之前有 etcd 定期备份,恢复时间可以大幅缩短
  3. 监控告警不足:etcd 的健康指标应该有完善的监控和告警,在问题初期就能发现
  4. 证书管理需要自动化:证书过期是 Kubernetes 集群最常见的故障原因之一
  5. 需要建立 SOP 文档:标准操作流程可以在故障时减少决策时间,提高恢复效率

注: 本报告基于诊断数据推断。实际修复时请根据现场日志和具体情况调整方案。建议在修复前先对当前状态做完整快照/备份,以防操作失误导致进一步损坏。