目录
[1. etcd备份](#1. etcd备份)
[2. 数据恢复](#2. 数据恢复)
[3. 总结与流程梳理](#3. 总结与流程梳理)
[错误一:Error: snapshot restore requires exactly one argument](#错误一:Error: snapshot restore requires exactly one argument)
[错误二:-bash: etcdutl: 未找到命令](#错误二:-bash: etcdutl: 未找到命令)
[1. 构建备份工具镜像](#1. 构建备份工具镜像)
[1.1. 镜像文件准备](#1.1. 镜像文件准备)
[1.2. 编写备份环境初始化脚本](#1.2. 编写备份环境初始化脚本)
[1.3. 编写Dockerfile](#1.3. 编写Dockerfile)
[1.4. 构建镜像](#1.4. 构建镜像)
[1.5. 上传镜像](#1.5. 上传镜像)
[2. 编写ConfigMap](#2. 编写ConfigMap)
[3. 编写CronJob](#3. 编写CronJob)
[4. 开启备份任务](#4. 开启备份任务)
[5. 查看cronjob状态](#5. 查看cronjob状态)
[6. 检查备份](#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. 参数详解
ETCDCTL_API=3
-
类型:环境变量
-
含义 :指定使用 etcdctl 工具的 v3 API。
-
为什么需要 :etcdctl 为了兼容旧版本,需要明确指定使用哪个版本的 API。快照(snapshot)功能是 v3 API 引入的,所以必须设置为 3。
etcdctl snapshot restore
-
类型:主命令
-
含义:这是 etcdctl 工具的子命令,用于从快照文件执行恢复操作。
/etcd/backup/etcdbackup.db
-
类型:位置参数
-
含义 :源快照文件的路径。这是你之前通过
etcdctl snapshot save
命令创建的备份文件的位置。 -
说明:执行恢复操作前,必须确保这个文件存在于该路径下。
--name master1
-
类型:关键配置参数
-
含义 :指定当前节点 在即将创建的新集群 中的成员名称。
-
说明 :这个名称必须 与后面
--initial-cluster
参数列表中对应本节点 IP 的那个成员的名称一致。这里告诉系统:"我这台机器,在新集群里的名字叫master1
。"
--data-dir /var/lib/etcd
-
类型:关键配置参数
-
含义 :指定恢复操作生成的全新数据目录的路径。
-
说明 :恢复过程会创建一个全新的 etcd 数据目录。重要提示 :你不能覆盖当前正在运行的 etcd 实例的数据目录。通常,你会先停止 etcd 服务,删除或移走旧的
/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"
-
类型 :最关键的集群配置参数
-
含义 :定义新集群的初始成员列表。
-
格式 :
<成员名称1>=<peer-url1>, <成员名称2>=<peer-url2>, ...
-
详细解释:
-
master1=https://192.168.48.11:2380
:名为master1
的节点,其对等通信地址(Peer URL) 是https://192.168.48.11:2380
。 -
master2=...
和master3=...
:定义了集群的另外两个节点。 -
端口 2380 :这是 etcd 节点间内部通信的专用端口(用于领导选举、数据同步、心跳等)。
-
-
为什么需要:这个参数告诉正在恢复的节点:"你将要加入的这个新集群,总共有这三个成员,这是他们的名字和联系方式。"
--initial-cluster-token etcd-cluster-token
-
类型:安全配置参数
-
含义 :为新集群设置一个唯一的集群令牌。
-
为什么需要 :这个令牌用于防止新集群在初始启动时与网络中其他无关的 etcd 集群意外连接并形成同一个集群。执行恢复时,必须提供一个新的 token,因为这相当于创建一个全新的集群,而不是加入旧的。
--initial-advertise-peer-urls "https://192.168.48.11:2380"
-
类型:关键网络配置参数
-
含义 :指定本节点 在新集群 中对外宣告的对等通信地址(Peer URL)。
-
详细解释:
-
对等通信地址用于 etcd 集群成员节点之间的通信(如心跳、数据同步、领导者选举)。
-
这个地址必须能被集群中其他所有节点访问到。
-
关键一致性 :这个地址必须 出现在上面的
--initial-cluster
参数列表中,与--name
参数指定的名称相对应。在这个命令中,--name
是master1
,所以在--initial-cluster
列表中找master1
,它的 URL 也必须是https://192.168.48.11:2380
。两者必须完全匹配,否则集群无法形成。
-
这条命令在 master1
节点上执行后,会:
-
读取快照文件
/etcd/backup/etcdbackup.db
中的数据。 -
在
/var/lib/etcd
目录下创建一个全新的数据结构。 -
将快照中的数据恢复到新目录中。
-
丢弃旧集群的所有成员信息和网络配置。
-
根据你提供的参数,生成新集群的初始化配置:
-
集群名叫
etcd-cluster-token
。 -
集群有三个节点:master1, master2, master3。
-
本节点(master1)告诉其他节点:"想和我进行内部管理通信,请用
https://192.168.48.11:2380
这个地址找我。"
-
执行流程:
-
在
master1
(IP: 192.168.48.11) 上执行上面的命令。 -
在
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"
-
在
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
这个命令。etcdutl
和 etcdctl
的分拆是较新版本才引入的。
解决方案
使用旧的、但肯定可用的 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"
我做的改进:
-
移除了错误的换行 :确保
--name master1
是一个完整的单元。 -
给URL列表加上了引号 :使用引号
"..."
将包含逗号的--initial-cluster
参数值括起来,这是一个好习惯,可以避免 shell 解析错误。
执行流程:
-
在
master1
(IP: 192.168.48.11) 上执行上面的命令。 -
在
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"
-
在
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 bash
set -euo pipefail
# Create required hostPath directories
REQUIRED_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 differently
kubectl label node master1 etcd-backup=master1 --overwrite
kubectl label node master2 etcd-backup=master2 --overwrite
kubectl label node master3 etcd-backup=master3 --overwrite
echo -e "\e[32mInitialization complete.\e[0m"
EOF
执行这个脚本
所有master节点都要做。
chmod +x init-etcd-backup.sh
sh 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 /bin
RUN chmod +x /bin/kubectl
# 固定使用随项目提供的 etcdctl 二进制
COPY etcdctl /bin
RUN 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:latest
docker push 192.168.48.19/etcd-backup/etcd-backup:latest
2. 编写ConfigMap
vim etcd-backup-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: etcd-backup-config
namespace: kube-system
data:
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/v1
kind: CronJob
metadata:
name: etcd-backup-master1
namespace: kube-system
spec:
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/v1
kind: CronJob
metadata:
name: etcd-backup-master2
namespace: kube-system
spec:
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/v1
kind: CronJob
metadata:
name: etcd-backup-master3
namespace: kube-system
spec:
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]# ls
Dockerfile etcd-backup-cronjob-master2.yaml init-etcd-backup.sh
etcd-backup-config.yaml etcd-backup-cronjob-master3.yaml kubectl
etcd-backup-cronjob-master1.yaml etcdctl
4. 开启备份任务
[root@master1 etcd-backup]# kubectl apply -f ./
configmap/etcd-backup-config created
cronjob.batch/etcd-backup-master1 created
cronjob.batch/etcd-backup-master2 created
cronjob.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 AGE
etcd-backup-master1 0 20 * * * <none> False 0 <none> 59s
etcd-backup-master2 5 20 * * * <none> False 0 <none> 59s
etcd-backup-master3 10 20 * * * <none> False 0 <none> 59s
我们可以马上执行这三个cronjob看看效果。
kubectl create job --from=cronjob/etcd-backup-master1 etcd-backup-manual-$(date +%s) -n kube-system
kubectl create job --from=cronjob/etcd-backup-master2 etcd-backup-manual-$(date +%s) -n kube-system
kubectl 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-manual
etcd-backup-manual-1756482367-5hprb 0/1 Completed 0 29s
etcd-backup-manual-1756482375-7rgmv 0/1 Completed 0 21s
etcd-backup-manual-1756482381-smn2l 0/1 Completed 0 15s
显示Completed,说明备份成功了,到备份目录查看。
[root@master1 etcd-backup]# cd /data/etcd/backups/
[root@master1 backups]# ls
etcd-127.0.0.1-2025_08_26_19_40_08.db etcd-127.0.0.1-2025_08_29_22_56_33.db
etcd-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.db
Deprecated: 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自动备份就完成了。恢复方式和前文一样,这里就不再演示了。