From af365221f7014beb8f5aea136fe04507f48f4598 Mon Sep 17 00:00:00 2001 From: Hera Zhao Date: Wed, 8 Apr 2026 22:14:35 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=AF=8F=E6=97=A5=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=A4=87=E4=BB=BD=E6=95=B0=E6=8D=AE=E5=BA=93=E5=88=B0=20MinIO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CronJob: daily-minio-backup, 每天 UTC 3:00 执行 - 备份 SQLite DB 到 minio-api.oci.euphon.net/oil-backups/ - 文件名: oil_calculator_YYYYMMDD.db - 滚动保留最近 30 份,自动删除旧备份 - 使用 Python minio SDK 上传 Co-Authored-By: Claude Opus 4.6 (1M context) --- deploy/minio-backup-cronjob.yaml | 96 ++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 deploy/minio-backup-cronjob.yaml diff --git a/deploy/minio-backup-cronjob.yaml b/deploy/minio-backup-cronjob.yaml new file mode 100644 index 0000000..4e4c465 --- /dev/null +++ b/deploy/minio-backup-cronjob.yaml @@ -0,0 +1,96 @@ +apiVersion: v1 +kind: Secret +metadata: + name: minio-backup-creds + namespace: oil-calculator +type: Opaque +stringData: + MINIO_ALIAS: "oci" + MINIO_URL: "https://minio-api.oci.euphon.net" + MINIO_ACCESS_KEY: "admin" + MINIO_SECRET_KEY: "HpYMIVH0WN79VkzF4L4z8Zx1" + MINIO_BUCKET: "oil-backups" +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: daily-minio-backup + namespace: oil-calculator +spec: + schedule: "0 3 * * *" # Daily at 3:00 UTC + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 2 + jobTemplate: + spec: + template: + spec: + containers: + - name: backup + image: registry.oci.euphon.net/oil-calculator:latest + command: + - sh + - -c + - | + set -e + DATE=$(date +%Y%m%d) + export BACKUP_FILE="oil_calculator_${DATE}.db" + + echo "=== Oil Calculator Daily Backup ===" + echo "Date: ${DATE}" + + # 1. Copy SQLite database (app does WAL checkpoint every 5min) + cp /data/oil_calculator.db /tmp/${BACKUP_FILE} + SIZE=$(du -h /tmp/${BACKUP_FILE} | cut -f1) + echo "Backup created: ${BACKUP_FILE} (${SIZE})" + + # 2. Upload to minio and cleanup using Python minio SDK + pip install -q minio 2>/dev/null + cat > /tmp/upload_backup.py << 'PYEOF' + import os + from minio import Minio + url = os.environ['MINIO_URL'].replace('https://','').replace('http://','') + client = Minio(url, access_key=os.environ['MINIO_ACCESS_KEY'], secret_key=os.environ['MINIO_SECRET_KEY'], secure='https' in os.environ['MINIO_URL']) + bucket = os.environ['MINIO_BUCKET'] + bf = os.environ['BACKUP_FILE'] + client.fput_object(bucket, bf, '/tmp/' + bf) + print('Uploaded:', bf) + objs = sorted(client.list_objects(bucket, prefix='oil_calculator_'), key=lambda o: o.object_name, reverse=True) + for o in objs[30:]: + client.remove_object(bucket, o.object_name) + print('Deleted:', o.object_name) + print('Total backups:', min(len(objs), 30)) + PYEOF + python3 /tmp/upload_backup.py + echo "=== Done ===" + env: + - name: MINIO_URL + valueFrom: + secretKeyRef: + name: minio-backup-creds + key: MINIO_URL + - name: MINIO_ACCESS_KEY + valueFrom: + secretKeyRef: + name: minio-backup-creds + key: MINIO_ACCESS_KEY + - name: MINIO_SECRET_KEY + valueFrom: + secretKeyRef: + name: minio-backup-creds + key: MINIO_SECRET_KEY + - name: MINIO_BUCKET + valueFrom: + secretKeyRef: + name: minio-backup-creds + key: MINIO_BUCKET + volumeMounts: + - name: data + mountPath: /data + readOnly: true + volumes: + - name: data + persistentVolumeClaim: + claimName: oil-calculator-data + restartPolicy: OnFailure + imagePullSecrets: + - name: regcred