Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

利用 k8s+helm 实现备份有状态应用的数据 #335

Open
Bpazy opened this issue Oct 8, 2024 · 0 comments
Open

利用 k8s+helm 实现备份有状态应用的数据 #335

Bpazy opened this issue Oct 8, 2024 · 0 comments

Comments

@Bpazy
Copy link
Owner

Bpazy commented Oct 8, 2024

前言

很多服务比如 jenkins, qbittorrent, jellyfin 等等都是有状态服务,如何定期将这些数据备份到 NAS 上呢?

有几种方法:

  1. 手动定期备份
  2. 在对应的机器上创建 crontab 任务进行备份
  3. (目前采用该方法)利用 k8s cronjob 挂载对应应用的 pvc 进行备份

方法详情

方法 1

就不谈了。

方法 2

需要创建忙忙多的 shell 脚本,然后在对应机器维护好 crontab 任务。

事实上我最开始就是用这种方法的:
image

每个 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 翻译为人话,做了这些事:

  1. 迭代备份任务: 通过 .Values.backupTasks 列表中定义的每一项任务进行迭代,对每个定义的备份任务进行处理。
  2. 定义 CronJob 资源: 对于每个备份任务,创建一个 CronJob 资源。
  3. 任务配置:
  • name: CronJob 的名称由配置中的 .name 属性指定。
  • schedule: 定时计划根据 .schedule 属性设定,该属性定义了任务执行的频率。
  1. 任务模板:
  • 使用 rsync-ssh 镜像,从 ghcr.io/instrumentisto/rsync-ssh:alpine3.20 获取。
  • 定义了如何通过 SSH(不检查主机键)将数据从本地目录(挂载到 /data)同步到远程服务器的特定目录。
  • 私钥通过挂载的卷 /etc/secret-volume 提供,这个卷从一个 Kubernetes Secret 中获取,该 Secret 由 .secretName 属性指定。
  • 还有另一个卷从一个持久卷声明(PVC)挂载到 /data,由 .pvc 属性指定,这个 PVC 应该包含需要备份的数据。
  1. 容器配置:
  • 包含重启策略 OnFailure,意味着如果备份任务失败,任务会重新启动。
  • 使用两个卷挂载: 一个用于提供 SSH 私钥(只读),另一个为需要备份的数据卷。
  1. 执行的命令:
  • 任务的执行命令主要执行两步:首先通过 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 会涉及敏感信息,这里就不贴出来仓库地址了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant