> 技术文档 > etcd自动备份以及恢复

etcd自动备份以及恢复

目录

一、命令行备份

1. etcd备份

2. 数据恢复

3. 总结与流程梳理

错误一:Error: snapshot restore requires exactly one argument

错误二:-bash: etcdutl: 未找到命令

二、K8S自动备份

1. 构建备份工具镜像

1.1. 镜像文件准备

1.2. 编写备份环境初始化脚本

1.3. 编写Dockerfile

1.4. 构建镜像

1.5. 上传镜像

2. 编写ConfigMap

3. 编写CronJob

4. 开启备份任务

5. 查看cronjob状态

6. 检查备份


环境说明:

k8s三主三从高可用集群

主机名 IP地址 说明 master1 192.168.48.11 master节点 master2 192.168.48.12 master节点 master3 192.168.48.13 master节点 node01 192.168.48.14 node节点 node02 192.168.48.15 node节点 node02 192.168.48.16 node节点 database 192.168.48.19 harbor仓库 192.168.48.10 VIP(虚拟IP)

安装配置信息如下表所示:

配置信息 备注 OS系统版本 openEuler-24.03 Docker版本 28.3.2 etcdctl版本 3.5.20 Kubernetes版本 1.32.7

一、命令行备份

1. etcd备份

确保所有master节点etcdctl命令可用。

master1执行:

scp -r /usr/local/bin/etcdctl root@192.168.48.102:/usr/local/bin/scp -r /usr/local/bin/etcdctl root@192.168.48.103:/usr/local/bin/

所有节点执行:

cd ~sudo mkdir -p /etcd/backup/sudo mkdir -p /etc/kubernetes/manifests.bak#etcd备份的关键命令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 /etcd/backup/etcdbackup.db​ETCDCTL_API=3 etcdctl --write-out=table snapshot status /etcd/backup/etcdbackup.db

2. 数据恢复

停止etcd服务和K8s集群的相关组件 在恢复之前,需要停止etcd服务和K8s集群的相关组件(如apiserver、controller-manager、scheduler等)。由于etcd是通过静态Pod方式部署的,你可以通过重命名/etc/kubernetes/manifests/目录来停止所有由该目录下的YAML文件启动的服务。

mv /etc/kubernetes/manifests/* /etc/kubernetes/manifests.bak

物理备份etcd:

这是为了避免我们的备份出错导致集群不可逆损伤。

mv /var/lib/etcd /var/lib/etcd.bck

etcd数据恢复关键命令:

ETCDCTL_API=3 etcdctl snapshot restore /etcd/backup/etcdbackup.db --name master1 --data-dir /var/lib/etcd --initial-cluster \"master1=https://192.168.48.11:2380,master2=https://192.168.48.12:2380,master3=https://192.168.48.13:2380\" --initial-cluster-token etcd-cluster-token --initial-advertise-peer-urls \"https://192.168.48.11:2380\"

我们来详细分解并解释这条完整的 etcd 恢复命令中每一个参数的意义和作用。

这条命令的核心目的是:使用一个备份的快照文件,在当前服务器上创建一个全新的 etcd 数据目录,并为加入一个的 etcd 集群做好初始化配置。


2.1. 参数详解

  1. ETCDCTL_API=3

  • 类型:环境变量

  • 含义:指定使用 etcdctl 工具的 v3 API

  • 为什么需要:etcdctl 为了兼容旧版本,需要明确指定使用哪个版本的 API。快照(snapshot)功能是 v3 API 引入的,所以必须设置为 3。

  1. etcdctl snapshot restore

  • 类型:主命令

  • 含义:这是 etcdctl 工具的子命令,用于从快照文件执行恢复操作。

  1. /etcd/backup/etcdbackup.db

  • 类型:位置参数

  • 含义:源快照文件的路径。这是你之前通过 etcdctl snapshot save 命令创建的备份文件的位置。

  • 说明:执行恢复操作前,必须确保这个文件存在于该路径下。

  1. --name master1

  • 类型:关键配置参数

  • 含义:指定当前节点在即将创建的新集群中的成员名称

  • 说明:这个名称必须与后面 --initial-cluster 参数列表中对应本节点 IP 的那个成员的名称一致。这里告诉系统:“我这台机器,在新集群里的名字叫 master1。”

  1. --data-dir /var/lib/etcd

  • 类型:关键配置参数

  • 含义:指定恢复操作生成的全新数据目录的路径。

  • 说明:恢复过程会创建一个全新的 etcd 数据目录。重要提示:你不能覆盖当前正在运行的 etcd 实例的数据目录。通常,你会先停止 etcd 服务,删除或移走旧的 /var/lib/etcd 目录,然后执行此命令来生成一个全新的、包含备份数据的数据目录。

  1. --initial-cluster \"master1=https://192.168.48.11:2380,master2=https://192.168.48.12:2380,master3=https://192.168.48.13:2380\"

  • 类型最关键的集群配置参数

  • 含义:定义新集群的初始成员列表。

  • 格式=, =, ...

  • 详细解释

    • master1=https://192.168.48.11:2380:名为 master1 的节点,其对等通信地址(Peer URL)https://192.168.48.11:2380

    • master2=...master3=...:定义了集群的另外两个节点。

    • 端口 2380:这是 etcd 节点间内部通信的专用端口(用于领导选举、数据同步、心跳等)。

  • 为什么需要:这个参数告诉正在恢复的节点:“你将要加入的这个新集群,总共有这三个成员,这是他们的名字和联系方式。”

  1. --initial-cluster-token etcd-cluster-token

  • 类型:安全配置参数

  • 含义:为新集群设置一个唯一的集群令牌。

  • 为什么需要:这个令牌用于防止新集群在初始启动时与网络中其他无关的 etcd 集群意外连接并形成同一个集群。执行恢复时,必须提供一个新的 token,因为这相当于创建一个全新的集群,而不是加入旧的。

  1. --initial-advertise-peer-urls \"https://192.168.48.11:2380\"

  • 类型:关键网络配置参数

  • 含义:指定本节点新集群中对外宣告的对等通信地址(Peer URL)

  • 详细解释

    • 对等通信地址用于 etcd 集群成员节点之间的通信(如心跳、数据同步、领导者选举)。

    • 这个地址必须能被集群中其他所有节点访问到。

    • 关键一致性:这个地址必须出现在上面的 --initial-cluster 参数列表中,与 --name 参数指定的名称相对应。在这个命令中,--namemaster1,所以在 --initial-cluster 列表中找 master1,它的 URL 也必须是 https://192.168.48.11:2380两者必须完全匹配,否则集群无法形成

这条命令在 master1 节点上执行后,会:

  1. 读取快照文件 /etcd/backup/etcdbackup.db 中的数据。

  2. /var/lib/etcd 目录下创建一个全新的数据结构。

  3. 将快照中的数据恢复到新目录中。

  4. 丢弃旧集群的所有成员信息和网络配置

  5. 根据你提供的参数,生成新集群的初始化配置:

    • 集群名叫 etcd-cluster-token

    • 集群有三个节点:master1, master2, master3。

    • 本节点(master1)告诉其他节点:“想和我进行内部管理通信,请用 https://192.168.48.11:2380 这个地址找我。”

执行流程:

  1. master1 (IP: 192.168.48.11) 上执行上面的命令。

  2. master2 (IP: 192.168.48.12) 上执行类似的命令,只需修改 --name--initial-advertise-peer-urls

    ETCDCTL_API=3 etcdctl snapshot restore /etcd/backup/etcdbackup.db --name master2 --data-dir /var/lib/etcd --initial-cluster \"master1=https://192.168.48.11:2380,master2=https://192.168.48.12:2380,master3=https://192.168.48.13:2380\" --initial-cluster-token etcd-cluster-token --initial-advertise-peer-urls \"https://192.168.48.12:2380\"
  3. master3 (IP: 192.168.48.103) 上执行:

    ETCDCTL_API=3 etcdctl snapshot restore /etcd/backup/etcdbackup.db --name master3 --data-dir /var/lib/etcd --initial-cluster \"master1=https://192.168.48.11:2380,master2=https://192.168.48.12:2380,master3=https://192.168.48.13:2380\" --initial-cluster-token etcd-cluster-token --initial-advertise-peer-urls \"https://192.168.48.13:2380\"

所有节点执行:

mv /etc/kubernetes/manifests.bak/* /etc/kubernetes/manifests/systemctl restart kubelet.service

到此,集群etcd恢复正常。

3. 总结与流程梳理

报错解决:

错误一:Error: snapshot restore requires exactly one argument

原因:这个错误是因为你的命令格式不正确。你在 --name 参数后面直接换行了,导致 etcdctl 认为 master1 是一个独立的参数,而不是 --name 的值。

错误写法(换行破坏了参数结构):

... --name master1 --data-dir ...

这被解析为:--name (没有值) + 参数 master1 + --data-dir ...

正确写法(确保参数和它的值在同一行,或者用 \\ 转义换行符):

... --name master1 --data-dir ...

或者

... --name \\master1 --data-dir ...

错误二:-bash: etcdutl: 未找到命令

原因:你的系统上安装的 etcd 版本可能比较旧(可能是 3.4 之前),还没有提供 etcdutl 这个命令。etcdutletcdctl 的分拆是较新版本才引入的。


解决方案

使用旧的、但肯定可用的 etcdctl 命令,并确保正确的格式。

请在你的 master1 节点上执行以下完整的一行命令(不要换行):

ETCDCTL_API=3 etcdctl snapshot restore /etcd/backup/etcdbackup.db --name master1 --data-dir /var/lib/etcd --initial-cluster \"master1=https://192.168.48.11:2380,master2=https://192.168.48.12:2380,master3=https://192.168.48.13:2380\" --initial-cluster-token etcd-cluster-token --initial-advertise-peer-urls \"https://192.168.48.11:2380\"

我做的改进:

  1. 移除了错误的换行:确保 --name master1 是一个完整的单元。

  2. 给URL列表加上了引号:使用引号 \"...\" 将包含逗号的 --initial-cluster 参数值括起来,这是一个好习惯,可以避免 shell 解析错误。

执行流程:

  1. master1 (IP: 192.168.48.11) 上执行上面的命令。

  2. master2 (IP: 192.168.48.12) 上执行类似的命令,只需修改 --name--initial-advertise-peer-urls

    ETCDCTL_API=3 etcdctl snapshot restore /etcd/backup/etcdbackup.db --name master2 --data-dir /var/lib/etcd --initial-cluster \"master1=https://192.168.48.11:2380,master2=https://192.168.48.12:2380,master3=https://192.168.48.13:2380\" --initial-cluster-token etcd-cluster-token --initial-advertise-peer-urls \"https://192.168.48.12:2380\"
  3. master3 (IP: 192.168.48.13) 上执行:

    ETCDCTL_API=3 etcdctl snapshot restore /etcd/backup/etcdbackup.db --name master3 --data-dir /var/lib/etcd --initial-cluster \"master1=https://192.168.48.11:2380,master2=https://192.168.48.12:2380,master3=https://192.168.48.13:2380\" --initial-cluster-token etcd-cluster-token --initial-advertise-peer-urls \"https://192.168.48.13:2380\"

总结:忽略 etcdutl,坚持使用 etcdctl,并确保命令的格式正确(参数和值不被人为换行断开)。

二、K8S自动备份

不管是使用命令备份还是脚本备份,亦或是加入cronjob,我们都不能保证备份的时间节点下k8s集群正常。换句话说,我们有可能备份了故障的k8s集群,那如何解决这个问题呢?

答案是将备份任务交给K8S集群本身来做,这样,K8S只有在健康状态下才会执行备份任务。

1. 构建备份工具镜像

1.1. 镜像文件准备

cd ~mkdir etcd-backup && cd etcd-backup#可能是其他路径,下面以我的为例。cp -p /usr/local/bin/etcdctl .cp -p /usr/bin/kubectl .

1.2. 编写备份环境初始化脚本

所有master节点都要做。

cat > init-etcd-backup.sh << \'EOF\'#!/usr/bin/env bashset -euo pipefail​# Create required hostPath directoriesREQUIRED_DIRS=( \"/data/etcd/backups\" #备份存储的目录)​echo \"[1/2] Ensuring required directories exist...\"for d in \"${REQUIRED_DIRS[@]}\"; do if [ ! -d \"$d\" ]; then   echo \"Creating: $d\"   mkdir -p \"$d\" else   echo \"Exists:   $d\" fi chown root:root \"$d\" chmod 755 \"$d\"done​echo \"[2/2] Labeling control-plane nodes for etcd backup...\"# Replace these names if your masters are named differentlykubectl label node master1 etcd-backup=master1 --overwritekubectl label node master2 etcd-backup=master2 --overwritekubectl label node master3 etcd-backup=master3 --overwrite​echo -e \"\\e[32mInitialization complete.\\e[0m\"EOF

执行这个脚本

所有master节点都要做。

chmod +x init-etcd-backup.shsh init-etcd-backup.sh

1.3. 编写Dockerfile

FROM ubuntu:22.04​# 安装常用工具(不安装 etcd-client,避免与自带 etcdctl 冲突)RUN apt-get update && \\   apt-get install -y curl wget vim unzip tar net-tools && \\   rm -rf /var/lib/apt/lists/*​# 如需要 kubectl,请保留;若不需要可删除以下两行以减小镜像COPY kubectl /binRUN chmod +x /bin/kubectl​# 固定使用随项目提供的 etcdctl 二进制COPY etcdctl /binRUN chmod +x /bin/etcdctl​

1.4. 构建镜像

docker build -t etcd-backup:latest .

1.5. 上传镜像

打标签,推送到harbor仓库。

docker tag docker.io/library/etcd-backup:latest 192.168.48.19/etcd-backup/etcd-backup:latestdocker push 192.168.48.19/etcd-backup/etcd-backup:latest

2. 编写ConfigMap

vim etcd-backup-config.yaml
apiVersion: v1kind: ConfigMapmetadata: name: etcd-backup-config namespace: kube-systemdata: backup_etcd.sh: |   #!/bin/bash   set -euo pipefail​   # 通过本机网络访问 etcd(CronJob 使用 hostNetwork)   ENDPOINT=\"https://127.0.0.1:2379\"​   # 证书路径(kubeadm 默认路径)   ETCD_CA=\"/etc/kubernetes/pki/etcd/ca.crt\"   ETCD_CERT=\"/etc/kubernetes/pki/apiserver-etcd-client.crt\"   ETCD_KEY=\"/etc/kubernetes/pki/apiserver-etcd-client.key\"​   # 日期   current_date=$(date +\"%Y_%m_%d_%H_%M_%S\")​   # 备份目录   mkdir -p /etcd/backup/   chmod 755 /etcd/backup/​   SNAPSHOT=\"/etcd/backup/etcd-127.0.0.1-${current_date}.db\"   echo \"开始备份到: ${SNAPSHOT}\"​   etcdctl --endpoints=\"${ENDPOINT}\" \\     --cacert=\"${ETCD_CA}\" \\     --cert=\"${ETCD_CERT}\" \\     --key=\"${ETCD_KEY}\" \\     snapshot save \"${SNAPSHOT}\"​   echo \"备份完成: ${SNAPSHOT}\"​   # 清理超过3天的 .db 文件   find /etcd/backup/ -type f -name \'*.db\' -mtime +3 -delete​   echo \"清理完成,仅保留最近三天的快照\"

3. 编写CronJob

由于我的是高可用k8s集群,我把master节点的内置etcd全备份了。理论上只要备份一个master节点的etcd就行,但是为了保险起见,我把所有maser节点的etcd都做了备份,所以我写了3个cronjob。内容都是差不多的,关键在于备份的时间要错开,避免并发。

master1备份的cronjob

vim etcd-backup-cronjob-master1.yaml
apiVersion: batch/v1kind: CronJobmetadata: name: etcd-backup-master1 namespace: kube-systemspec: schedule: \"0 23 * * *\"         # 每日23:00(UTC) concurrencyPolicy: Forbid       # 避免并发 successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 1 jobTemplate:   spec:     template:       spec:         hostNetwork: true         dnsPolicy: ClusterFirstWithHostNet         nodeSelector:           etcd-backup: \"master1\" # 绑定第1个master         tolerations:           - key: \"node-role.kubernetes.io/control-plane\"             operator: \"Exists\"             effect: \"NoSchedule\"           - key: \"node-role.kubernetes.io/master\"             operator: \"Exists\"             effect: \"NoSchedule\"         containers:           - name: etcd-backup             image: 192.168.48.19/etcd-backup/etcd-backup:latest             imagePullPolicy: IfNotPresent             securityContext:               runAsUser: 0               runAsNonRoot: false               readOnlyRootFilesystem: true               allowPrivilegeEscalation: false               capabilities:                 drop: [\"ALL\"]             resources:               requests:                 cpu: \"50m\"                 memory: \"128Mi\"               limits:                 cpu: \"500m\"                 memory: \"1Gi\"             env:             - name: ETCDCTL_API               value: \"3\"             command: [\'bash\', \'-c\']             args:               - |                 bash /usr/local/bin/backup_etcd.sh             volumeMounts:               - mountPath: /etc/localtime                 name: localtime                 readOnly: true               - mountPath: /etc/kubernetes/pki                 name: kube-pki                 readOnly: true               - mountPath: /etcd/backup         # 改为脚本用的目录                 name: etcd-bak               - mountPath: /usr/local/bin/backup_etcd.sh                 name: backup-script                 subPath: backup_etcd.sh                 readOnly: true         volumes:           - hostPath:               path: /etc/localtime               type: \'\'             name: localtime           - hostPath:               path: /etc/kubernetes/pki               type: \'\'             name: kube-pki           - hostPath:               path: /data/etcd/backups         # 宿主机保存目录               type: \'\'             name: etcd-bak           - configMap:               name: etcd-backup-config             name: backup-script         restartPolicy: OnFailure

master2备份的cronjob

vim etcd-backup-cronjob-master2.yaml
apiVersion: batch/v1kind: CronJobmetadata: name: etcd-backup-master2 namespace: kube-systemspec: schedule: \"5 23 * * *\"         # 每日23:05(UTC) concurrencyPolicy: Forbid       # 避免并发 successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 1 jobTemplate:   spec:     template:       spec:         hostNetwork: true         dnsPolicy: ClusterFirstWithHostNet         nodeSelector:           etcd-backup: \"master2\" # 绑定第2个master         tolerations:           - key: \"node-role.kubernetes.io/control-plane\"             operator: \"Exists\"             effect: \"NoSchedule\"           - key: \"node-role.kubernetes.io/master\"             operator: \"Exists\"             effect: \"NoSchedule\"         containers:           - name: etcd-backup             image: 192.168.48.19/etcd-backup/etcd-backup:latest             imagePullPolicy: IfNotPresent             securityContext:               runAsUser: 0               runAsNonRoot: false               readOnlyRootFilesystem: true               allowPrivilegeEscalation: false               capabilities:                 drop: [\"ALL\"]             resources:               requests:                 cpu: \"50m\"                 memory: \"128Mi\"               limits:                 cpu: \"500m\"                 memory: \"1Gi\"             env:             - name: ETCDCTL_API               value: \"3\"             command: [\'bash\', \'-c\']             args:               - |                 bash /usr/local/bin/backup_etcd.sh             volumeMounts:               - mountPath: /etc/localtime                 name: localtime                 readOnly: true               - mountPath: /etc/kubernetes/pki                 name: kube-pki                 readOnly: true               - mountPath: /etcd/backup         # 改为脚本用的目录                 name: etcd-bak               - mountPath: /usr/local/bin/backup_etcd.sh                 name: backup-script                 subPath: backup_etcd.sh                 readOnly: true         volumes:           - hostPath:               path: /etc/localtime               type: \'\'             name: localtime           - hostPath:               path: /etc/kubernetes/pki               type: \'\'             name: kube-pki           - hostPath:               path: /data/etcd/backups         # 宿主机保存目录               type: \'\'             name: etcd-bak           - configMap:               name: etcd-backup-config             name: backup-script         restartPolicy: OnFailure

master3备份的cronjob

vim etcd-backup-cronjob-master3.yaml
apiVersion: batch/v1kind: CronJobmetadata: name: etcd-backup-master3 namespace: kube-systemspec: schedule: \"10 23 * * *\"         # 每日23:10(UTC) concurrencyPolicy: Forbid       # 避免并发 successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 1 jobTemplate:   spec:     template:       spec:         hostNetwork: true         dnsPolicy: ClusterFirstWithHostNet         nodeSelector:           etcd-backup: \"master3\" # 绑定第3个master         tolerations:           - key: \"node-role.kubernetes.io/control-plane\"             operator: \"Exists\"             effect: \"NoSchedule\"           - key: \"node-role.kubernetes.io/master\"             operator: \"Exists\"             effect: \"NoSchedule\"         containers:           - name: etcd-backup             image: 192.168.48.19/etcd-backup/etcd-backup:latest             imagePullPolicy: IfNotPresent             securityContext:               runAsUser: 0               runAsNonRoot: false               readOnlyRootFilesystem: true               allowPrivilegeEscalation: false               capabilities:                 drop: [\"ALL\"]             resources:               requests:                 cpu: \"50m\"                 memory: \"128Mi\"               limits:                 cpu: \"500m\"                 memory: \"1Gi\"             env:             - name: ETCDCTL_API               value: \"3\"             command: [\'bash\', \'-c\']             args:               - |                 bash /usr/local/bin/backup_etcd.sh             volumeMounts:               - mountPath: /etc/localtime                 name: localtime                 readOnly: true               - mountPath: /etc/kubernetes/pki                 name: kube-pki                 readOnly: true               - mountPath: /etcd/backup         # 改为脚本用的目录                 name: etcd-bak               - mountPath: /usr/local/bin/backup_etcd.sh                 name: backup-script                 subPath: backup_etcd.sh                 readOnly: true         volumes:           - hostPath:               path: /etc/localtime               type: \'\'             name: localtime           - hostPath:               path: /etc/kubernetes/pki               type: \'\'             name: kube-pki           - hostPath:               path: /data/etcd/backups         # 宿主机保存目录               type: \'\'             name: etcd-bak           - configMap:               name: etcd-backup-config             name: backup-script         restartPolicy: OnFailure

现在目录下包含以下文件:

[root@master1 etcd-backup]# lsDockerfile                       etcd-backup-cronjob-master2.yaml init-etcd-backup.shetcd-backup-config.yaml           etcd-backup-cronjob-master3.yaml kubectletcd-backup-cronjob-master1.yaml etcdctl

4. 开启备份任务

[root@master1 etcd-backup]# kubectl apply -f ./configmap/etcd-backup-config createdcronjob.batch/etcd-backup-master1 createdcronjob.batch/etcd-backup-master2 createdcronjob.batch/etcd-backup-master3 created

5. 查看cronjob状态

[root@master1 etcd-backup]# kubectl get cronjobs.batch -n kube-system NAME                 SCHEDULE     TIMEZONE   SUSPEND   ACTIVE   LAST SCHEDULE   AGEetcd-backup-master1   0 20 * * *        False     0                59setcd-backup-master2   5 20 * * *        False     0                59setcd-backup-master3   10 20 * * *        False     0                59s​

我们可以马上执行这三个cronjob看看效果。

kubectl create job --from=cronjob/etcd-backup-master1 etcd-backup-manual-$(date +%s) -n kube-systemkubectl create job --from=cronjob/etcd-backup-master2 etcd-backup-manual-$(date +%s) -n kube-systemkubectl create job --from=cronjob/etcd-backup-master3 etcd-backup-manual-$(date +%s) -n kube-system

查看是否备份完毕。

[root@master1 etcd-backup]# kubectl get pod -n kube-system | grep etcd-backup-manualetcd-backup-manual-1756482367-5hprb       0/1     Completed   0               29setcd-backup-manual-1756482375-7rgmv       0/1     Completed   0               21setcd-backup-manual-1756482381-smn2l       0/1     Completed   0               15s

显示Completed,说明备份成功了,到备份目录查看。

[root@master1 etcd-backup]# cd /data/etcd/backups/[root@master1 backups]# lsetcd-127.0.0.1-2025_08_26_19_40_08.db etcd-127.0.0.1-2025_08_29_22_56_33.dbetcd-127.0.0.1-2025_08_27_09_51_40.db etcd-127.0.0.1-2025_08_29_23_46_08.db

可以看到保留了三天以内的(其他两天是我之前备份的),和我们预想的一样。

6. 检查备份

在master节点查看备份是否可用

[root@master1 backups]# ETCDCTL_API=3 etcdctl --write-out=table snapshot status /data/etcd/backups/etcd-127.0.0.1-2025_08_29_23_46_08.dbDeprecated: Use `etcdutl snapshot status` instead.​+----------+----------+------------+------------+|   HASH   | REVISION | TOTAL KEYS | TOTAL SIZE |+----------+----------+------------+------------+| e30f1e5f | 1172570 |       2219 |     19 MB |+----------+----------+------------+------------+[root@master2 ~]# ETCDCTL_API=3 etcdctl --write-out=table snapshot status /data/etcd/backups/etcd-127.0.0.1-2025_08_29_23_46_15.db Deprecated: Use `etcdutl snapshot status` instead.​+----------+----------+------------+------------+|   HASH   | REVISION | TOTAL KEYS | TOTAL SIZE |+----------+----------+------------+------------+| cde97ef5 | 1172616 |       2267 |     20 MB |+----------+----------+------------+------------+[root@master3 ~]# ETCDCTL_API=3 etcdctl --write-out=table snapshot status /data/etcd/backups/etcd-127.0.0.1-2025_08_29_23_46_21.db Deprecated: Use `etcdutl snapshot status` instead.​+----------+----------+------------+------------+|   HASH   | REVISION | TOTAL KEYS | TOTAL SIZE |+----------+----------+------------+------------+| bbc38825 | 1172663 |       2311 |     18 MB |+----------+----------+------------+------------+​

到此,k8s自动备份就完成了。恢复方式和前文一样,这里就不再演示了。