-
-
Notifications
You must be signed in to change notification settings - Fork 3
Open
Description
前言
很多服务比如 jenkins, qbittorrent, jellyfin 等等都是有状态服务,如何定期将这些数据备份到 NAS 上呢?
有几种方法:
- 手动定期备份
- 在对应的机器上创建 crontab 任务进行备份
- (目前采用该方法)利用 k8s cronjob 挂载对应应用的 pvc 进行备份
方法详情
方法 1
就不谈了。
方法 2
需要创建忙忙多的 shell 脚本,然后在对应机器维护好 crontab 任务。
每个 sh 的文件内容大致如下:
#!/bin/sh
APPNAME=uptime-kuma
ARCHIVE=$APPNAME-$(date +%Y%m%d).tar.gz
APPPATH=/home/ubuntu/uptime-kuma/
STORAGE=/mnt/ServerBackups/sHan/$APPNAME/
cd $APPPATH
tar czvPf $ARCHIVE *
rsync $ARCHIVE $STORAGE
rm -rf $ARCHIVE缺点是要创建很多的 shell,crontab 还需要处理用户权限问题,总不能所有的备份都用 root 用户来进行吧,不太安全。
方法 3
注意前提,应用必须部署在 k8s 上。
可以利用 helm 模板,内容如下:
{{- range .Values.backupTasks }}
apiVersion: batch/v1
kind: CronJob
metadata:
name: {{ .name }}
spec:
schedule: "{{ .schedule }}"
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: backup-container
image: ghcr.io/instrumentisto/rsync-ssh:alpine3.20
command: ["/bin/sh"]
args:
[
"-c",
"ssh -t -o StrictHostKeyChecking=no -i /etc/secret-volume/{{ .privateKeyName }} {{ .target.server }} 'mkdir -p {{ .target.path }}'; rsync -e 'ssh -o StrictHostKeyChecking=no -i /etc/secret-volume/{{ .privateKeyName }}' -avz /data/ {{ .target.server }}:{{ .target.path }}",
]
volumeMounts:
- name: secret-volume
mountPath: /etc/secret-volume
readOnly: true
- name: pvc-to-backup
mountPath: /data
volumes:
- name: secret-volume
secret:
secretName: {{ .secretName }}
defaultMode: 0400
- name: pvc-to-backup
persistentVolumeClaim:
claimName: {{ .pvc }}
---
{{- end }}让 GPT 帮忙把 yaml 翻译为人话,做了这些事:
- 迭代备份任务: 通过 .Values.backupTasks 列表中定义的每一项任务进行迭代,对每个定义的备份任务进行处理。
- 定义 CronJob 资源: 对于每个备份任务,创建一个 CronJob 资源。
- 任务配置:
- name: CronJob 的名称由配置中的 .name 属性指定。
- schedule: 定时计划根据 .schedule 属性设定,该属性定义了任务执行的频率。
- 任务模板:
- 使用 rsync-ssh 镜像,从 ghcr.io/instrumentisto/rsync-ssh:alpine3.20 获取。
- 定义了如何通过 SSH(不检查主机键)将数据从本地目录(挂载到 /data)同步到远程服务器的特定目录。
- 私钥通过挂载的卷 /etc/secret-volume 提供,这个卷从一个 Kubernetes Secret 中获取,该 Secret 由 .secretName 属性指定。
- 还有另一个卷从一个持久卷声明(PVC)挂载到 /data,由 .pvc 属性指定,这个 PVC 应该包含需要备份的数据。
- 容器配置:
- 包含重启策略 OnFailure,意味着如果备份任务失败,任务会重新启动。
- 使用两个卷挂载: 一个用于提供 SSH 私钥(只读),另一个为需要备份的数据卷。
- 执行的命令:
- 任务的执行命令主要执行两步:首先通过 SSH 创建远程服务器上的目标目录(如果尚不存在);然后使用 rsync 通过 SSH(使用提供的私钥)将数据从本地目录同步到远程目录。
然后创建 values.yaml 文件,我这里放几个自己的备份内容:
# Helm template path: ../backup-cronjob
# Run command: helm upgrade backup-task ./backup-cronjob -f ./backup_values.yaml
backupTasks:
- name: backup-jenkins
schedule: "0 3 * * *"
pvc: jenkins-pvc-local
secretName: backup-privatekey
privateKeyName: id_rsa
target:
server: [email protected]
path: /share/ServerBackups/app/jenkins
- name: backup-vaultwarden
schedule: "0 3 * * *"
pvc: vaultwarden-pvc-local
secretName: backup-privatekey
privateKeyName: id_rsa
target:
server: [email protected]
path: /share/ServerBackups/app/vaultwarden
- name: backup-homeassistant-config
schedule: "0 3 * * *"
pvc: homeassistant-config-pvc-local
secretName: backup-privatekey
privateKeyName: id_rsa
target:
server: [email protected]
path: /share/ServerBackups/app/homeassistant/config最后执行 helm upgrade 命令来让 cronjob 任务生效:
helm upgrade backup-task ./backup-cronjob -f ./backup_values.yaml效果如下:
ziyuan@pve-ubuntu:~/k8s$ kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
backup-jenkins 0 3 * * * False 0 14h 12d
backup-vaultwarden 0 3 * * * False 0 14h 12d
backup-homeassistant-ssh 0 3 * * * False 0 14h 12d
ziyuan@pve-ubuntu:~/k8s$ kubectl get pod | grep backup
backup-vaultwarden-28805460-4blkd 0/1 Completed 0 14h
backup-jenkins-28805460-zznwn 0/1 Completed 0 14h
backup-homeassistant-config-28805976-rff2g 0/1 Completed 0 6h2m
# 远端 NAS
[/share/ServerBackups/app] # ll
total 48K
drwxrwx--- 6 admin administrators 4.0K 2024-10-08 16:54 ./
drwxrwxrwx 12 admin administrators 4.0K 2024-09-12 10:38 ../
drwxrwx--- 3 admin administrators 4.0K 2024-10-08 11:33 homeassistant/
drwxrwx--- 3 admin administrators 4.0K 2024-10-08 16:54 jellyfin/
drwxrwxr-x 21 hanziyuan my-system 4.0K 2024-09-26 17:19 jenkins/
drwxr-xr-x 6 hanziyuan my-system 4.0K 2024-06-29 10:26 vaultwarden/其他
因为备份脚本或者 yaml 会涉及敏感信息,这里就不贴出来仓库地址了。
Metadata
Metadata
Assignees
Labels
No labels
