etcd 备份与恢复

集群上的 etcd 服务是一个分布式键值存储,用于存储集群配置信息。etcd 部署在集群的所有控制平面节点上。

安装 Cluster Enhancement 插件后,系统会自动为集群配置创建一个 EtcdBackupConfiguration 资源。EtcdBackupConfiguration 包含备份数据源、控制平面节点路径、备份数据存储位置和备份方法。根据策略执行的每次备份都会生成一条新的备份记录,从而支持按需备份和定期备份集群配置。

前提条件

要启用 etcd 备份,请执行以下操作:

  1. 从 Customer Portal 下载 Cluster Enhancement。
  2. 将软件包上传到平台。
  3. 在集群上安装插件。

安装后,系统会自动创建 EtcdBackupConfiguration 资源。

工作原理

  • etcd 备份由 Cluster Enhancement 提供。
  • 支持本地存储和兼容 S3 的对象存储。本地备份会写入每个控制平面节点上的目录,默认为 /var/cpaas/backup。请为该目录规划足够的容量,以满足 etcd 数据大小和保留期限的要求。配置 S3 存储后,会在 S3 存储桶中创建额外副本;本地备份仍会继续生成。
  • 对于节点运行 Alauda OS 的集群,本地备份默认使用 /var/cpaas/backup。仍可通过 remoteStorage.s3 使用 S3 存储。

配置参考

您可以配置 EtcdBackupConfiguration 资源,以自定义备份计划、保留策略和存储选项。

计划和保留

  • schedule:使用标准 cron 语法定义备份频率。
    • 示例:0 0 * * *(每天午夜运行备份)。
  • localStorage:配置本地备份存储。
    • path:每个控制平面节点上用于存储备份的目录。默认值为 /var/cpaas/backup。请将其设置为具有足够容量的目录,以满足 etcd 数据大小和配置的保留期限要求;请参阅下面的存储说明。
    • ttl:备份文件的保留期限,单位为秒。超过此期限的备份将自动删除。
      • 示例:7776000(约 90 天)。
  • paused:设置为 true,可在不删除配置的情况下暂时暂停自动备份。
WARNING

启用 etcd 备份前,请规划本地备份所需的存储容量。本地备份会累积在控制平面节点上,并一直保留到其 ttl 过期,因此 /var/cpaas/backup 必须有足够的可用空间,以满足预期的备份大小和保留期限要求。

配置示例:

apiVersion: enhancement.cluster.alauda.io/v1
kind: EtcdBackupConfiguration
metadata:
  name: etcd-backup-default
spec:
  schedule: "0 0 * * *"       # Run daily at 00:00
  paused: false               # Enable backups
  localStorage:
    path: /var/cpaas/backup   # Local backup directory on each control plane node
    ttl: "7776000"            # Retain for 90 days
  # ... other fields

查看备份记录

要查看 etcd 备份记录,可以使用平台 UI 或命令行。

使用平台 UI

  1. 在左侧导航栏中,点击 运维中心 > 监控 > 仪表板。
  2. 点击页面右上角的 切换。
  3. 点击 集群 → etcd 备份,查看 etcd 备份记录。

使用 CLI

通过检查 EtcdBackupConfiguration 资源的 status 字段,可以验证备份状态和历史记录:

kubectl get etcdbackupconfiguration etcd-backup-default -o yaml

输出包含一个 status.records 列表,其中包含每次备份的详细信息,包括:

  • backupTimestamp:备份创建的时间。
  • fileName:备份文件的名称(例如 snapshot-etcd-<date>-<time>-<ip>.tar)。
  • result:备份操作的结果(例如 Success)。

S3 备份配置

要为 etcd 备份启用 S3 存储,请执行以下步骤:

前提条件

  • 集群中已安装 Cluster Enhancement。

步骤 1:创建 S3 Secret

准备 S3 访问凭据,并在 cpaas-system 命名空间中创建 Kubernetes secret:

export ACCESS_KEY="your-access-key"
export SECRET_KEY="your-secret-key"

kubectl create secret generic etcd-backup-s3-secret \
  --from-literal=ACCESS_KEY="$ACCESS_KEY" \
  --from-literal=SECRET_KEY="$SECRET_KEY" \
  --dry-run=client -n cpaas-system -o yaml | kubectl apply -f -

步骤 2:配置 EtcdBackupConfiguration

修改 EtcdBackupConfiguration 资源,添加包含 S3 配置的 remoteStorage 字段:

spec:
  remoteStorage:
    s3:
      endpoint: "your-s3-endpoint"  # e.g.: https://s3.bucket.com
      region: "your-s3-region"
      bucket: "your-s3-bucket"
      dir: "your-s3-bucket-dir"
      skipTLSVerify: false  # Set to true only for self-signed certificates
      secretRef: etcd-backup-s3-secret

步骤 3:验证备份

触发手动 etcd 备份以验证配置:

# Set environment variables
token="your-platform-token"
platform_url="your-platform-url"
cluster_name="your-cluster-name"

# Trigger backup
curl $platform_url/kubernetes/$cluster_name/apis/enhancement.cluster.alauda.io/v1/etcdbackupconfigurations/etcd-backup-default/exec \
  -k -H "Authorization: Bearer $token"

备份完成后,验证 S3 bucket 中是否存在备份文件。

准备恢复时,使用备份记录中显示的 fileName 和已配置的 remoteStorage.s3.dir 值,从 S3 下载 tar 归档文件:

aws --endpoint-url <s3-endpoint> s3 cp \
  s3://<bucket>/<dir>/<backup-file-name> \
  /tmp/snapshot-etcd.tar

mkdir -p /tmp/etcd-restore
tar -xf /tmp/snapshot-etcd.tar -C /tmp/etcd-restore
find /tmp/etcd-restore -name 'snapshot-etcd-*.db' -type f

etcd 恢复

警告:

  • 此操作会对 etcd 集群执行破坏性恢复,并覆盖现有数据。请确保在继续操作前已有有效的备份快照。
  • 此操作步骤存在重大风险。如果不确定如何操作,请联系技术支持。
  • 恢复过程中,Kubernetes API Server 将不可用。

前提条件

  • Kubernetes 集群使用主机名部署(kubectl get node 显示主机名作为节点名称)。
  • 有可用的 etcd 备份快照。
  • 集群因 etcd 故障而运行异常(例如,超过半数的控制平面节点已宕机)。
  • 此恢复操作步骤专为 3 节点控制平面 集群设计。如果集群有 5 个或更多控制平面节点,请联系技术支持。
  • 在 Alauda OS 上,开始恢复前,请确认每个控制平面节点上都存在 /var/lib/etcd、/etc/kubernetes/manifests/etcd.yaml 和 /etc/kubernetes/pki/etcd/。
  • 在 Alauda OS 上,主机 PATH 中可能没有 etcdctl。请在 /var/lib/containerd 下查找,或使用包含兼容的 etcdctl 二进制文件的容器镜像。

步骤 1:备份原始数据并修改 etcd 配置

在所有控制平面节点上执行以下命令:

# Create backup directory
mkdir -p /root/backup_$(date +%Y%m%d%H)/old-etcd/

# Stop kubelet
systemctl stop kubelet

# Prepare etcdctl binary
ETCDCTL_PATH="$(find /var/lib/containerd/ -name etcdctl -type f | tail -1)"
if [ -z "$ETCDCTL_PATH" ]; then
  echo "etcdctl was not found under /var/lib/containerd. Use a container image that includes a compatible etcdctl binary."
  exit 1
fi
cp "$ETCDCTL_PATH" /root/etcdctl
chmod +x /root/etcdctl

# Remove etcd containers
crictl ps -a | grep etcd | awk '{print $1}' | xargs -r crictl rm -f

# Backup etcd data and kubernetes configuration
cp -a /var/lib/etcd/* /root/backup_$(date +%Y%m%d%H)/old-etcd/
rm -rf /var/lib/etcd/*
cp -r /etc/kubernetes/ /root/backup_$(date +%Y%m%d%H)/old-etcd/

# Modify etcd.yaml to use existing cluster state
sed -i /initial-cluster-state=/d /etc/kubernetes/manifests/etcd.yaml
sed -i '/initial-cluster=/a\    - --initial-cluster-state=existing' /etc/kubernetes/manifests/etcd.yaml

注意:请检查 /etc/kubernetes/manifests/etcd.yaml 中 --initial-cluster-state=existing 的缩进。

步骤 2:复制备份快照

将选定的 etcd 备份快照复制到第一个控制平面节点上的 /tmp 目录,并将其命名为 snapshot.db。

如果备份 tar 归档文件已在本地,请从 /var/cpaas/backup 中解压:

mkdir -p /tmp/etcd-restore
tar -xf "$(ls -1t /var/cpaas/backup/snapshot-etcd-*.tar | head -1)" -C /tmp/etcd-restore
cp "$(find /tmp/etcd-restore -name 'snapshot-etcd-*.db' -type f | head -1)" /tmp/snapshot.db

如果备份 tar 归档文件存储在 S3 中,请先下载,然后解压快照文件:

aws --endpoint-url <s3-endpoint> s3 cp \
  s3://<bucket>/<dir>/<backup-file-name> \
  /tmp/snapshot-etcd.tar

mkdir -p /tmp/etcd-restore
tar -xf /tmp/snapshot-etcd.tar -C /tmp/etcd-restore
cp "$(find /tmp/etcd-restore -name 'snapshot-etcd-*.db' -type f | head -1)" /tmp/snapshot.db

步骤 3:恢复 etcd

在第一个控制平面节点上执行以下脚本,以恢复快照。

注意:以下脚本假设集群具有 3 节点控制平面。如果集群有 5 个或更多节点,请联系技术支持。

#!/usr/bin/env bash

# Set etcd node IPs (Replace with actual IPs)
export ETCD_1=1.1.1.1
export ETCD_2=2.2.2.2
export ETCD_3=3.3.3.3

# Set corresponding node hostnames (Replace with actual hostnames)
export ETCD_1_HOSTNAME=etcd-1
export ETCD_2_HOSTNAME=etcd-2
export ETCD_3_HOSTNAME=etcd-3

export ETCDCTL_API=3

# Loop for 3 nodes. Adjust '1 2 3' if you have a different number of nodes.
for n in 1 2 3; do
  ip_var=ETCD_${n}
  host_var=ETCD_${n}_HOSTNAME

  ip=${!ip_var}
  host=${!host_var}

  echo "Restoring for node: ${host} (${ip})..."

  rm -rf /tmp/etcd
  /root/etcdctl snapshot restore /tmp/snapshot.db \
    --cert=/etc/kubernetes/pki/etcd/server.crt \
    --key=/etc/kubernetes/pki/etcd/server.key \
    --cacert=/etc/kubernetes/pki/etcd/ca.crt \
    --skip-hash-check=true \
    --data-dir=/tmp/etcd \
    --name "${host}" \
    --initial-cluster \
      ${ETCD_1_HOSTNAME}=https://${ETCD_1}:2380,\
${ETCD_2_HOSTNAME}=https://${ETCD_2}:2380,\
${ETCD_3_HOSTNAME}=https://${ETCD_3}:2380 \
    --initial-advertise-peer-urls https://"${ip}":2380 && \
    mv /tmp/etcd /root/etcd_"${host}"

  echo "Restoration for ${host} completed. Data directory: /root/etcd_${host}"
done

脚本完成后,将在 /root 目录中生成三个目录(etcd_$host)。

步骤 4:分发恢复的数据

  1. 将恢复的数据目录传输到相应的控制平面节点。使用 scp 或类似工具,将步骤 3 中生成的目录(/root/etcd_<hostname>)从第一个节点复制到其他节点。

    例如,传输到 etcd-2 和 etcd-3:

    # Replace <etcd-2-ip> and <etcd-3-ip> with actual IPs
    scp -r /root/etcd_etcd-2 root@<etcd-2-ip>:/root/
    scp -r /root/etcd_etcd-3 root@<etcd-3-ip>:/root/
  2. 将数据恢复到每个控制平面节点上的 etcd 数据目录(/var/lib/etcd)。

    # On etcd-1:
    cp -r /root/etcd_etcd-1/member/* /var/lib/etcd/
    
    # On etcd-2:
    cp -r /root/etcd_etcd-2/member/* /var/lib/etcd/
    
    # On etcd-3:
    cp -r /root/etcd_etcd-3/member/* /var/lib/etcd/

步骤 5:重启集群组件

在所有控制平面节点上执行以下命令:

# Remove Kubernetes control plane containers
crictl ps -a | grep -E "kube-api|kube-sche|kube-contro" | awk '{print $1}' | xargs -r crictl rm -f

# Restart kubelet
systemctl restart kubelet

步骤 6:验证恢复

  1. 检查 etcd 集群是否健康。可以在任意 etcd pod 中执行此命令,或在主机上使用 etcdctl 二进制文件:

    # Using etcdctl on the host
    export ETCDCTL_API=3
    /root/etcdctl --cacert=/etc/kubernetes/pki/etcd/ca.crt \
      --cert=/etc/kubernetes/pki/etcd/server.crt \
      --key=/etc/kubernetes/pki/etcd/server.key \
      --endpoints=https://127.0.0.1:2379 \
      endpoint health
  2. 检查 Kubernetes pod 是否正常运行:

    kubectl get po -n kube-system
  3. 在所有节点(包括控制平面节点和工作节点)上重启 kubelet,以确保所有组件重新连接到恢复的 etcd:

    systemctl restart kubelet

配置管理

如需修改默认的 etcd 备份配置,请联系技术支持以获取详细的配置选项和高级设置。