8.1 K8s 生产运维:etcd 备份与恢复
预计阅读时间:17 分钟
📖 目录
etcd 是 Kubernetes 控制面的数据存储,保存了集群的全部状态——Pod、Service、ConfigMap、Secret 等。etcd 数据丢失意味着整个集群的配置丢失。生产环境必须做好 etcd 备份策略。
学习目标
- 理解 etcd 在 Kubernetes 架构中的角色及其数据模型
- 掌握手动与自动化两种 etcd 快照备份方式
- 能够在灾难场景下安全地恢复 etcd 数据并验证集群状态
- 建立生产级别的备份策略与监控告警体系
前置知识
- 熟悉 Kubernetes 控制面组件(kube-apiserver、etcd、controller-manager、scheduler)的基本职责
- 了解 TLS 证书体系——etcd 通信依赖 mTLS 认证
- 具备 Linux 系统管理基础:systemctl、文件权限、证书路径
- 了解 kubeadm 部署方式下静态 Pod 的管理机制(manifest 目录)
etcd 架构回顾
- etcd 是分布式的键值存储,基于 Raft 共识算法
- K8s 控制面组件(kube-apiserver)是唯一直接读写 etcd 的组件
- 集群推荐 3 或 5 节点奇数部署(容忍
(n-1)/2节点故障) - 数据存储路径:
/var/lib/etcd/ - etcd 默认存储配额为 2GB,超过后集群进入只读模式
- Raft 日志会无限增长,需要配置自动压缩(auto-compaction)
etcd 与 K8s 的交互流程
所有 K8s 资源的增删改查都经过 kube-apiserver 转译为 etcd 的 key-value 操作。资源以 /registry/<resource-type>/<namespace>/<name> 的路径存储。例如一个名为 my-pod 的 Pod 存储在 /registry/pods/default/my-pod。理解这一路径结构有助于在极端情况下手动排查 etcd 数据。
Raft 共识与 Leader 选举
- etcd 集群通过 Raft 协议保证数据一致性
- 写操作必须经过 Leader 节点复制到多数节点后才返回成功
- 3 节点容忍 1 台故障,5 节点容忍 2 台故障
- Leader 选举超时默认为 1000ms,心跳间隔为 100ms
前提条件
# 确认 etcdctl 已安装
etcdctl version
# K8s 1.29+ 中 etcd 快照需要设置环境变量
export ETCDCTL_API=3
export ETCDCTL_ENDPOINTS=https://127.0.0.1:2379
export ETCDCTL_CACERT=/etc/kubernetes/pki/etcd/ca.crt
export ETCDCTL_CERT=/etc/kubernetes/pki/etcd/server.crt
export ETCDCTL_KEY=/etc/kubernetes/pki/etcd/server.key
# kubeadm 部署的集群,etcd 运行在 Pod 中
# 通过 kubectl 进入 etcd pod 操作更方便
证书文件说明
| 证书 | 用途 | 默认路径 |
|---|---|---|
| ca.crt | etcd CA 根证书,验证服务端身份 | /etc/kubernetes/pki/etcd/ca.crt |
| server.crt | etcd 服务端证书,客户端验证服务端 | /etc/kubernetes/pki/etcd/server.crt |
| server.key | etcd 服务端私钥 | /etc/kubernetes/pki/etcd/server.key |
| peer.crt | etcd 节点间通信证书(集群内部) | /etc/kubernetes/pki/etcd/peer.crt |
| healthcheck-client.crt | 健康检查客户端证书 | /etc/kubernetes/pki/etcd/healthcheck-client.crt |
1. 手动创建快照
方式一:通过 etcdctl(控制面节点上执行)
sudo etcdctl snapshot save /backup/etcd-snapshot-$(date +%F).db
# 验证快照
sudo etcdctl snapshot status /backup/etcd-snapshot-2026-07-30.db -w table
# 输出示例:
# +----------+----------+------------+------------+
# | HASH | REVISION | TOTAL KEYS | TOTAL SIZE |
# +----------+----------+------------+------------+
# | xxxx | 123456 | 5678 | 120 MB |
# +----------+----------+------------+------------+
# 以 JSON 格式输出(适合脚本解析)
sudo etcdctl snapshot status /backup/etcd-snapshot-2026-07-30.db -w json
方式二:etcd Pod 内执行(kubeadm 集群)
# 进入 etcd pod
kubectl -n kube-system exec -it etcd-master -- sh
# 在 pod 内执行快照
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 \
snapshot save /var/lib/etcd/snapshot.db
# 从 pod 复制到宿主机
kubectl -n kube-system cp etcd-master:/var/lib/etcd/snapshot.db /backup/
# 一行命令完成(不进入 Pod)
kubectl -n kube-system exec etcd-master -- \
ETCDCTL_API=3 etcdctl snapshot save /tmp/snapshot.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
方式三:通过 kube-apiserver 的 /healthz 间接验证
# 确认 etcd 健康(apiserver 能连接到 etcd)
kubectl get --raw /healthz/etcd
# 输出 "ok" 表示正常
# 查看 etcd 的 leader 状态
kubectl -n kube-system exec etcd-master -- \
etcdctl endpoint status --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 -w table
2. 自动化备份(推荐方式)
使用 etcd-backup CronJob 或 Velero:
# etcd-backup CronJob YAML
apiVersion: batch/v1
kind: CronJob
metadata:
name: etcd-backup
namespace: kube-system
spec:
schedule: "0 */6 * * *" # 每 6 小时
jobTemplate:
spec:
template:
spec:
nodeName: master-node # 在控制面节点运行
hostNetwork: true
containers:
- name: etcdctl
image: bitnami/etcd:3.5
env:
- name: ETCDCTL_API
value: "3"
- name: ETCDCTL_ENDPOINTS
value: https://127.0.0.1:2379
- name: ETCDCTL_CACERT
value: /certs/ca.crt
- name: ETCDCTL_CERT
value: /certs/server.crt
- name: ETCDCTL_KEY
value: /certs/server.key
command:
- /bin/sh
- -c
- etcdctl snapshot save /backup/snapshot-$(date +%Y%m%d-%H%M).db
# 保留最近 30 个快照,删除旧的
ls -t /backup/etcd-*.db | tail -n +31 | xargs -r rm
# 验证快照完整性
etcdctl snapshot status /backup/etcd-$(date +%Y%m%d-%H%M).db -w json
volumeMounts:
- name: etcd-certs
mountPath: /certs
readOnly: true
- name: backup
mountPath: /backup
volumes:
- name: etcd-certs
hostPath:
path: /etc/kubernetes/pki/etcd
type: Directory
- name: backup
hostPath:
path: /backup/etcd
type: DirectoryOrCreate
restartPolicy: OnFailure
备份到对象存储(S3/OSS)
本地备份不够安全,推荐将快照同步到云对象存储:
# 在 CronJob 中增加上传步骤
- /bin/sh
- -c
- |
BACKUP_FILE="/backup/etcd-$(date +%Y%m%d-%H%M).db"
etcdctl snapshot save "$BACKUP_FILE"
etcdctl snapshot status "$BACKUP_FILE" -w json
# 上传到 S3
aws s3 cp "$BACKUP_FILE" s3://my-etcd-backups/$(date +%Y/%m/%d)/ \
--sse AES256
# 清理本地 30 天前的备份
find /backup -name "etcd-*.db" -mtime +30 -delete
# 清理 S3 上 90 天前的备份
aws s3 ls s3://my-etcd-backups/ | while read -r line; do
dir_date=$(echo "$line" | awk '{print $2}' | tr -d '/')
if [[ $(date -d "$dir_date" +%s) -lt $(date -d "90 days ago" +%s) ]]; then
aws s3 rm "s3://my-etcd-backups/$dir_date/" --recursive
fi
done
3. 快照恢复
恢复操作是高风险操作,需要严格按顺序执行。恢复前确认已获得最新的快照文件。
恢复前检查
# 确认快照文件可用
etcdctl snapshot status /backup/etcd-latest.db -w table
# 记录当前集群状态(如果 apiserver 仍可用)
kubectl get nodes -o wide
kubectl get pods -A -o wide > /tmp/pre-restore-state.txt
# 确认 etcd 数据目录大小
du -sh /var/lib/etcd/
执行恢复
# 1. 停止 kube-apiserver(先停 apiserver,再停 etcd)
sudo systemctl stop kube-apiserver
# 或移动静态 Pod manifest
sudo mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/
# 2. 停止 etcd
sudo mv /etc/kubernetes/manifests/etcd.yaml /tmp/
# 等待 etcd pod 终止
kubectl -n kube-system wait --for=delete pod/etcd-master --timeout=60s
# 3. 备份当前数据目录(保险起见)
sudo cp -r /var/lib/etcd /var/lib/etcd.bak
# 4. 恢复快照到新数据目录
sudo ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-latest.db \
--data-dir=/var/lib/etcd-restore \
--initial-cluster=master=https://127.0.0.1:2380 \
--initial-advertise-peer-urls=https://127.0.0.1:2380 \
--name=master
# 5. 替换数据目录
sudo mv /var/lib/etcd /var/lib/etcd.old
sudo mv /var/lib/etcd-restore /var/lib/etcd
# 6. 恢复 etcd manifest
sudo mv /tmp/etcd.yaml /etc/kubernetes/manifests/
# 等待 etcd 启动
kubectl -n kube-system wait --for=condition=ready pod/etcd-master --timeout=120s
# 7. 恢复 kube-apiserver
sudo mv /tmp/kube-apiserver.yaml /etc/kubernetes/manifests/
# 8. 验证集群状态
kubectl get nodes
kubectl get pods -A
多节点 etcd 集群恢复
对于 3 节点或 5 节点的高可用 etcd 集群,恢复流程略有不同:
# 在所有 etcd 节点上执行恢复(使用同一个快照)
# 每个节点的 --name 和 --initial-cluster 参数不同
# 节点 1
sudo ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-latest.db \
--data-dir=/var/lib/etcd-restore \
--name=etcd-0 \
--initial-cluster=etcd-0=https://10.0.0.1:2380,etcd-1=https://10.0.0.2:2380,etcd-2=https://10.0.0.3:2380 \
--initial-advertise-peer-urls=https://10.0.0.1:2380
# 节点 2
sudo ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-latest.db \
--data-dir=/var/lib/etcd-restore \
--name=etcd-1 \
--initial-cluster=etcd-0=https://10.0.0.1:2380,etcd-1=https://10.0.0.2:2380,etcd-2=https://10.0.0.3:2380 \
--initial-advertise-peer-urls=https://10.0.0.2:2380
# 节点 3
sudo ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-latest.db \
--data-dir=/var/lib/etcd-restore \
--name=etcd-2 \
--initial-cluster=etcd-0=https://10.0.0.1:2380,etcd-1=https://10.0.0.2:2380,etcd-2=https://10.0.0.3:2380 \
--initial-advertise-peer-urls=https://10.0.0.3:2380
4. 备份策略建议
| 环境 | 备份频率 | 保留策略 | 存储位置 |
|---|---|---|---|
| 生产 | 每 6 小时 | 本地 30 天 + 云 90 天 | 本地 + 云对象存储 |
| 预发 | 每天 | 7 天 | 本地 |
| 开发 | 不强制 | 按需 | 本地 |
5. 快照、压缩与存储配额
快照与 Raft 日志的关系
etcd 的数据由两部分组成:当前状态(内存中的 B+ 树键值)和 Raft 日志(全部写操作的历史)。每次写操作先追加到 Raft 日志,提交后才应用到内存状态机。快照(snapshot)是某个 revision 时刻完整状态的一次持久化拷贝——有了快照之后,之前的 Raft 日志就可以安全丢弃。
| 数据组成部分 | 存放位置 | 作用 |
|---|---|---|
| WAL(Write-Ahead Log) | /var/lib/etcd/member/wal/ | 记录每次写入,崩溃后重放恢复,防止丢数据 |
| snap(快照文件) | /var/lib/etcd/member/snap/ | 定期保存的状态副本,加速重启恢复 |
| db(后端数据库) | /var/lib/etcd/member/db | boltDB 持久化的键值数据(db 是文件不是目录),即快照本体 |
理解这一点是备份策略的前提:etcdctl snapshot save 保存的是 boltDB 数据库文件的在线拷贝,它天然是一致的(内部有事务保证),不需要像 MySQL 那样先锁表再备份。
自动压缩(auto-compaction)
如果不做压缩,Raft 历史会无限增长,最终耗尽存储并触发告警。etcd 3.5 起推荐使用 --auto-compaction-retention 按小时或按 revision 数压缩:
# 方式一:按时间保留(推荐,单位可以是 h/m/s)
--auto-compaction-retention=8h # 保留最近 8 小时的历史版本
# 方式二:按 revision 数量保留
--auto-compaction-retention=100000 # 保留最近 10 万个 revision
# 查看当前压缩状态(Compaction 相关字段)
ETCDCTL_API=3 etcdctl endpoint status --write-out=table
# 手动触发压缩(应急场景)
ETCDCTL_API=3 etcdctl compact 123456
存储配额与只读保护
# 默认配额 2GB,超过后写入被拒(集群进入只读)
--quota-backend-bytes=8589934592 # 调大到 8GB(生产常见配置)
# 观察当前 db 大小
du -sh /var/lib/etcd/member/db/
ETCDCTL_API=3 etcdctl endpoint status -w table | grep DB_SIZE
# 配额已满时的应急处理
# 1. 确认不是异常增长(检查是否有循环写操作)
# 2. 压缩 + defrag 回收空间
ETCDCTL_API=3 etcdctl compact --physical $(etcdctl endpoint status -w json | jq -r '.[0].Status.header.revision')
ETCDCTL_API=3 etcdctl defrag
# 3. 若仍无法回收,需在维护窗口重启 etcd 节点
碎片整理的最佳时机
- defrag 是阻塞操作,会暂时停止节点服务,必须在低峰期执行
- 多节点集群逐个节点执行,一次只整理一台,避免同时阻塞
- defrag 前确认该节点不是当前 Leader,或接受短暂写入延迟
- 整理后立即做一次快照备份——defrag 可能改变 db 文件结构
6. etcd 监控与告警
备份体系的价值建立在"知道什么时候该恢复"之上。etcd 自身的 Prometheus 指标(监听 :2381 指标端口)是判断集群健康的第一手数据:
| 指标名 | 含义 | 告警阈值 |
|---|---|---|
| etcd_server_has_leader | 节点是否能看到 Leader(0/1) | 0 持续 30s(选主失败) |
| etcd_server_leader_changes_seen_total | Leader 切换次数 | 5 分钟内增长(频繁选主) |
| etcd_server_is_leader | 当前节点是否为 Leader | 多节点同时为 1(脑裂征兆) |
| etcd_server_slow_apply_total | apply 耗时超过阈值的次数 | 持续增长(磁盘慢) |
| etcd_mvcc_db_total_size_in_bytes | db 文件实际大小 | 超过配额 80% |
| etcd_network_client_grpc_received_bytes_total | 客户端流量 | 异常突增(扫描或写入风暴) |
# Prometheus 告警规则示例(etcd-alerting.yml)
groups:
- name: etcd.rules
rules:
- alert: EtcdNoLeader
expr: etcd_server_has_leader == 0
for: 30s
labels:
severity: critical
annotations:
summary: "etcd 集群失去 Leader 超过 30 秒"
- alert: EtcdLeaderChanges
expr: increase(etcd_server_leader_changes_seen_total[5m]) > 3
labels:
severity: warning
annotations:
summary: "etcd 集群 5 分钟内发生多次 Leader 切换"
- alert: EtcdDbQuotaHigh
expr: etcd_mvcc_db_total_size_in_bytes / 8589934592 > 0.8
for: 10m
labels:
severity: warning
annotations:
summary: "etcd 数据库使用量超过配额 80%,即将进入只读模式"
- alert: EtcdSnapshotFailure
expr: etcd_server_snapshot_failures_total > 0
labels:
severity: critical
annotations:
summary: "etcd 快照创建失败,备份链路可能中断"
snapshot status 验证并上报成功/失败指标(如写入文件时间戳),再配合 alertmanager 检查"备份文件超过 8 小时未更新"即可形成完整闭环。7. 恢复演练全流程
"能恢复的备份才有价值"不是口号——多数团队第一次真正执行恢复都是在故障现场,结果发现快照损坏、证书不匹配、参数记错。恢复演练就是把这些错误提前暴露在可控环境里。
演练设计要点
- 频率:生产集群每季度至少一次;每次 etcd 或 K8s 大版本升级后追加一次
- 环境:演练必须使用独立的测试集群,禁止在生产环境"假恢复"
- 随机性:从备份池随机选取一个快照(而不是每次都拿最新一份),验证历史快照也可用
- 完整闭环:演练结束要产出报告(RTO 实测值、问题清单、改进项),并纳入下季度计划
演练步骤模板
# 演练场景:单节点集群 etcd 数据目录彻底损坏
# 阶段一:故障注入
sudo systemctl stop kubelet
sudo rm -rf /var/lib/etcd
# 阶段二:恢复(计时开始,作为 RTO 基准)
sudo ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-latest.db \
--data-dir=/var/lib/etcd-restore \
--initial-cluster=master=https://127.0.0.1:2380 \
--initial-advertise-peer-urls=https://127.0.0.1:2380 \
--name=master
sudo mv /var/lib/etcd-restore /var/lib/etcd
sudo systemctl start kubelet
# 阶段三:验证(计时结束)
kubectl get nodes
kubectl get pods -A
# 抽查关键业务:选 3 个 Namespace,核对资源数量与恢复前记录一致
kubectl get deploy,svc,cm,secret -n production | wc -l
# 检查 etcd 健康
kubectl -n kube-system exec etcd-master -- etcdctl endpoint health
演练验收标准
| 指标 | 目标值 | 说明 |
|---|---|---|
| RTO(恢复时间目标) | 单节点 ≤ 15 分钟;HA 集群 ≤ 30 分钟 | 从故障注入到业务可用 |
| RPO(数据丢失容忍) | 等于备份周期(如 6 小时) | 恢复后 revision 落后不超过一个备份周期 |
| 数据完整性 | 抽查资源 100% 一致 | 对比恢复前后资源清单 |
| 演练报告 | 24 小时内产出 | 含问题清单与改进项 |
8. 灾备场景与多区域容灾
典型故障场景与应对
| 场景 | 恢复方式 | 停机影响 |
|---|---|---|
| 单台 etcd 节点宕机(HA 集群) | 无需恢复,其余节点自动补位,替换故障节点 | 无感知 |
| etcd 数据目录损坏(单节点) | 从快照恢复(本文第 3 节) | RTO 内可恢复 |
| 误删除 Namespace/资源(人祸) | 从快照恢复,接受部分数据回退 | 需评估其他组件一致性 |
| 磁盘损坏导致数据全丢 | 新盘 + 快照恢复 | 取决于备份介质可用性 |
| 整个可用区故障 | 依赖跨区域备份 + 异地重建 | 数小时级别 |
多区域容灾方案
单区域灾难(机房断电、云可用区故障)会同时摧毁集群和本地备份,因此生产环境必须满足 3-2-1 原则:3 份副本(1 份集群内 + 2 份独立介质)、2 种存储类型(本地磁盘 + 对象存储)、1 份异地存放(跨区域桶)。
# 跨区域备份的最小实现:本地 CronJob 快照 + 对象存储同步
# 方案 A:AWS S3 跨区域复制(CRR)——主桶开启 CRR 到灾备区域
aws s3api put-bucket-replication --bucket my-etcd-backups \
--replication-configuration file://crr-config.json
# 方案 B:双写两个区域(备份脚本内两次上传)
aws s3 cp "$BACKUP_FILE" s3://my-etcd-backups/ # 主区域
aws s3 cp "$BACKUP_FILE" s3://dr-etcd-backups/ # 灾备区域桶
# 定期验证异地副本(恢复演练时指定从灾备桶拉取)
aws s3 ls s3://dr-etcd-backups/ | sort -r | head -5
aws s3 cp s3://dr-etcd-backups/$(ls -t | head -1) /backup/dr-test.db
ETCDCTL_API=3 etcdctl snapshot status /backup/dr-test.db -w table
kubectl get all -A -o yaml 定期导出资源清单(存入 Git),可以在不重启集群的情况下快速核对恢复结果,两者互为印证。9. 备份产物管理与审计
备份体系运行一段时间后,最常见的失控点是"备份文件散落各处、无人核查"。用清单化管理把备份变成可审计的资产:
| 管理项 | 建议做法 | 验证方式 |
|---|---|---|
| 命名规范 | etcd-<集群名>-<日期>-<revision>.db | ls 即可追溯来源与新旧 |
| 完整性校验 | 每个快照同步生成 SHA256 校验文件 | sha256sum -c 每日比对 |
| 异地留存 | 快照 + 校验文件一起上传对象存储 | 定期从存储下载校验一次 |
| 保留期限 | 本地 30 天、云端 90 天(与 RPO 匹配) | 过期自动清理任务存在且运行 |
| 访问权限 | 备份文件含集群全部密钥(Secret),必须加密 | 对象存储服务端加密(SSE) |
# 备份审计脚本片段:检查"最新快照是否够新"
#!/bin/bash
# 目标:最新快照不超过 8 小时,否则告警
LATEST=$(ls -t /backup/etcd-*.db | head -1)
AGE_MIN=$(( $(date +%s) - $(stat -c %Y "$LATEST") ))
if [ "$AGE_MIN" -gt 480 ]; then
echo "ALERT: 最新 etcd 快照已 $AGE_MIN 分钟未更新"
exit 1
fi
# 校验最近 3 份快照的完整性
for f in $(ls -t /backup/etcd-*.db | head -3); do
ETCDCTL_API=3 etcdctl snapshot status "$f" -w table || echo "ALERT: 快照损坏 $f"
done
常见错误
| 问题 | 原因 | 解决方案 |
|---|---|---|
etcdctl snapshot save 超时 | etcd 负载过高或网络延迟 | 降低快照频率,检查 etcd check perf 输出,确认磁盘 IO 正常 |
| 恢复后 apiserver 无法启动 | 快照版本与当前 etcd 版本不匹配 | 确认 etcd 二进制版本兼容,使用 etcd --version 检查 |
| 恢复后集群数据比预期旧 | 恢复的是旧快照而非最新 | 恢复前务必用 snapshot status 检查 REVISION 字段,选择最大 revision 的快照 |
| 多节点恢复后集群无法选主 | --initial-cluster 参数配置错误 | 确保每个节点的 --name 与 --initial-cluster 中的名称严格一致 |
| etcd 数据目录权限问题 | sudo 恢复后目录属主变为 root | 执行 chown -R etcd:etcd /var/lib/etcd 修正权限 |
最佳实践
- 定期做恢复演练——不能恢复的备份毫无价值
- 快照文件加密后上传到异地对象存储(S3/OSS)
- 监控 etcd 数据库大小(默认 2GB quota,超过后集群只读)
- etcd 慢查询监控:
etcdctl check perf - 限制 etcd 历史版本保留数:
--auto-compaction-retention=8(保留 8 小时历史) - 为备份文件添加 SHA256 校验:
sha256sum /backup/etcd-snapshot.db > /backup/etcd-snapshot.db.sha256 - 在 CronJob 中增加快照完整性验证步骤,确保备份文件可用
- 使用
etcd-defrag工具定期整理碎片空间,但需在低峰期执行
练习题
- 手动备份与验证:在你的测试集群上执行一次手动 etcd 快照,使用
-w json输出格式获取详细信息,并将 REVISION、TOTAL KEYS、TOTAL SIZE 记录到日志文件中。 - 自动化备份 CronJob:编写一个完整的 CronJob YAML,实现每 4 小时自动备份一次 etcd,保留最近 15 个快照,备份完成后自动验证快照完整性,并将结果通过
kubectl create configmap记录到集群中。 - 恢复演练:在测试集群上模拟 etcd 数据丢失场景——先备份,然后手动删除一个 Namespace,再通过恢复快照找回该 Namespace。记录完整的恢复步骤和耗时。
学习检查点
学完本章后,请检验自己是否掌握以下内容:
| 检查项 | 自测问题 | 验证方法 |
|---|---|---|
| 概念理解 | 能用自己的话解释 etcd 的 Raft 一致性协议和数据备份原理 | 尝试向他人讲解 |
| 命令操作 | 能不查文档完成 etcd 快照备份、恢复和状态检查 | 在终端实际执行 |
| 原理掌握 | 能说出 etcd 数据恢复的完整流程和注意事项 | 画出流程图 |
| 故障排查 | 能独立排查 etcd 集群选举失败或数据损坏的问题 | 模拟故障并修复 |
| 最佳实践 | 能说明为什么需要定期进行 etcd 恢复演练 | 对比不同方案 |
本章总结
备份本身没有价值,能恢复的备份才有价值——因此必须定期做恢复演练,并遵循 3-2-1 原则:3 份副本、2 种存储介质、1 份异地存放。生产环境用 CronJob 自动化快照并加入完整性校验(snapshot status/MD5),同时监控 etcd 数据库大小(2GB 配额)与慢查询,防止集群在配额耗尽后进入只读模式。
延伸阅读
- 6.15:HA 集群 Linux 高可用集群——etcd Raft 选举与备份恢复
- 5.2:Docker 生产实践 Docker 生产实践——生产级部署策略
- etcd 官方文档:https://etcd.io/docs/v3.5/op-guide/maintenance/
- Kubernetes 官方文档:https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/