148 lines
5.7 KiB
Markdown
148 lines
5.7 KiB
Markdown
# 06-03-k3s 自动备份与恢复(基于 openlist + WebDAV)
|
||
|
||
> 本文专注一件事:**如何为使用本地目录的工作负载补上一条“自动备份 + 半自动恢复”的安全网**。
|
||
> 核心工具:openlist 聚合网盘 + WebDAV 暴露 + `rclone` / CronJob / CI 脚本。
|
||
|
||
|
||
## TL;DR
|
||
|
||
- **自动化验收**:`./ansible/bin/verify.sh run 06-03`
|
||
- **关键前置**:按本文「前置条件」准备环境变量/Secret/入口 IP
|
||
- **成功判据**:达到本文「预期」且 playbook 断言通过
|
||
- **排障**:见本文「排障」
|
||
|
||
## 前置条件
|
||
|
||
- 已部署 openlist,并通过它聚合了至少一个云盘
|
||
- openlist 已暴露 WebDAV 接口(例如 `https://openlist.example.com/webdav`)
|
||
- 目标工作负载使用本地目录(`hostPath`)或 PVC 作为数据目录
|
||
- 至少有一台可以运行备份脚本/容器的节点(建议是控制节点或专用备份节点)
|
||
|
||
---
|
||
|
||
## 1. 设计思路总览
|
||
|
||
在 K3s 里,**“Pod 漂移”与“数据高可用”是两件事**:
|
||
|
||
- 调度器会在节点故障时重建 Pod,但**不会自动搬运宿主机本地目录的数据**;
|
||
- 对于使用 `hostPath` 的工作负载,需要额外设计“把目录同步到安全地方,再在需要时拉回来”的方案。
|
||
|
||
本篇采用的通用思路是:
|
||
|
||
1. **备份**:定期将本地目录(或 PVC 挂载点)同步到 openlist 暴露的 WebDAV(例如使用 `rclone sync`);
|
||
2. **恢复**:在节点故障或数据损坏时,通过一次性 Job 或脚本,从 WebDAV 拉回数据到本地目录,然后重启相关 Deployment。
|
||
|
||
> 这里的“自动”主要指**备份是自动的**;恢复部分推荐先做成“半自动脚本”,由你在确认告警后一键触发。
|
||
|
||
---
|
||
|
||
## 2. 备份:从本地目录到 WebDAV
|
||
|
||
### 2.1 在备份节点上配置 rclone(一次性)
|
||
|
||
在一台作为备份节点的机器(可以是 K3s 控制节点)上安装 `rclone` 并配置 WebDAV 远端。例如:
|
||
|
||
```bash
|
||
sudo dnf install -y rclone # 或其它包管理器
|
||
|
||
rclone config
|
||
# 交互过程中选择:
|
||
# - New remote: openlist-webdav
|
||
# - Storage: WebDAV
|
||
# - URL: https://openlist.example.com/webdav
|
||
# - User/Password: 按 openlist WebDAV 凭据填写
|
||
```
|
||
|
||
确认配置成功:
|
||
|
||
```bash
|
||
rclone ls openlist-webdav:
|
||
```
|
||
|
||
### 2.2 使用 CronJob 定期备份(集群内)
|
||
|
||
如果你希望在 K3s 内部完成备份,可以将 `rclone` 封装到容器镜像中。**唯一真源(CronJob)**:[`ansible/files/06-03/app-data-backup-cronjob.yaml`](../ansible/files/06-03/app-data-backup-cronjob.yaml)。
|
||
|
||
应用方式:
|
||
|
||
```bash
|
||
kubectl apply -f ansible/files/06-03/app-data-backup-cronjob.yaml
|
||
```
|
||
|
||
> 提示:如果你的应用使用的是 PVC,而不是 `hostPath`,则可以将 `volumes.hostPath` 改为 `persistentVolumeClaim`。
|
||
|
||
---
|
||
|
||
## 3. 恢复:从 WebDAV 回灌到本地目录
|
||
|
||
### 3.1 恢复 Job 示例
|
||
|
||
当某个节点发生故障、你将应用调度到另一节点后,可以通过一次性 Job 拉回备份。**唯一真源(Job)**:[`ansible/files/06-03/app-data-restore-job.yaml`](../ansible/files/06-03/app-data-restore-job.yaml)。
|
||
|
||
执行恢复:
|
||
|
||
```bash
|
||
kubectl apply -f ansible/files/06-03/app-data-restore-job.yaml
|
||
kubectl -n default logs -f job/app-data-restore
|
||
```
|
||
|
||
确认恢复成功后,可以删除该 Job:
|
||
|
||
```bash
|
||
kubectl delete job app-data-restore -n default
|
||
```
|
||
|
||
### 3.2 重启相关 Deployment
|
||
|
||
数据恢复到位后,你可以重启对应的 Deployment,让 Pod 在新节点使用恢复后的目录启动:
|
||
|
||
```bash
|
||
kubectl rollout restart deploy your-app-deployment -n default
|
||
```
|
||
|
||
> 建议在恢复前先确保 Deployment 已限制在目标节点运行(例如使用 `nodeSelector` 或 `affinity`),避免 Pod 同时在多个节点竞争同一份本地目录。
|
||
|
||
---
|
||
|
||
## 4. 与节点故障联动的思路(概念级)
|
||
|
||
本篇不实现完整的“节点故障 → 自动恢复数据 → 自动重启 Pod”控制器,但给出一个可以与监控/告警结合的思路:
|
||
|
||
- **监控层**:使用 Prometheus + Alertmanager 监控 `Node` 状态,当某个节点长时间 `NotReady` 或 `Unreachable` 时触发告警;
|
||
- **告警处理层**:Alertmanager 将告警发送到一个 Webhook(或 GitLab CI Job),该 Webhook 执行脚本:
|
||
- 将故障节点 `cordon` / `drain`;
|
||
- 在目标节点上执行一次“恢复 Job”(参考上文 `app-data-restore.yaml`);
|
||
- 最后 `kubectl rollout restart` 相关 Deployment;
|
||
- **人工兜底**:初期建议先“收到告警后人工执行脚本”,确认流程可靠后,再考虑部分自动化。
|
||
|
||
这样可以在不引入自定义 Controller/Operator 的前提下,实现一个“**监控 + 脚本驱动的半自动恢复**”方案。
|
||
|
||
---
|
||
|
||
## 5. 适用场景与不适用场景
|
||
|
||
**适用:**
|
||
|
||
- 重要性中等,但暂时无法改用 NFS/PV/PVC 的业务数据目录;
|
||
- 需要一个“万一节点坏了还能从云盘拉回来”的兜底方案;
|
||
- 家庭实验室/小规模集群,接受手动确认/触发恢复脚本。
|
||
|
||
**不适用:**
|
||
|
||
- 严格生产环境的强一致/低 RPO/RTO 场景(建议使用成熟的存储方案和专业备份系统);
|
||
- 不允许依赖外部 WebDAV/网盘服务稳定性的关键业务。
|
||
|
||
---
|
||
|
||
## 6. 关联文档
|
||
|
||
- `05-06-openlist挂载网盘与自动备份.md`:介绍 openlist 与网盘聚合、基础备份 CronJob 示例。
|
||
- `03-06-k3s-使用nfs存储.md`:更推荐的共享存储方案,适合重要业务数据。
|
||
- `06-02-运维小结.md`:运维/备份总体建议。
|
||
|
||
## 排障
|
||
|
||
- **先看 playbook 输出**:失败时先定位是 deploy/wait/http_check 哪一步。
|
||
- **集群侧总览**:`kubectl get nodes -o wide`、`kubectl -n kube-system get pods -o wide`。
|
||
- **事件与日志**:`kubectl -n <ns> describe ...`、`kubectl -n <ns> logs ... --tail=200`。
|