Kubernetes 备份与灾难恢复指南

Kubernetes 备份与灾难恢复指南 本文介绍 K3s 集群的备份与恢复策略,包括 etcd 快照、应用数据备份以及集群灾难恢复方法。 概述 在生产环境中运行 Kubernetes 集群时,制定完善的备份与恢复策略至关重要。本文将详细介绍 K3s 集群的备份方法,包括 etcd 数据备份、应用配

Kubernetes 备份与灾难恢复指南

本文介绍 K3s 集群的备份与恢复策略,包括 etcd 快照、应用数据备份以及集群灾难恢复方法。

概述

在生产环境中运行 Kubernetes 集群时,制定完善的备份与恢复策略至关重要。本文将详细介绍 K3s 集群的备份方法,包括 etcd 数据备份、应用配置备份以及完整的灾难恢复流程。

备份策略规划

需要备份的内容

类型 内容 备份频率
集群状态 etcd 数据 每小时
应用配置 YAML 文件、Secrets 每次变更
持久化数据 PVC 数据 每日
证书 TLS 证书、Token 每月

备份工具选择

  • K3s 内置:etcd 快照功能
  • Velero:全面的集群备份方案
  • 脚本工具:自定义备份脚本

etcd 数据备份

使用 K3s 内置快照

K3s 使用嵌入式 etcd 时,提供了便捷的快照功能:

# 手动触发快照
k3s etcd-snapshot save

# 查看快照列表
ls -la /var/lib/rancher/k3s/server/db/snapshots/

# 输出示例
on-demand-ip-172-31-3-36-1688025329

自动快照配置

# 配置定时快照(通过 cron)
crontab -e

# 每小时执行一次快照
0 * * * * /usr/local/bin/k3s etcd-snapshot save

# 保留最近 7 天的快照
0 0 * * * find /var/lib/rancher/k3s/server/db/snapshots/ -name "*.etcd" -mtime +7 -delete

快照文件位置

/var/lib/rancher/k3s/server/db/snapshots/
├── on-demand-k8s-server-01-1720245075
└── etcd-snapshot-2024-01-06T10:00:00Z

灾难恢复

基于内嵌 etcd 恢复

当集群出现严重故障时,可以通过快照恢复:

# 1. 停止 K3s 服务
systemctl stop k3s

# 2. 使用快照恢复
k3s server \
  --cluster-reset \
  --cluster-reset-restore-path=/var/lib/rancher/k3s/server/db/snapshots/on-demand-k8s-server-01-1720245075

# 3. 等待恢复完成,然后正常启动
systemctl start k3s

其他 Server 节点恢复

在主节点恢复后,其他 Server 节点需要清理 etcd 数据后重新加入:

# 在其他 Server 节点执行
systemctl stop k3s
rm -rf /var/lib/rancher/k3s/server/db/

# 重新启动,会自动从主节点同步数据
systemctl start k3s

全量备份脚本

备份脚本

#!/bin/bash
# k3s_backup.sh

BACKUP_DIR="/backup/k3s/$(date +%Y%m%d)"
K3S_DATA_DIR="/var/lib/rancher/k3s"
RETENTION_DAYS=7

mkdir -p "${BACKUP_DIR}"

# 1. 备份 etcd 快照
echo "[INFO] Creating etcd snapshot..."
k3s etcd-snapshot save

cp ${K3S_DATA_DIR}/server/db/snapshots/* "${BACKUP_DIR}/"

# 2. 备份集群配置
echo "[INFO] Backing up cluster configurations..."
kubectl get all --all-namespaces -o yaml > "${BACKUP_DIR}/cluster-resources.yaml"
kubectl get configmap --all-namespaces -o yaml > "${BACKUP_DIR}/configmaps.yaml"
kubectl get secret --all-namespaces -o yaml > "${BACKUP_DIR}/secrets.yaml"
kubectl get ingress --all-namespaces -o yaml > "${BACKUP_DIR}/ingresses.yaml"
kubectl get pvc --all-namespaces -o yaml > "${BACKUP_DIR}/pvcs.yaml"

# 3. 备份 K3s 配置
echo "[INFO] Backing up K3s configurations..."
cp -r /etc/rancher/k3s "${BACKUP_DIR}/k3s-config"
cp ${K3S_DATA_DIR}/server/token "${BACKUP_DIR}/" 2>/dev/null || true
cp ${K3S_DATA_DIR}/server/node-token "${BACKUP_DIR}/" 2>/dev/null || true

# 4. 压缩备份
echo "[INFO] Compressing backup..."
tar -czf "${BACKUP_DIR}.tar.gz" -C "${BACKUP_DIR%/*}" "$(basename ${BACKUP_DIR})"
rm -rf "${BACKUP_DIR}"

# 5. 清理旧备份
echo "[INFO] Cleaning up old backups..."
find /backup/k3s -name "*.tar.gz" -mtime +${RETENTION_DAYS} -delete

echo "[INFO] Backup completed: ${BACKUP_DIR}.tar.gz"

恢复脚本

#!/bin/bash
# k3s_restore.sh

BACKUP_FILE="$1"
K3S_DATA_DIR="/var/lib/rancher/k3s"

if [ -z "$BACKUP_FILE" ]; then
    echo "Usage: $0 <backup-file.tar.gz>"
    exit 1
fi

# 1. 停止 K3s
systemctl stop k3s

# 2. 备份当前数据(可选)
if [ -d "${K3S_DATA_DIR}" ]; then
    mv ${K3S_DATA_DIR} ${K3S_DATA_DIR}.bak.$(date +%Y%m%d%H%M%S)
fi

# 3. 解压备份
mkdir -p ${K3S_DATA_DIR}
tar -xzf "${BACKUP_FILE}" -C /tmp
BACKUP_DIR="/tmp/$(basename ${BACKUP_FILE%.tar.gz})"

# 4. 恢复 etcd 数据
mkdir -p ${K3S_DATA_DIR}/server/db
if [ -d "${BACKUP_DIR}/snapshots" ]; then
    cp ${BACKUP_DIR}/snapshots/* ${K3S_DATA_DIR}/server/db/snapshots/
    k3s server --cluster-reset \
      --cluster-reset-restore-path=$(ls -t ${K3S_DATA_DIR}/server/db/snapshots/ | head -1)
fi

# 5. 恢复配置
cp -r ${BACKUP_DIR}/k3s-config/* /etc/rancher/k3s/

# 6. 启动 K3s
systemctl start k3s

echo "[INFO] Restore completed"

应用数据备份

PVC 数据备份

使用 Velero

# 安装 Velero CLI
wget https://github.com/vmware-tanzu/velero/releases/download/v1.12.0/velero-v1.12.0-linux-amd64.tar.gz
tar -xzf velero-v1.12.0-linux-amd64.tar.gz
mv velero-v1.12.0-linux-amd64/velero /usr/local/bin/

# 安装 Velero Server(使用 MinIO 作为后端)
velero install \
  --provider aws \
  --plugins velero/velero-plugin-for-aws:v1.8.0 \
  --bucket k8s-backup \
  --secret-file ./credentials-velero \
  --use-volume-snapshots=false \
  --backup-location-config region=minio,s3ForcePathStyle=true,s3Url=http://minio.example.com:9000

创建备份

# 备份整个集群
velero backup create full-backup-$(date +%Y%m%d)

# 备份指定命名空间
velero backup create nginx-backup --include-namespaces nginx

# 备份包含 PVC
velero backup create app-backup \
  --include-namespaces app \
  --snapshot-volumes \
  --volume-snapshot-locations aws

恢复备份

# 查看备份列表
velero backup get

# 恢复备份
velero restore create --from-backup full-backup-20240106

# 恢复到指定命名空间
velero restore create --from-backup app-backup --namespace-mappings app:app-new

数据库备份示例

MySQL 备份

apiVersion: batch/v1
kind: CronJob
metadata:
  name: mysql-backup
spec:
  schedule: "0 2 * * *"  # 每天凌晨 2 点
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: mysql-backup
              image: mysql:8.0
              command:
                - /bin/sh
                - -c
                - |
                  mysqldump -h mysql-service -u root -p${MYSQL_ROOT_PASSWORD} \
                    --all-databases > /backup/mysql-$(date +%Y%m%d).sql
              env:
                - name: MYSQL_ROOT_PASSWORD
                  valueFrom:
                    secretKeyRef:
                      name: mysql-secret
                      key: password
              volumeMounts:
                - name: backup-volume
                  mountPath: /backup
          volumes:
            - name: backup-volume
              persistentVolumeClaim:
                claimName: backup-pvc
          restartPolicy: OnFailure

证书备份

备份证书和 Token

# 备份 Server Token
cp /var/lib/rancher/k3s/server/token /backup/

# 备份 Node Token
cp /var/lib/rancher/k3s/server/node-token /backup/

# 备份 TLS 证书
tar -czf /backup/k3s-certs-$(date +%Y%m%d).tar.gz \
  /var/lib/rancher/k3s/server/tls/

轮换证书

K3s 客户端和服务器证书有效期为 365 天,到期前会自动轮换:

# 手动轮换证书
systemctl stop k3s
k3s certificate rotate
systemctl start k3s

# 轮换完成后验证
kubectl get nodes

异地备份策略

使用 rsync 同步到远程服务器

#!/bin/bash
# remote_backup.sh

LOCAL_BACKUP_DIR="/backup/k3s"
REMOTE_SERVER="backup@backup-server.example.com"
REMOTE_DIR="/backup/k8s-cluster"

# 同步到远程服务器
rsync -avz --delete ${LOCAL_BACKUP_DIR}/ ${REMOTE_SERVER}:${REMOTE_DIR}/

# 保留远程服务器上最近 30 天的备份
ssh ${REMOTE_SERVER} "find ${REMOTE_DIR} -name '*.tar.gz' -mtime +30 -delete"

使用云存储

# 使用 rclone 同步到对象存储
rclone sync /backup/k3s remote:my-k8s-backup-bucket

# 使用 AWS CLI 上传到 S3
aws s3 sync /backup/k3s s3://my-k8s-backup-bucket/k3s/

灾难恢复演练

演练步骤

  1. 模拟故障

    # 停止所有 K3s 服务
    systemctl stop k3s
    # 或删除 etcd 数据
    rm -rf /var/lib/rancher/k3s/server/db
    
  2. 执行恢复

    • 使用备份脚本恢复数据
    • 验证集群状态
  3. 验证应用

    # 检查节点状态
    kubectl get nodes
    
    # 检查 Pod 状态
    kubectl get pods --all-namespaces
    
    # 测试服务访问
    curl http://app.example.com
    

恢复时间目标(RTO)

场景 RTO 方法
单节点故障 5 分钟 自动重新调度
etcd 数据损坏 15 分钟 快照恢复
整个集群丢失 1 小时 全量备份恢复
数据中心灾难 4 小时 异地备份恢复

最佳实践

备份建议

  1. 定期备份:etcd 每小时,配置每次变更,数据每日
  2. 多地存储:本地 + 异地 + 云存储
  3. 定期演练:每季度进行一次恢复演练
  4. 监控告警:备份失败及时通知

安全配置

# 加密备份文件
gpg --symmetric --cipher-algo AES256 backup.tar.gz

# 安全传输
scp -i /path/to/private_key backup.tar.gz user@remote:/backup/

总结

本文介绍了 K3s 集群的备份与恢复策略:

  1. etcd 备份:使用 K3s 内置快照功能定期备份集群状态
  2. 应用备份:使用 Velero 或 CronJob 备份应用数据
  3. 灾难恢复:详细的恢复步骤和演练方法
  4. 异地备份:多地点存储确保数据安全

完善的备份策略是生产环境稳定运行的重要保障,建议根据业务需求制定合适的备份计划和恢复流程。

Comment