Kubernetes 中 ETCD 数据备份与恢复完整指南
ETCD作为Kubernetes(K8s)集群的“数据库”,存储了集群所有状态信息(如资源配置、工作负载、权限规则等)。一旦ETCD数据丢失或损坏,可能导致集群瘫痪,因此定期备份、可靠恢复是集群运维的核心环节。本文将从备份策略、手动备份/恢复、故障回滚、第三方工具(Velero)等维度,提供可落地的操作方案。
一、ETCD 数据备份:基础准备与手动操作
ETCD备份的核心是通过etcdctl工具生成快照文件(snapshot),需先完成环境配置,再执行备份操作。
1.1 备份前的核心准备
(1)确认 ETCD 版本与下载 etcdctl
etcdctl是ETCD官方命令行工具,需确保其版本与集群ETCD版本一致(避免兼容性问题)。
# 1. 查看集群 ETCD 版本(通过静态 Pod 配置文件)
cat /etc/kubernetes/manifests/etcd.yaml | grep image
# 输出示例:image: registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.6-0(版本为 3.5.6)# 2. 下载对应版本的 etcdctl(从 GitHub 官方仓库)
wget https://github.com/etcd-io/etcd/releases/download/v3.5.6/etcd-v3.5.6-linux-amd64.tar.gz# 3. 解压并安装 etcdctl
tar xf etcd-v3.5.6-linux-amd64.tar.gz
mv etcd-v3.5.6-linux-amd64/etcdctl /usr/local/sbin/# 4. 验证安装(需显示版本匹配)
etcdctl version
# 输出示例:etcdctl version: 3.5.6; API version: 3.5
(2)配置 ETCD API 版本
ETCD v3 是当前主流版本,需通过环境变量 ETCD_API指定使用v3 API(默认可能为v2,导致命令失效):
# 临时生效(当前终端)
export ETCDCTL_API=3# 永久生效(所有终端,写入 bash 配置)
echo "ETCDCTL_API=3" >> ~/.bashrc
source ~/.bashrc # 立即生效# 验证
echo $ETCDCTL_API # 输出:3
(3)获取 ETCD 认证凭证
K8s集群的ETCD启用了SSL认证,备份时需要指定CA证书、服务端证书、服务端私钥(默认路径在/etc/kubernetes/pki/etcd/):
- CA证书:/etc/kubernetes/pki/etcd/ca.crt
- 服务端证书:/etc/kubernetes/pki/etcd/server.crt
- 服务端私钥:/etc/kubernetes/pki/etcd/server.key
1.2 执行 ETCD 数据备份
通过etcdctl snapshot save命令生成快照文件,建议将备份文件存储在非集群节点的安全位置(如远程存储、本地独立磁盘)。
# 1. 创建备份目录(建议按日期命名,便于管理)
mkdir -p /opt/etcd/backup/$(date +%Y%m%d)# 2. 执行备份(核心命令)
ETCDCTL_API=3 etcdctl \--endpoints=https://127.0.0.1:2379 \ # ETCD 监听地址(默认本地 2379)--cacert=/etc/kubernetes/pki/etcd/ca.crt \ # CA 证书路径--cert=/etc/kubernetes/pki/etcd/server.crt \ # 服务端证书路径--key=/etc/kubernetes/pki/etcd/server.key \ # 服务端私钥路径snapshot save /opt/etcd/backup/$(date +%Y%m%d)/etcd_snapshot_$(date +%H%M%S).db# 3. 验证备份文件(查看大小与元信息)
# 查看文件大小(需非空,通常几 MB 到几十 MB,取决于集群规模)
ll -h /opt/etcd/backup/$(date +%Y%m%d)/# 查看快照状态(确认版本、数据量等)
ETCDCTL_API=3 etcdctl --write-out=table snapshot status /opt/etcd/backup/$(date +%Y%m%d)/etcd_snapshot_*.db
快照状态输出示例(关键字段:TotalKey为总键数量,Version为ETCD版本):
filename | revision | version | totalKey | totalSize |
---|---|---|---|---|
etcd_snapshot_1730.db | 123456 | 3.5.6 | 890 | 3.8 MB |
1.3 备份策略建议
为避免单一备份丢失或损坏,需制定规范的备份策略:
- 备份频率:生产环境建议每日全量备份+每小时增量备份(增量需结合ETCD历史版本,需提前开启 --enable-v2=true)。
- 存储位置:至少保留2份副本,分别存储在本地磁盘(集群节点外)和远程存储(如S3、NFS)。
- 保留周期:按业务需求设置(如保留最近7天的每日备份,最近30天的每周备份)。
- 校验机制:备份后定期通过 snapshot status 校验文件完整性,避免备份失效。
二、ETCD 数据恢复:手动恢复与故障验证
ETCD恢复需停止集群核心组件(避免数据写入冲突),再通过快照文件重建ETCD数据目录,最后重启集群。
2.1 恢复前的准备:标记验证资源
为确认恢复成功,建议先创建一个 “临时测试资源”,恢复后若该资源消失,说明恢复到备份前状态。
# 1. 创建测试 Pod(备份后新增的资源)
kubectl run test-nginx --image=nginx:alpine --image-pull-policy=IfNotPresent# 2. 确认资源存在
kubectl get pods | grep test-nginx
# 输出示例:test-nginx 1/1 Running 0 30s
2.2 核心步骤:停止集群组件 + 恢复数据
K8s核心组件(APIServer、Controller Manager、Scheduler、ETCD)通过静态Pod启动(配置文件在/etc/kubernetes/mainfests/),停止这些组件只需移动配置文件即可。
(1)停止集群核心组件
# 1. 创建临时目录,存放静态 Pod 配置文件(移动后组件会自动停止)
mkdir -p /opt/k8s-manifests-backup# 2. 移动配置文件(停止 APIServer、Controller Manager、Scheduler、ETCD)
mv /etc/kubernetes/manifests/* /opt/k8s-manifests-backup/# 3. 确认组件已停止(APIServer 停止后,kubectl 会无法连接)
kubectl get pods -n kube-system
# 输出示例:The connection to the server 192.168.100.10:6443 was refused...
(2)备份当前 ETCD 数据目录(故障回滚用)
为防止恢复失败,需先备份当前 ETCD 数据目录(默认路径 /var/lib/etcd
):
# 重命名现有数据目录(保留原始数据,便于回滚)
mv /var/lib/etcd /var/lib/etcd_old_backup
(3)执行 ETCD 恢复
通过etcdctl snapshot restore 命令,从快照文件重建ETCD数据目录,需指定集群初始化参数(与备份的ETCD配置一致)。
# 核心恢复命令(参数需根据集群实际配置调整)
ETCDCTL_API=3 etcdctl snapshot restore \/opt/etcd/backup/20240928/etcd_snapshot_1730.db \ # 快照文件路径--name=etcd-master-01 \ # ETCD 节点名称(需与集群配置一致,查看 etcd.yaml 中的 --name 参数)--data-dir=/var/lib/etcd \ # 新的 ETCD 数据目录(恢复后的数据将存于此)--initial-cluster=etcd-master-01=https://192.168.100.10:2380 \ # ETCD 集群节点列表(单节点集群仅需自身)--initial-cluster-token=etcd-cluster-token \ # 集群令牌(需与 etcd.yaml 中的 --initial-cluster-token 一致)--initial-advertise-peer-urls=https://192.168.100.10:2380 # 节点对等通信地址(需与 etcd.yaml 中的 --initial-advertise-peer-urls 一致)
参数说明(需从 etcd.yaml
中获取准确值):
- --name:ETCD节点名称,查看etcd.yaml中的--name字段。
- --initial-cluster:集群节点列表,格式为“节点名=通信地址”(单节点仅填自身)。
- --initial-cluster-token:集群唯一令牌,查看etcd.yaml中的--initial-cluster-token。
- --initial-advertise-peer-urls:节点对等通信地址(用于集群内节点通信,默认2380端口)。
(4)重启集群核心组件
恢复数据目录后,将静态Pod配置文件移回原目录,组件会自动重启:
# 移动配置文件(重启 APIServer、ETCD 等组件)
mv /opt/k8s-manifests-backup/* /etc/kubernetes/manifests/# 等待 1-2 分钟,确认组件启动(需确保 ETCD 正常运行)
kubectl get pods -n kube-system | grep etcd
# 输出示例:etcd-master-01 1/1 Running 0 1m
2.3 验证恢复结果
恢复成功的核心标志是“备份后新增的资源消失”,且原有资源政策正常:
# 1. 检查测试资源(test-nginx 应消失,说明恢复到备份前状态)
kubectl get pods | grep test-nginx
# 输出:无结果(资源已消失)# 2. 检查原有资源(如备份前存在的 tomcat Pod,应正常运行)
kubectl get pods | grep tomcat
# 输出示例:tomcat-test 1/1 Running 0 8h
2.4 恢复失败的回滚方案
若恢复后集群异常(如ETCD无法启动),可通过“还原原始数据目录”回滚:
# 1. 再次停止集群组件
mv /etc/kubernetes/manifests/* /opt/k8s-manifests-backup/# 2. 删除恢复的数据目录,还原原始目录
rm -rf /var/lib/etcd
mv /var/lib/etcd_old_backup /var/lib/etcd# 3. 重启组件
mv /opt/k8s-manifests-backup/* /etc/kubernetes/manifests/
三、ETCD 备份的两种核心方式对比
除了上述“快照备份”,还可通过“目录备份”直接复制ETCD数据目录,两种方式各有使用场景:
备份方式 | 备份源 | 备份目标 | 优点 | 缺点 | 适用场景 |
---|---|---|---|---|---|
快照备份 | ETCD 数据库内容(通过 etcdctl ) | 单一快照文件(如 etcd_snapshot.db ) | 体积小、跨版本兼容(部分版本)、支持增量 | 需安装 etcdctl 、依赖 ETCD 服务正常 | 日常定期备份、跨节点恢复 |
目录备份 | ETCD 数据目录(/var/lib/etcd ) | 复制目录(如 /var/lib/etcd_bak ) | 操作简单、无需依赖 etcdctl | 体积大(与数据目录一致)、跨版本兼容性差 | 紧急故障备份(ETCD 无法启动时) |
四、扩展:集群级备份(不止 ETCD)
仅备份 ETCD 不足以覆盖所有风险(如应用数据、自定义配置),需补充以下备份:
4.1 应用数据备份(持久卷 PV)
应用数据通常存储在PV中(如数据库数据、业务日志),需结合PV类型选择备份方式:
- 宿主目录/本地磁盘PV:通过rsync或tar备份PV挂载目录(如/data/pv/mysql)。
- 云存储PV(如AWS EBS、阿里云云盘):使用云厂商提供的“快照功能”(如aws ec2 create-snapshot)。
- 分布式存储PV(如Ceph):使用存储自身的备份工具(如Ceph RBD快照)。
4.2 K8s 配置与资源定义备份
- 静态配置文件:备份/etc/kubernetes/目录(包含证书、静态Pod配置):
tar zcvf /opt/backup/k8s_config_$(date +%Y%m%d).tar.gz /etc/kubernetes/
- 资源定义YAML:导出所有集群资源的YAML配置(便于快速重建):
kubectl get all --all-namespaces -o yaml > /opt/backup/k8s_all_resources_$(date +%Y%m%d).yaml
五、第三方工具:使用 Velero 实现自动化备份
手动备份 / 恢复效率低且易出错,生产环境推荐使用 Velero(开源工具,支持集群资源、ETCD 数据、PV 备份的自动化)。
5.1 Velero 核心优势
- 支持 定时备份(如每日凌晨 1 点自动备份)。
- 支持 选择性备份(如仅备份特定命名空间、特定资源)。
- 集成对象存储(如 MinIO、S3),备份文件存储更可靠。
- 简化恢复流程(无需手动停止集群组件)。
5.2 部署 Velero 与 MinIO(本地对象存储)
Velero 需要对象存储存储备份文件,此处使用 MinIO(轻量级开源对象存储)作为本地存储。
(1)安装 MinIO(对象存储服务)
# 1. 下载 MinIO 二进制文件
wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
mv minio /usr/local/bin/# 2. 创建数据目录
mkdir -p /mnt/minio-data# 3. 启动 MinIO(后台运行,设置访问密钥)
nohup MINIO_ROOT_USER=velero-admin MINIO_ROOT_PASSWORD=velero-pass123 \minio server /mnt/minio-data --console-address ":9001" > /var/log/minio.log 2>&1 &# 4. 验证 MinIO 启动(访问控制台:http://集群IP:9001,登录账号密码为上述设置)
curl http://127.0.0.1:9000/minio/health/live
# 输出:OK
(2)安装 Velero
# 1. 下载 Velero CLI(版本 1.12.0,兼容主流 K8s 版本)
wget https://github.com/vmware-tanzu/velero/releases/download/v1.12.0/velero-v1.12.0-linux-amd64.tar.gz
tar xf velero-v1.12.0-linux-amd64.tar.gz
mv velero-v1.12.0-linux-amd64/velero /usr/local/bin/# 2. 验证 CLI 安装
velero version
# 输出:Client Version: v1.12.0(仅客户端,服务端未安装)# 3. 创建 MinIO 访问凭证文件(Velero 需此文件访问 MinIO)
cat > credentials-velero << EOF
[default]
aws_access_key_id=velero-admin
aws_secret_access_key=velero-pass123
EOF# 4. 安装 Velero 服务端(关联 MinIO)
velero install \--provider aws \ # 兼容 MinIO(S3 协议)--plugins velero/velero-plugin-for-aws:v1.9.0 \ # S3 插件--bucket velero-backups \ # MinIO 中存储备份的桶名(会自动创建)--secret-file ./credentials
5.3 创建 Velero 备份(手动触发)
Velero 支持灵活的备份策略,可根据需求选择 “全集群备份”“指定命名空间备份” 或 “指定资源类型备份”,核心命令为 velero backup create
。
(1)全集群备份(备份所有命名空间与资源)
适用于集群级灾备,备份所有命名空间(包括 kube-system
系统命名空间)的资源和关联的持久卷(PV):
# 创建全集群备份,命名格式:backup-日期-时间(便于追溯)
velero backup create backup-full-$(date +%Y%m%d%H%M) \--include-namespaces=* \ # 包含所有命名空间(* 表示全部)--snapshot-volumes=true \ # 备份持久卷(PV)的快照(需存储支持快照功能)--wait # 等待备份完成后再退出(便于查看结果)
(2)指定命名空间备份(如仅备份业务命名空间)
生产环境中,常需单独备份业务命名空间(如 prod
、test
),避免系统命名空间占用过多备份空间:
# 备份 prod 和 test 两个命名空间
velero backup create backup-prod-test-$(date +%Y%m%d) \--include-namespaces=prod,test \ # 逗号分隔多个命名空间--snapshot-volumes=true \--wait
(3)指定资源类型备份(如仅备份 Deployment 和 PVC)
若仅需备份特定资源(如避免备份临时 Pod),可通过 --include-resources
指定资源类型:
# 仅备份 prod 命名空间的 Deployment、StatefulSet 和 PVC
velero backup create backup-prod-resources-$(date +%Y%m%d) \--include-namespaces=prod \--include-resources=deployments.apps,statefulsets.apps,persistentvolumeclaims \ # 资源类型(格式:资源名.API组,核心资源无需API组)--snapshot-volumes=true \--wait
(4)排除特定资源备份
若需排除临时资源(如 Job、Pod),可通过 --exclude-resources
过滤:
# 备份 prod 命名空间,但排除 Job 和 Pod
velero backup create backup-prod-exclude-$(date +%Y%m%d) \--include-namespaces=prod \--exclude-resources=jobs.batch,pods \--snapshot-volumes=true \--wait
5.4 查看与校验备份状态
备份创建后,需确认备份是否成功,避免 “无效备份”(如存储连接失败、权限不足导致备份中断)。
(1)查看所有备份列表
velero backup get
输出示例(关键列说明):
NAME | STATUS | ERRORS | WARNINGS | CREATED | EXPIRES | STORAGE LOCATION | SELECTOR |
---|---|---|---|---|---|---|---|
backup-full-202409281030 | Completed | 0 | 0 | 2024-09-28 10:30:00 +0800 CST | 29d | default | <none> |
backup-prod-202409281100 | Completed | 0 | 0 | 2024-09-28 11:00:00 +0800 CST | 29d | default | <none> |
- STATUS:
Completed
表示成功,InProgress
表示正在执行,Failed
表示失败。 - EXPIRES:备份过期时间(默认 30 天,可通过
--ttl
指定,如--ttl=720h
表示 30 天)。
(2)查看单个备份详情(排查失败原因)
若备份状态为 Failed
或有 ERRORS
,需查看详情定位问题:
# 替换为实际备份名
velero backup describe backup-prod-202409281100 --details
关键信息:
- Phase:备份阶段(如
Completed
)。 - Errors/Warnings:错误或警告信息(如 “PV 快照失败,因存储不支持快照”)。
- Included Resources:已包含的资源类型。
- Volume Snapshots:持久卷快照状态(每个 PV 的快照是否成功)。
(3)校验备份文件完整性
Velero 支持通过 velero backup download
下载备份文件到本地,验证文件是否可正常读取:
# 下载备份文件(会生成一个压缩包)
velero backup download backup-prod-202409281100# 解压并查看内容(包含资源 YAML 和 PV 快照元数据)
unzip backup-prod-202409281100.zip
ls -l backup-prod-202409281100/
5.5 执行 Velero 恢复操作
当集群出现故障(如资源误删、ETCD 数据损坏)时,可通过 Velero 从备份中恢复数据,核心命令为 velero restore create
。
(1)全量恢复(从全集群备份恢复所有资源)
适用于集群整体故障,恢复所有命名空间和资源:
# 从全集群备份恢复,恢复任务命名格式:restore-备份名-时间
velero restore create restore-full-$(date +%Y%m%d%H%M) \--from-backup=backup-full-202409281030 \ # 指定备份源--wait # 等待恢复完成
(2)选择性恢复(仅恢复特定命名空间 / 资源)
若仅需恢复部分资源(如误删 prod
命名空间的 Deployment),可通过参数过滤:
# 从全集群备份中,仅恢复 prod 命名空间的 Deployment
velero restore create restore-prod-deploy-$(date +%Y%m%d) \--from-backup=backup-full-202409281030 \--include-namespaces=prod \ # 仅恢复 prod 命名空间--include-resources=deployments.apps \ # 仅恢复 Deployment--wait
(3)恢复时排除特定资源
若需恢复大部分资源,但排除临时资源(如旧的 Job),可使用 --exclude-resources
:
# 恢复 prod 命名空间,但排除 Job 和 Pod(避免恢复旧的临时任务)
velero restore create restore-prod-exclude-$(date +%Y%m%d) \--from-backup=backup-prod-202409281100 \--exclude-resources=jobs.batch,pods \--wait
5.6 查看恢复状态与验证结果
恢复执行后,需确认恢复是否成功,并验证资源是否正常运行。
(1)查看恢复任务列表
velero restore get
输出示例:
NAME | BACKUP | STATUS | ERRORS | WARNINGS | CREATED | COMPLETED |
---|---|---|---|---|---|---|
restore-prod-deploy-20240928 | backup-full-202409281030 | Completed | 0 | 0 | 2024-09-28 14:30:00 +0800 CST | 2024-09-28 14:30:30 +0800 CST |
(2)查看恢复详情(排查失败原因)
若恢复状态为 Failed
,需查看详情定位问题(如 “资源已存在导致恢复冲突”):
velero restore describe restore-prod-deploy-20240928 --details
(3)验证恢复结果
通过 kubectl
确认资源是否恢复正常:
# 1. 查看 prod 命名空间的 Deployment(确认恢复的资源存在)
kubectl get deployments -n prod# 2. 查看 PV/PVC(确认持久卷数据是否恢复)
kubectl get pvc -n prod
kubectl get pv# 3. 查看 Pod 状态(确认应用正常运行)
kubectl get pods -n prod
5.7 配置 Velero 定时备份(自动化运维)
手动备份难以保证及时性,Velero 支持通过 velero schedule create
创建定时任务,实现 “按周期自动备份”(如每日凌晨 1 点备份)。
(1)创建每日全集群定时备份
# 定时任务命名:schedule-full-daily(每日全量备份)
# 调度规则:0 1 * * *(Cron 表达式,每日凌晨 1 点执行)
# 备份保留时间:7 天(--ttl=168h)
velero schedule create schedule-full-daily \--schedule="0 1 * * *" \--include-namespaces=* \--snapshot-volumes=true \--ttl=168h \ # 备份保留 7 天,自动清理过期备份--wait
(2)创建每小时业务命名空间增量备份
对于核心业务命名空间(如 prod
),可设置更频繁的增量备份(依赖存储支持增量快照):
# 定时任务命名:schedule-prod-hourly(每小时增量备份)
# 调度规则:0 * * * *(每小时整点执行)
# 备份保留时间:24 小时(--ttl=24h)
velero schedule create schedule-prod-hourly \--schedule="0 * * * *" \--include-namespaces=prod \--snapshot-volumes=true \--ttl=24h \--wait
(3)查看定时任务与历史备份
# 1. 查看所有定时任务
velero schedule get# 2. 查看某个定时任务的执行历史(如每日全量备份的历史结果)
velero schedule history schedule-full-daily# 3. 查看定时任务生成的备份列表
velero backup get --selector=velero.io/schedule-name=schedule-full-daily
六、ETCD 与 Velero 备份方案对比与选型建议
在实际运维中,需根据集群规模、业务需求选择合适的备份方案,以下是两种核心方案的对比:
对比维度 | ETCD 手动备份(快照 / 目录) | Velero 自动化备份 |
---|---|---|
备份范围 | 仅 ETCD 数据(集群状态、资源配置) | 集群资源(Deployment/Pod 等)+ PV 数据 + ETCD 数据(间接) |
自动化能力 | 需手动编写脚本实现定时备份 | 内置定时任务,支持自动清理过期备份 |
恢复灵活性 | 仅支持全集群恢复(无法选择性恢复单个资源) | 支持选择性恢复(命名空间、资源类型、单个资源) |
PV 备份支持 | 不支持(需单独备份 PV 目录) | 支持 PV 快照(需存储支持),自动关联资源恢复 |
运维复杂度 | 高(需手动管理备份文件、恢复时需停止集群) | 低(图形化控制台 + 命令行,无需停止集群) |
适用场景 | 小型集群、应急备份(ETCD 故障时) | 中大型集群、生产环境、日常自动化运维 |
选型建议:
- 小型测试集群:可使用 ETCD 手动备份(快照),降低运维成本。
- 生产环境集群:优先选择 Velero,结合 “每日全量备份 + 核心业务每小时增量备份”,确保数据可快速恢复,同时减少故障影响范围。
- 核心业务场景:在 Velero 基础上,额外定期执行 ETCD 快照备份(作为 “最后一道防线”),避免 Velero 自身故障导致备份失效。
七、总结
Kubernetes 集群的数据安全依赖 “定期备份 + 可靠恢复”,核心结论如下:
- ETCD 是核心:ETCD 存储集群所有状态,需通过
etcdctl
定期生成快照,确保集群可回滚到历史状态。 - Velero 提升效率:Velero 实现了备份 / 恢复的自动化、灵活化,支持选择性恢复和 PV 数据备份,是生产环境的首选工具。
- 策略需适配业务:根据业务重要性制定备份频率(核心业务每小时增量,普通业务每日全量),备份文件需多副本存储(本地 + 远程)
点赞+收藏+关注,下期我们接着唠嗑