k3s-etcd-backup · 定时给 etcd 拍快照并加密上传 MinIO

etcd 存储整个 Kubernetes 集群的状态(所有资源定义、ConfigMap、Secret、集群元数据),一旦损坏会让 API 不可用,因此它需要独立于 Velero 之外的专门备份。这个组件就是集群三层备份策略里的「层次 1」——以 CronJob 的形式跑在 kube-system 命名空间,每 6 小时给 etcd 拍一次快照,校验完整性、保留本地 7 天,并把快照 GPG 加密后上传到 MinIO,使得 MinIO/NAS 上永远不落明文 etcd(明文 etcd 含全部 Kubernetes secret)。

它由两组互补的 CronJob 组成:一组(etcd-backup)调度到任一控制平面节点,自己用 etcdctl snapshot save 主动拍快照存到一块 NFS PVC;另一组(k3s-etcd-snapshot-upload-masterN,每个 master 一个)直接读取 K3s 自身生成在本机磁盘上的快照,逐个 GPG 加密后用 rclone 推到 MinIO。

部署形态

ArgoCD 通过 bootstrap/applications/infrastructure/etcd-backup.yaml 同步本目录(Application 名 etcd-backup,project platformautomated: {prune, selfHeal},目标命名空间 kube-system)。本目录没有 kustomization,直接是裸 YAML 清单。

  • Name
    命名空间
    Description
    kube-system
  • Name
    工作负载类型
    Description
    CronJob ×4(1 个主动快照 + 3 个 per-master 上传),均 alpine:3.24,concurrencyPolicy: Forbid
  • Name
    调度时间
    Description
    主动快照与 master1 上传 0 */6 * * *,master2 5 */6 * * *,master3 10 */6 * * *(均含时区 Asia/Tokyo),即每 6 小时一轮、错峰 5 分钟
  • Name
    调度约束
    Description
    主动快照 CronJob 用 nodeSelector: node-role.kubernetes.io/control-plane=true + control-plane 污点 toleration,hostNetwork: true 连本机 etcd;三个上传 CronJob 分别 nodeName: k8s-master1/2/3 钉死到对应 master
  • Name
    存储
    Description
    主动快照写到 PVC etcd-backup-storage(storageClass nfs-client,RWX,20Gi);上传任务只读挂载本机快照目录,不占 PVC
  • Name
    历史保留
    Description
    successfulJobsHistoryLimit / failedJobsHistoryLimit 均为 3

主动快照容器在运行时下载 etcdctl v3.5.12,从 https://127.0.0.1:2379 拉取快照,使用 K3s 的 etcd 证书(/var/lib/rancher/k3s/server/tls/etcd 下的 server-ca.crt / server-client.crt / server-client.key,以只读 hostPath 挂入)。快照存为 etcd-snapshot-<时间戳>.db,附带一份 .metadata(含时间戳、主机名、大小、SHA256、etcd 版本),并清理本地 7 天前的旧快照。

配置与依赖

  • Name
    ExternalSecret
    Description
    etcd-backup-gpg(ClusterSecretStore vault-backend)从 Vault yldm/backup/oracle-gpg-passphrase(property passphrase)拉取 GPG 口令,生成 Secret etcd-backup-gpg-passphrase,refreshInterval 1h。这是独立于 Oracle 主机的 break-glass 副本
  • Name
    MinIO 凭据
    Description
    上传任务从 minio-secretroot-password 读取密码,access key 写死为 xiaomo,endpoint http://minio.minio.svc.cluster.local:9000
  • Name
    加密方式
    Description
    gpg --batch -c --cipher-algo AES256,口令来自挂载的 /gpg/passphrase;产物 <快照名>.gpg 上传后从 /tmp 删除
  • Name
    上传目标
    Description
    MinIO bucket k3s-etcd-snapshots/<主机名>/;上传前先 rclone lsf 去重,已存在的 .gpg 跳过,实现幂等增量上传
  • Name
    RBAC
    Description
    ServiceAccount etcd-backup + ClusterRole/Binding,授予 pods、pods/exec(get/list/create)与 nodes(get/list)

上传 CronJob 通过只读 hostPath 挂载本机的 K3s 快照目录 /var/lib/rancher/k3s/server/db/snapshots,并挂载 /etc(用于读取节点 hostname 拼出 MinIO 子路径)。它不调用 etcdctl,只是把 K3s 自动生成的快照做加密搬运。

访问与监控

这是纯后台批处理组件,没有 Service、Ingress、ServiceMonitor、PrometheusRule、HPA/VPA 或 PDB——CronJob 不需要这些。运行结果以 Job 历史(成功/失败各保留 3 个)和容器日志体现,日志里会打印快照大小、SHA256、本地备份统计,以及上传了几个新的加密快照。

资源配额:主动快照容器 requests 100m/256Mi、limits 500m/512Mi;每个上传容器 requests 100m/128Mi、limits 500m/512Mi。

注意事项

按集群备份运维手册,etcd 快照属于三层备份的层次 1(频率每 6 小时、本地保留 7 天、恢复时间目标 < 5 分钟),层次 2 是 Velero 每日集群备份,层次 3 是数据库逻辑备份 + PVE VM 快照。Velero 备份的是 Kubernetes 资源,但 etcd 故障会让 API 本身不可用,所以 etcd 必须单独备份、用于快速整体恢复。

解密用同一口令:Vault 路径 secret/yldm/backup/oracle-gpg-passphrase。注意 ESO 的 remoteRef.key 省略了 secret/ 挂载前缀(store 会自动补上),而用 vault CLI 读写时需带上完整的 secret/...

由于设计上集群、MinIO、NAS 三处都不保存明文 etcd,恢复时必须先用该 GPG 口令解密 .gpg 才能拿到 .db 快照——口令丢失等同于备份不可用,务必确保 Vault 与 Oracle 两处副本都在。

返回 infrastructure 总览

评论