AI Infra 训练营
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
HiHuo 主站
GitHub
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
HiHuo 主站
GitHub
  • Day 0 · 环境与硬件

    • Day 0:5 节点裸 Ubuntu → K8s 装机基线
  • Week 1:K8s 内核 + 周边基础设施

    • Day 1:3 CP HA 集群 + CNI 选型 + DNS 调优
    • Day 2: 控制面 deep dive + etcd 内核 + chaos drill
    • Day 3: CRD + Operator (kubebuilder 从 0 写)
    • Day 4: Storage 主线 + Cilium 二探
    • Day 5: Volume Expansion + 安全主线
    • Day 6: 调度 + 观测主线 + Day 2 遗留修复
    • Day 7: Harbor + ArgoCD + Cilium Service Mesh
  • Week 2:制品 + GitOps + AI Infra + 综合

    • Day 8 主线 — AI Infra: GPU + k3s + vLLM + Qwen2.5
    • Day 8 主线 — AI Infra 尝试 1 (跨 WAN GPU 加入主集群)
    • Day 8 (alt) — AlertManager 真接入 + PrometheusRule 实战
    • Day 8: CI Infrastructure — Gitea + Jenkins + Kaniko
    • Day 9: Triton + GPU Metrics + 推理性能对比
    • Day 10: MIG + 量化 + HPA Custom Metrics
    • Day 11: AI Agent 业务端到端 — 把 Day 1-10 全部串起来
    • Day 12: 灾难恢复 + 生产事故注入
    • Day 13: LLM Operator + 联邦 + Mesh + RAG
    • Day 14: CKA/CKS 真题演练 + 14 天 Bootcamp 终极总结

Day 12: 灾难恢复 + 生产事故注入

目标: Day 1-11 都在"建",Day 12 来"破" + "救",完成完整闭环 价值: SRE / 平台工程师 / CKA-CKS 必考核心 耗时: 4-5 小时 风险: 真的会让集群短暂不可用,得有 backup 保证可恢复


0. TL;DR (4 个事故)

段事故注入恢复手段
A etcd cp 节点损毁stop etcd + 删 /var/lib/etcdsnapshot restore + member add
B OOM 雪崩deploy mem hog Pod 抢占资源LimitRange + ResourceQuota + 杀 Pod
C Cilium 全 downdelete cilium DaemonSetreapply manifest + 看现存 Pod 是否影响
D 生产 SOP—5 个真事故的应急流程

1. SRE 黄金原则 (面试经典)

3 步法:

1. 止血 (stop the bleeding):
   - 隔离故障组件,防止扩散
   - 流量切走 / 副本下线
   
2. 诊断 (diagnose):
   - 看 events / logs / metrics
   - 不要急着改,先理解 "为什么"
   
3. 修复 (recover):
   - 优先用 "已知好状态" 回滚(snapshot / 上一版本)
   - 复杂事故记录 timeline,事后复盘

核心心态:

  • 不慌: 集群不会"瞬间烧毁",大部分故障可恢复
  • 不蛮: 不要 kubectl delete --force 先,先看 events
  • 不孤: 关键操作 (snapshot restore / 删 etcd) 必须 pair work

10. 实时执行日志(6 维度)

Day 12.A — etcd 灾难:cp-2 节点 etcd 完全损毁 + member remove/add 恢复 ✅

A1. 灾难注入设计 + 实测

场景: cp-2 磁盘故障,/var/lib/etcd 数据丢

实测 timeline:

时刻动作集群状态
T+0snapshot save: 453 MB / 24 万 keys3/3 healthy
T+10smv etcd.yaml + mv /var/lib/etcdcp-2 etcd down
T+20sendpoint health: cp-2 connection refused2/3 quorum,仍可写
T+30scp-2 apiserver CrashLoopBackOffHAProxy 自动 failover 到 cp-1/cp-3
T+60skubectl create ns day12-test✅ 成功(per-node HAProxy 救场)
T+90setcdctl member remove c14422e68fa9c73e2/2 active members
T+100setcdctl member add k8s-cp-2接受新 member
T+110s修 cp-2 etcd.yaml: --initial-cluster-state=existing + 3-node cluster listmanifest 就绪
T+120smv etcd.yaml 回 manifests/kubelet 自启 etcd Pod
T+140setcd container Running从 leader 拉 snapshot/WAL
T+180sendpoint health 3/3 true完全恢复

Total recovery time: ~2 分钟(从注入到 quorum 恢复)

A2. Pre-Disaster Snapshot

What (在 cp-1 上跑,etcd pod 健康时):

# 进 cp-1 etcd pod 跑 snapshot
ETCD_POD=$(kubectl get pod -n kube-system -l component=etcd \
  --field-selector=spec.nodeName=k8s-cp-1 -o name | head -1)

kubectl exec -n kube-system $ETCD_POD -- sh -c "ETCDCTL_API=3 etcdctl \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  snapshot save /tmp/snapshot-day12.db"

# 把 snapshot 拷出 cp-1 (Pod 临时存储, Pod 重启会丢)
kubectl cp -n kube-system $ETCD_POD:/tmp/snapshot-day12.db /root/etcd-backups/snapshot-$(date +%Y%m%d-%H%M).db
ls -la /root/etcd-backups/

Snapshot 文件大小约 2-5 MB(我们集群规模)

生产策略:

  • CronJob 每 30min 自动 snapshot
  • 拷出集群到 S3 / NFS / 异地
  • 保留 ≥ 7 天历史,可时间点回滚

A3. 注入故障 — cp-2 etcd 完全损毁

(开干填)

A4. 不是直接 restore — 正确流程

为什么不能直接 restore?

错误流程 (新手):
  cp-2 etcd data 丢 → 在 cp-2 上 etcdctl snapshot restore
  → 启动 etcd 用恢复的 data → 加入集群?
  ❌ 错!restore 出来的 etcd 是"独立 cluster",member-id 跟现有 cluster 不一致
  → etcd 拒绝 join, "member ID mismatch"

正确流程:
  1. etcdctl member remove <cp-2 member id>  (从集群 active member 列表移除)
  2. 在 cp-2 上清空 etcd data dir
  3. 修改 etcd static pod manifest 加 --initial-cluster-state=existing
  4. etcd member add <cp-2 url> 让 cluster 接受新 member
  5. cp-2 etcd 启动,作为"新 member"加入(数据从 leader 拉)

关键认知: snapshot restore 适合"整个 cluster 全死了"灾难,单节点损毁应该用 member add

A5. 多 cp 全死的最严重灾难场景 — snapshot restore

3 个 cp etcd 全死 (机房断电 + 数据损毁):
  1. 在某个还有 snapshot 的节点跑 restore:
     etcdctl snapshot restore snapshot.db \
       --name k8s-cp-1 \
       --initial-cluster k8s-cp-1=https://10.0.24.31:2380 \
       --initial-cluster-token etcd-cluster-1 \
       --initial-advertise-peer-urls https://10.0.24.31:2380 \
       --data-dir /var/lib/etcd-new
  
  2. mv /var/lib/etcd-new /var/lib/etcd
  
  3. 修改 etcd manifest 启动单节点 cluster (initial-cluster-state=new)
  
  4. 其他 2 个 cp 重新 join: kubeadm reset + kubeadm join with new token

时间点丢失 = 距上次 snapshot 的时间(如 30 min 内的变更全丢)。


Day 12.B — OOM 雪崩注入 + LimitRange 救场 ✅

B1. 注入 — BestEffort Pod 抢 6GB(w-2 只 8GB)

apiVersion: v1
kind: Pod
metadata: {name: mem-hog, namespace: day12-test}
spec:
  restartPolicy: Never
  containers:
  - name: stress
    image: polinux/stress
    args: [stress, --vm, "1", --vm-bytes, "6G", --vm-hang, "180"]
    # ⚠️ 不设 resources.limits → BestEffort QoS → OOM killer 第一目标

Actual (15-60s 内):

dmesg:
  oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=cri-containerd-...scope
  Out of memory: Killed process 1530928 (stress) total-vm:6292240kB, anon-rss:6188660kB
  Tasks in /kubepods.slice/kubepods-besteffort.slice/... are going to be killed due to memory.oom.group set
  oom_reaper: reaped process 1530928

kubectl get pod mem-hog:
  Status: OOMKilled, exitCode 137

关键观察:

  • 集群其他 Pod 完全没受影响(longhorn / cilium / etcd 全 healthy)
  • BestEffort QoS Pod 被精准杀掉,Burstable / Guaranteed 不动
  • Node MemoryPressure 没触发(kernel OOM killer 比 K8s Eviction 更快)

B2. 救场 — LimitRange + ResourceQuota

---
apiVersion: v1
kind: LimitRange
metadata: {name: default-limits, namespace: day12-test}
spec:
  limits:
  - type: Container
    default: {cpu: 500m, memory: 512Mi}     # 没设 limit 用这个
    defaultRequest: {cpu: 100m, memory: 128Mi}
    max: {cpu: 2, memory: 2Gi}              # 上限,即使显式写也不能超
---
apiVersion: v1
kind: ResourceQuota
metadata: {name: ns-quota, namespace: day12-test}
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 4Gi
    limits.cpu: "8"
    limits.memory: 8Gi
    pods: "10"

再注入同样 6GB stress Pod:

mem-hog-v2:
  Limits:    cpu 500m, memory 512Mi  ← LimitRange 自动注入
  Requests:  cpu 100m, memory 128Mi
  Status:    OOMKilled (15s 内)
  ExitCode:  137

关键区别:

  • 第一次:节点级 OOM(kernel OOM killer 杀整个 BestEffort cgroup)
  • 第二次:容器级 OOM(container cgroup 到 limit 立刻被 kill,精确隔离)

生产推论:

  • 任何 namespace 上线都先加 LimitRange + ResourceQuota
  • Kyverno require-resources policy 双保险(我们 Day 5.F 已配)
  • 监控 kube_pod_container_status_last_terminated_reason{reason="OOMKilled"}

Day 12.C — Cilium 全 down 流量切断 + helm upgrade 恢复 ✅

C1. 注入

kubectl delete ds cilium -n kube-system

Actual (10-20s 内):

cilium-agent Pods: All deleted (5/5 gone)
Node taints:
  k8s-cp-1: node.cilium.io/agent-not-ready (set by cilium operator)
  k8s-cp-2: node.cilium.io/agent-not-ready
  ... 所有节点

C2. 影响分析(面试可讲)

影响项状态
新 Pod 调度❌ 阻塞 — FailedScheduling: untolerated taint cilium.io/agent-not-ready
已有 Pod✅ 进程不动(eBPF 程序在内核还在)
跨节点 Pod-to-Pod❌ Connection refused(SNAT/DNAT 失效)
Pod → ClusterIP Service⚠️ 间歇性失败(iptables-rule 但 Cilium 实际接管)
已有 Pod 跟 host network✅ 不影响
Hubble flow❌ Relay 收不到数据(agent 死了)

C3. 恢复

helm upgrade cilium cilium/cilium --reuse-values --version 1.16.5 -n kube-system

Actual (60-180s):

  • Cilium DaemonSet 重建,5 agent Pod Running
  • agent ready → cilium-operator 自动移除节点 taint
  • 新 Pod 调度恢复(test-recover 在 w-2 上 Running,IP 10.244.1.182)

关键认知:

  • Cilium 用 taint-on-startup 模式: agent 没 ready 时节点带 taint
  • 这是防御机制 — 防止 Pod 调度到无网络节点变僵尸
  • 删 DS 等于全集群 taint 强制 Pause,helm reapply 即恢复

Day 12.D — 生产 SOP 应急手册

D1. 5 个真生产事故的 SOP

SOP-1: etcd 单 cp 节点损毁

症状:

  • 1 个 cp 节点的 etcd Pod CrashLoopBackOff 或 Pod 起不来
  • kubectl get nodes 仍 work(2/3 quorum 维持)
  • 该 cp 节点的 apiserver 也 CrashLoopBackOff
  • 用户报"偶尔 kubectl 超时"(HAProxy 健康检查标 cp 为 unhealthy 之前)

应急 SOP:

[1分钟] 1. 确认影响范围:
   ETCD_POD=$(kubectl get pod -n kube-system -l component=etcd \
     --field-selector=spec.nodeName=k8s-cp-1 -o name | head -1)
   kubectl exec -n kube-system $ETCD_POD -- etcdctl endpoint health \
     --endpoints=<3-cp-2379-list>

[3分钟] 2. 拉最新 snapshot (灾难前一次的):
   ls -la /backup/etcd-snapshots/
   # 找最近的 *.db

[5分钟] 3. member remove 死掉的 cp:
   etcdctl member remove <cp-id>

[10分钟] 4. 修复磁盘 / 重建节点 / 清 /var/lib/etcd

[15分钟] 5. member add + 改 manifest --initial-cluster-state=existing
   etcdctl member add <new-cp-name> --peer-urls=https://<cp-ip>:2380
   # 改 /etc/kubernetes/manifests/etcd.yaml 加 existing + 新 cluster list

[20分钟] 6. mv etcd.yaml 回 manifests/
   等 30s, kubelet 自启 etcd

[25分钟] 7. 验证 3/3 healthy
   etcdctl endpoint health
   kubectl get pods -n kube-system -l component=etcd

Total: 25 分钟内可救回


SOP-2: 所有 cp 死(灾难级 — 整机房断电)

症状: kubectl get nodes 卡死,所有 apiserver 不可达

SOP:

1. 别慌。worker 节点上 Pod 一直在跑(kubelet local mode)
2. 找最近 snapshot(异地 backup,不能丢在本机房!)
3. 选 1 个 cp 节点:
   etcdctl snapshot restore snapshot.db \
     --name <cp1-hostname> \
     --initial-cluster <cp1>=https://<cp1-ip>:2380 \
     --initial-cluster-token <new-token> \
     --initial-advertise-peer-urls https://<cp1-ip>:2380 \
     --data-dir /var/lib/etcd-new
4. mv /var/lib/etcd-new → /var/lib/etcd
5. 改 etcd manifest --initial-cluster-state=new + initial-cluster 仅含 cp1
6. cp1 起来后,其他 cp 走 kubeadm reset + kubeadm join 重新加入
7. 时间点丢失 = 距上次 snapshot 时间(所以高频 snapshot 必要!)

关键: snapshot 必须异地存(S3/异机房 NFS),不能跟集群同处


SOP-3: Worker 节点 OOM 雪崩

症状:

  • 节点 MemoryPressure: True
  • 多个 Pod Evicted
  • Grafana 看 node mem util > 95%

SOP:

[即刻] 1. 隔离: kubectl drain <node> --ignore-daemonsets
        → 把 workload 调走

[5分钟] 2. 找元凶 Pod:
        kubectl top pods -A --sort-by=memory | head -10
        # 看哪个 Pod mem 异常高

[10分钟] 3. 临时杀掉元凶: kubectl delete pod <elite-name>

[长期修复]:
4. namespace 加 LimitRange 默认 limit
5. namespace 加 ResourceQuota 总量
6. Kyverno policy require-resources enforce (Day 5.F)
7. Grafana 加 alert: 当 mem_util > 85% 持续 5min → 钉钉

SOP-4: CNI (Cilium) 全集群 down

症状:

  • kubectl get nodes work
  • 但新 Pod 卡 Pending: untolerated taint node.cilium.io/agent-not-ready
  • 已有跨节点 Pod 通信失败

SOP:

[立刻] 1. 不要 panic delete 任何 Pod (避免破坏现有 work)
       2. 检查: kubectl get pods -n kube-system -l k8s-app=cilium
        a. 如果空 (DS 被误删) → helm upgrade cilium 重装
        b. 如果 CrashLoopBackOff → 看 log + 重启 Pod
        c. 如果 Pending → 看 events (image pull / RBAC)

[5分钟] 3. 业务流量切走 (DNS 切到备 cluster 或 fallback page)

[10分钟] 4. helm upgrade cilium cilium/cilium --reuse-values
        sleep 60
        kubectl get pods -n kube-system -l k8s-app=cilium

[15分钟] 5. 验证: 起一个 test Pod 看 IP 分配 + ping 跨节点 Pod

预防: Cilium DS 加 priorityClassName: system-node-critical,严防被 evict


SOP-5: apiserver cert 过期

症状:

  • kubectl 报 x509: certificate has expired
  • 集群所有 apiserver 同时挂(同时 install 同时过期)

SOP:

[预防为主!]
1. 监控 cert 过期: prometheus alert
   apiserver_client_certificate_expiration_seconds{quantile="0.01"} < 30*24*3600

[一年 -1天] 2. 提前续期:
   sudo kubeadm certs renew all
   # 重启 cp 上的 apiserver / controller / scheduler

[已过期但还能 ssh]:
3. ssh 进 cp,kubeadm certs renew all
4. 直接重启 etcd / kubelet / restart kube-apiserver pod

[集群完全失联]:
5. 进单个 cp 节点:
   kubeadm certs renew all
   systemctl restart kubelet
6. 用 /etc/kubernetes/admin.conf 在该节点本地 kubectl 救集群

D2. 黄金原则

原则解释
3-2-1 backup3 份 backup,2 种介质,1 份异地
chaos engineering月度灾难演练(我们就在做!)
runbook 即代码SOP 写 markdown,放 git,review
没 monitor 没 alert 没 SLO 等于裸奔Prometheus + AlertManager + 钉钉
关键操作 pair work删 etcd / --force 必须 2 人 review
回滚优先于修复snapshot restore 比"边修边推断"快 10x

99. Day 12 完整完成

  • [x] A — etcd cp-2 损毁注入 + member remove/add 恢复(2 min)
  • [x] B — OOM 雪崩注入 + LimitRange 救场(15s 容器 OOM)
  • [x] C — Cilium 全 DS 删 + helm upgrade 恢复(60s 内 agent 起 + taint 清)
  • [x] D — 5 个真生产事故 SOP 写完整

简历金句:

做过 K8s 灾难恢复全链路演练:

  • etcd: 单 cp 节点 etcd 数据完全损毁 → member remove/add + --initial-cluster-state=existing 2 min 救回 3/3 quorum
  • OOM: BestEffort Pod 6GB 抢占 → 节点 OOM kill 整 cgroup;LimitRange + ResourceQuota 后转为容器级精确 OOM
  • CNI: Cilium 全 DS 删 → 节点自动 taint + 新 Pod Pending 防御 + helm upgrade 60s 恢复
  • 完整 SOP 应急手册:5 个真生产事故 × 25 分钟内救回
在 GitHub 上编辑此页
Prev
Day 11: AI Agent 业务端到端 — 把 Day 1-10 全部串起来
Next
Day 13: LLM Operator + 联邦 + Mesh + RAG