feat: add Freeleaps PVC backup job with ArgoCD deployment

- Add Python backup script with PST timezone support
- Create Helm Chart for flexible configuration
- Add ArgoCD Application for GitOps deployment
- Include comprehensive documentation and build scripts
- Support incremental snapshots for cost efficiency
- Process PVCs independently with error handling
- Add .gitignore to exclude Python cache files
This commit is contained in:
Nicolas 2025-08-05 18:07:05 +08:00
parent 2bf8244370
commit a470476c71
15 changed files with 941 additions and 0 deletions

36
jobs/freeleaps-data-backup/.gitignore vendored Normal file
View File

@ -0,0 +1,36 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# Virtual environments
venv/
env/
ENV/
# IDE
.vscode/
.idea/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db

View File

@ -0,0 +1,25 @@
FROM python:3.11-slim
# Set working directory
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y \
curl \
&& rm -rf /var/lib/apt/lists/*
# Copy requirements and install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy backup script
COPY backup_script.py .
# Make script executable
RUN chmod +x backup_script.py
# Set environment variables
ENV PYTHONUNBUFFERED=1
# Run the backup script
CMD ["python", "backup_script.py"]

View File

@ -0,0 +1,277 @@
# Freeleaps PVC Backup Job
This job creates daily snapshots of critical PVCs in the Freeleaps production environment using Azure Disk CSI Snapshot feature.
## Overview
The backup job runs daily at 00:00 PST (Pacific Standard Time) and creates snapshots for the following PVCs:
- `gitea-shared-storage` in namespace `freeleaps-prod`
- `data-freeleaps-prod-gitea-postgresql-ha-postgresql-0` in namespace `freeleaps-prod`
## Components
- **backup_script.py**: Python script that creates snapshots and monitors their status
- **Dockerfile**: Container image definition
- **build.sh**: Script to build the Docker image
- **deploy-argocd.sh**: Script to deploy via ArgoCD
- **helm-pkg/**: Helm Chart for Kubernetes deployment
- **argo-app/**: ArgoCD Application configuration
## Features
- ✅ Creates snapshots with timestamp-based naming (YYYYMMDD format)
- ✅ Uses PST timezone for snapshot naming
- ✅ Monitors snapshot status until ready
- ✅ Comprehensive logging to console
- ✅ Error handling and retry logic
- ✅ RBAC permissions for secure operation
- ✅ Resource limits and security context
- ✅ Concurrency control (prevents overlapping jobs)
- ✅ Helm Chart for flexible configuration
- ✅ ArgoCD integration for GitOps deployment
- ✅ Incremental snapshots for cost efficiency
## Building and Deployment
### Option 1: ArgoCD Deployment (Recommended)
#### 1. Build and Push Docker Image
```bash
# Make build script executable
chmod +x build.sh
# Build the image
./build.sh
# Push to registry
docker push freeleaps-registry.azurecr.io/freeleaps-pvc-backup:latest
```
#### 2. Deploy via ArgoCD
```bash
# Deploy ArgoCD Application
./deploy-argocd.sh
```
#### 3. Monitor in ArgoCD
```bash
# Check ArgoCD application status
kubectl get applications -n freeleaps-devops-system
# Access ArgoCD UI
kubectl port-forward svc/argocd-server -n freeleaps-devops-system 8080:443
```
Then visit `https://localhost:8080` in your browser.
### Option 2: Direct Helm Deployment
#### 1. Build and Push Docker Image
```bash
# Build the image
./build.sh
# Push to registry
docker push freeleaps-registry.azurecr.io/freeleaps-pvc-backup:latest
```
#### 2. Deploy with Helm
```bash
# Deploy using Helm Chart
helm install freeleaps-data-backup ./helm-pkg/freeleaps-data-backup \
--values helm-pkg/freeleaps-data-backup/values.prod.yaml \
--namespace freeleaps-prod \
--create-namespace
```
## Monitoring
### Check CronJob Status
```bash
kubectl get cronjobs -n freeleaps-prod
```
### Check Job History
```bash
kubectl get jobs -n freeleaps-prod
```
### View Job Logs
```bash
# Get the latest job name
kubectl get jobs -n freeleaps-prod --sort-by=.metadata.creationTimestamp
# View logs
kubectl logs -n freeleaps-prod job/freeleaps-data-backup-<timestamp>
```
### Check Snapshots
```bash
kubectl get volumesnapshots -n freeleaps-prod
```
## Configuration
### Schedule
The job runs daily at 00:00 PST. To modify the schedule, edit the `cronjob.schedule` field in `helm-pkg/freeleaps-data-backup/values.prod.yaml`:
```yaml
cronjob:
schedule: "0 8 * * *" # UTC 08:00 = PST 00:00
```
### PVCs to Backup
To add or remove PVCs, modify the `backup.pvcs` list in `helm-pkg/freeleaps-data-backup/values.prod.yaml`:
```yaml
backup:
pvcs:
- "gitea-shared-storage"
- "data-freeleaps-prod-gitea-postgresql-ha-postgresql-0"
# Add more PVCs here
```
### Snapshot Class
The job uses the `csi-azuredisk-vsc` snapshot class with incremental snapshots enabled. This can be modified in `helm-pkg/freeleaps-data-backup/values.prod.yaml`:
```yaml
backup:
snapshotClass: "csi-azuredisk-vsc"
```
### Resource Limits
Resource limits can be configured in `helm-pkg/freeleaps-data-backup/values.prod.yaml`:
```yaml
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "500m"
```
## How It Works
### Snapshot Naming
Snapshots are named using the format: `{PVC_NAME}-snapshot-{YYYYMMDD}`
Examples:
- `gitea-shared-storage-snapshot-20250805`
- `data-freeleaps-prod-gitea-postgresql-ha-postgresql-0-snapshot-20250805`
### Processing Flow
1. **PVC Verification**: Each PVC is verified to exist before processing
2. **Snapshot Creation**: Individual snapshots are created for each PVC
3. **Status Monitoring**: Each snapshot is monitored until ready
4. **Independent Processing**: PVCs are processed independently (one failure doesn't affect others)
### Incremental Snapshots
The job uses Azure Disk CSI incremental snapshots, which:
- Save storage costs by only storing changed data blocks
- Create faster than full snapshots
- Maintain full recovery capability
## Troubleshooting
### Common Issues
1. **Permission Denied**: Ensure RBAC is properly configured
2. **PVC Not Found**: Verify PVC names and namespace
3. **Snapshot Creation Failed**: Check Azure Disk CSI driver status
4. **Job Timeout**: Increase timeout in the values file if needed
### Debug Mode
To run the script locally for testing:
```bash
# Install dependencies
pip install -r requirements.txt
# Run with local kubeconfig
python3 backup_script.py
```
## Security
- The job runs with minimal required permissions
- Non-root user execution
- Dropped capabilities
- Resource limits enforced
- No privileged access
## Maintenance
### Cleanup Old Snapshots
Old snapshots can be cleaned up manually:
```bash
# List all snapshots
kubectl get volumesnapshots -n freeleaps-prod
# Delete specific snapshot
kubectl delete volumesnapshot <snapshot-name> -n freeleaps-prod
# Delete snapshots older than 30 days (example)
kubectl get volumesnapshots -n freeleaps-prod -o jsonpath='{.items[?(@.metadata.creationTimestamp<"2024-07-05T00:00:00Z")].metadata.name}' | xargs kubectl delete volumesnapshot -n freeleaps-prod
```
### Updating Configuration
To update the backup configuration:
1. Modify the appropriate values file in `helm-pkg/freeleaps-data-backup/`
2. Commit and push changes to the repository
3. ArgoCD will automatically sync the changes
4. Or manually upgrade with Helm: `helm upgrade freeleaps-data-backup ./helm-pkg/freeleaps-data-backup --values values.prod.yaml`
## Backup Data
### What Gets Backed Up
- **gitea-shared-storage**: Gitea repository data, attachments, and configuration
- **data-freeleaps-prod-gitea-postgresql-ha-postgresql-0**: PostgreSQL database data
### Recovery
To restore from a snapshot:
```bash
# Create a PVC from snapshot
kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: restored-pvc
namespace: freeleaps-prod
spec:
dataSource:
name: <snapshot-name>
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
EOF
```

View File

@ -0,0 +1,32 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: freeleaps-data-backup
namespace: freeleaps-devops-system
labels:
app: freeleaps-data-backup
component: backup
environment: production
spec:
destination:
name: ""
namespace: freeleaps-prod
server: https://kubernetes.default.svc
source:
path: jobs/freeleaps-data-backup/helm-pkg/freeleaps-data-backup
repoURL: https://freeleaps@dev.azure.com/freeleaps/freeleaps-ops/_git/freeleaps-ops
targetRevision: HEAD
helm:
parameters: []
valueFiles:
- values.prod.yaml
sources: []
project: freeleaps-data-backup
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground
- PruneLast=true

View File

@ -0,0 +1,227 @@
#!/usr/bin/env python3
"""
PVC Backup Script for Freeleaps Production Environment
Creates snapshots for specified PVCs and monitors their status
"""
import os
import sys
import yaml
import time
import logging
from datetime import datetime, timezone, timedelta
from kubernetes import client, config
from kubernetes.client.rest import ApiException
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(sys.stdout)
]
)
logger = logging.getLogger(__name__)
class PVCBackupManager:
def __init__(self):
"""Initialize the backup manager with Kubernetes client"""
try:
# Load in-cluster config when running in Kubernetes
config.load_incluster_config()
logger.info("Loaded in-cluster Kubernetes configuration")
except config.ConfigException:
# Fallback to kubeconfig for local development
try:
config.load_kube_config()
logger.info("Loaded kubeconfig for local development")
except config.ConfigException:
logger.error("Failed to load Kubernetes configuration")
sys.exit(1)
self.api_client = client.ApiClient()
self.snapshot_api = client.CustomObjectsApi(self.api_client)
self.core_api = client.CoreV1Api(self.api_client)
# Backup configuration
self.namespace = os.getenv("BACKUP_NAMESPACE", "freeleaps-prod")
self.pvcs_to_backup = [
"gitea-shared-storage",
"data-freeleaps-prod-gitea-postgresql-ha-postgresql-0"
]
self.snapshot_class = os.getenv("SNAPSHOT_CLASS", "csi-azuredisk-vsc")
self.timeout = int(os.getenv("TIMEOUT", "300"))
def get_pst_date(self):
"""Get current date in PST timezone (UTC-8)"""
pst_tz = timezone(timedelta(hours=-8))
return datetime.now(pst_tz).strftime("%Y%m%d")
def generate_snapshot_name(self, pvc_name, timestamp):
"""Generate snapshot name with timestamp"""
return f"{pvc_name}-snapshot-{timestamp}"
def create_snapshot_yaml(self, pvc_name, snapshot_name):
"""Create VolumeSnapshot YAML configuration"""
snapshot_yaml = {
"apiVersion": "snapshot.storage.k8s.io/v1",
"kind": "VolumeSnapshot",
"metadata": {
"name": snapshot_name,
"namespace": self.namespace
},
"spec": {
"volumeSnapshotClassName": self.snapshot_class,
"source": {
"persistentVolumeClaimName": pvc_name
}
}
}
return snapshot_yaml
def apply_snapshot(self, snapshot_yaml):
"""Apply snapshot to Kubernetes cluster"""
try:
logger.info(f"Creating snapshot: {snapshot_yaml['metadata']['name']}")
# Create the snapshot
result = self.snapshot_api.create_namespaced_custom_object(
group="snapshot.storage.k8s.io",
version="v1",
namespace=self.namespace,
plural="volumesnapshots",
body=snapshot_yaml
)
logger.info(f"Successfully created snapshot: {result['metadata']['name']}")
return result
except ApiException as e:
logger.error(f"Failed to create snapshot: {e}")
return None
def wait_for_snapshot_ready(self, snapshot_name, timeout=None):
if timeout is None:
timeout = self.timeout
"""Wait for snapshot to be ready with timeout"""
logger.info(f"Waiting for snapshot {snapshot_name} to be ready...")
start_time = time.time()
while time.time() - start_time < timeout:
try:
# Get snapshot status
snapshot = self.snapshot_api.get_namespaced_custom_object(
group="snapshot.storage.k8s.io",
version="v1",
namespace=self.namespace,
plural="volumesnapshots",
name=snapshot_name
)
# Check if snapshot is ready
if snapshot.get('status', {}).get('readyToUse', False):
logger.info(f"Snapshot {snapshot_name} is ready!")
return True
# Check for error conditions
error = snapshot.get('status', {}).get('error', {})
if error:
logger.error(f"Snapshot {snapshot_name} failed: {error}")
return False
logger.info(f"Snapshot {snapshot_name} still processing...")
time.sleep(10)
except ApiException as e:
logger.error(f"Error checking snapshot status: {e}")
return False
logger.error(f"Timeout waiting for snapshot {snapshot_name} to be ready")
return False
def verify_pvc_exists(self, pvc_name):
"""Verify that PVC exists in the namespace"""
try:
pvc = self.core_api.read_namespaced_persistent_volume_claim(
name=pvc_name,
namespace=self.namespace
)
logger.info(f"Found PVC: {pvc_name}")
return True
except ApiException as e:
if e.status == 404:
logger.error(f"PVC {pvc_name} not found in namespace {self.namespace}")
else:
logger.error(f"Error checking PVC {pvc_name}: {e}")
return False
def run_backup(self):
"""Main backup process"""
logger.info("Starting PVC backup process...")
timestamp = self.get_pst_date()
successful_backups = []
failed_backups = []
for pvc_name in self.pvcs_to_backup:
logger.info(f"Processing PVC: {pvc_name}")
# Verify PVC exists
if not self.verify_pvc_exists(pvc_name):
failed_backups.append(pvc_name)
continue
# Generate snapshot name
snapshot_name = self.generate_snapshot_name(pvc_name, timestamp)
# Create snapshot YAML
snapshot_yaml = self.create_snapshot_yaml(pvc_name, snapshot_name)
# Apply snapshot
result = self.apply_snapshot(snapshot_yaml)
if not result:
failed_backups.append(pvc_name)
continue
# Wait for snapshot to be ready
if self.wait_for_snapshot_ready(snapshot_name):
successful_backups.append(pvc_name)
logger.info(f"Backup completed successfully for PVC: {pvc_name}")
else:
failed_backups.append(pvc_name)
logger.error(f"Backup failed for PVC: {pvc_name}")
# Summary
logger.info("=== Backup Summary ===")
logger.info(f"Successful backups: {len(successful_backups)}")
logger.info(f"Failed backups: {len(failed_backups)}")
if successful_backups:
logger.info(f"Successfully backed up: {', '.join(successful_backups)}")
if failed_backups:
logger.error(f"Failed to backup: {', '.join(failed_backups)}")
return False
logger.info("All backups completed successfully!")
return True
def main():
"""Main entry point"""
try:
backup_manager = PVCBackupManager()
success = backup_manager.run_backup()
if success:
logger.info("Backup job completed successfully")
sys.exit(0)
else:
logger.error("Backup job completed with errors")
sys.exit(1)
except Exception as e:
logger.error(f"Unexpected error: {e}")
sys.exit(1)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,24 @@
#!/bin/bash
# Build script for Freeleaps PVC Backup Docker image
set -e
# Configuration
IMAGE_NAME="freeleaps-pvc-backup"
REGISTRY="freeleaps-registry.azurecr.io"
TAG="${1:-latest}"
echo "Building Freeleaps PVC Backup Docker image..."
echo "Image: ${REGISTRY}/${IMAGE_NAME}:${TAG}"
# Build the Docker image
docker buildx build \
--platform linux/amd64 \
-f Dockerfile \
-t "${REGISTRY}/${IMAGE_NAME}:${TAG}" \
.
echo "Build completed successfully!"
echo "To push the image, run:"
echo "docker push ${REGISTRY}/${IMAGE_NAME}:${TAG}"

View File

@ -0,0 +1,26 @@
#!/bin/bash
# Deploy script for Freeleaps PVC Backup to ArgoCD
set -e
echo "Deploying Freeleaps PVC Backup to ArgoCD..."
# Apply ArgoCD Application
echo "Applying ArgoCD Application configuration..."
kubectl apply -f argo-app/application.yaml
echo "ArgoCD Application deployed successfully!"
echo ""
echo "To check the status:"
echo "kubectl get applications -n freeleaps-devops-system"
echo ""
echo "To view ArgoCD UI:"
echo "kubectl port-forward svc/argocd-server -n freeleaps-devops-system 8080:443"
echo ""
echo "To check the CronJob after sync:"
echo "kubectl get cronjobs -n freeleaps-prod"
echo ""
echo "To view job logs:"
echo "kubectl get jobs -n freeleaps-prod"
echo "kubectl logs -n freeleaps-prod job/freeleaps-data-backup-<timestamp>"

View File

@ -0,0 +1,17 @@
apiVersion: v2
name: freeleaps-data-backup
description: Freeleaps PVC Backup CronJob for production environment
type: application
version: 0.1.0
appVersion: "1.0.0"
keywords:
- backup
- pvc
- snapshot
- cronjob
home: https://freeleaps.com
sources:
- https://freeleaps@dev.azure.com/freeleaps/freeleaps-ops/_git/freeleaps-ops
maintainers:
- name: Freeleaps DevOps Team
email: devops@freeleaps.com

View File

@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "freeleaps-data-backup.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "freeleaps-data-backup.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "freeleaps-data-backup.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "freeleaps-data-backup.labels" -}}
helm.sh/chart: {{ include "freeleaps-data-backup.chart" . }}
{{ include "freeleaps-data-backup.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "freeleaps-data-backup.selectorLabels" -}}
app.kubernetes.io/name: {{ include "freeleaps-data-backup.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "freeleaps-data-backup.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "freeleaps-data-backup.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,54 @@
{{- if .Values.cronjob.enabled -}}
apiVersion: batch/v1
kind: CronJob
metadata:
name: {{ include "freeleaps-data-backup.fullname" . }}
namespace: {{ .Values.backup.namespace }}
labels:
app: {{ include "freeleaps-data-backup.name" . }}
component: backup
{{- include "freeleaps-data-backup.labels" . | nindent 4 }}
{{- with .Values.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
schedule: {{ .Values.cronjob.schedule | quote }}
concurrencyPolicy: {{ .Values.cronjob.concurrencyPolicy }}
successfulJobsHistoryLimit: {{ .Values.cronjob.successfulJobsHistoryLimit }}
failedJobsHistoryLimit: {{ .Values.cronjob.failedJobsHistoryLimit }}
jobTemplate:
spec:
template:
metadata:
labels:
app: {{ include "freeleaps-data-backup.name" . }}
component: backup
{{- include "freeleaps-data-backup.labels" . | nindent 12 }}
spec:
{{- if .Values.serviceAccount.enabled }}
serviceAccountName: {{ .Values.serviceAccount.name }}
{{- end }}
restartPolicy: {{ .Values.cronjob.restartPolicy }}
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 12 }}
{{- end }}
containers:
- name: backup
image: "{{ .Values.global.imageRegistry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
- name: TZ
value: "UTC"
- name: BACKUP_NAMESPACE
value: {{ .Values.backup.namespace | quote }}
- name: SNAPSHOT_CLASS
value: {{ .Values.backup.snapshotClass | quote }}
- name: TIMEOUT
value: {{ .Values.backup.timeout | quote }}
resources:
{{- toYaml .Values.resources | nindent 14 }}
securityContext:
{{- toYaml .Values.securityContext | nindent 14 }}
{{- end }}

View File

@ -0,0 +1,37 @@
{{- if .Values.rbac.enabled -}}
{{- if .Values.rbac.create -}}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "freeleaps-data-backup.fullname" . }}-role
labels:
app: {{ include "freeleaps-data-backup.name" . }}
component: backup
{{- include "freeleaps-data-backup.labels" . | nindent 4 }}
rules:
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshots", "volumesnapshotclasses"]
verbs: ["get", "list", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "freeleaps-data-backup.fullname" . }}-rolebinding
labels:
app: {{ include "freeleaps-data-backup.name" . }}
component: backup
{{- include "freeleaps-data-backup.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "freeleaps-data-backup.fullname" . }}-role
subjects:
- kind: ServiceAccount
name: {{ .Values.serviceAccount.name }}
namespace: {{ .Values.backup.namespace }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,17 @@
{{- if .Values.serviceAccount.enabled -}}
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.serviceAccount.name }}
namespace: {{ .Values.backup.namespace }}
labels:
app: {{ include "freeleaps-data-backup.name" . }}
component: backup
{{- include "freeleaps-data-backup.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,40 @@
# Production values for freeleaps-data-backup
# Image settings
image:
repository: freeleaps-pvc-backup
tag: "latest"
pullPolicy: Always
# CronJob settings
cronjob:
enabled: true
schedule: "0 8 * * *" # Daily at 00:00 UTC (08:00 UTC+8)
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 7
failedJobsHistoryLimit: 3
restartPolicy: OnFailure
# Resource limits for production
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "500m"
# Backup configuration for production
backup:
namespace: "freeleaps-prod"
pvcs:
- "gitea-shared-storage"
- "data-freeleaps-prod-gitea-postgresql-ha-postgresql-0"
snapshotClass: "csi-azuredisk-vsc"
timeout: 600 # 10 minutes for production
# Labels for production
labels:
environment: "production"
team: "devops"
component: "backup"

View File

@ -0,0 +1,65 @@
# Default values for freeleaps-data-backup
# This is a YAML-formatted file.
# Global settings
global:
imageRegistry: "freeleaps-registry.azurecr.io"
imagePullSecrets: []
# Image settings
image:
repository: freeleaps-pvc-backup
tag: "latest"
pullPolicy: Always
# CronJob settings
cronjob:
enabled: true
schedule: "0 8 * * *" # Daily at 00:00 UTC (08:00 UTC+8)
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 7
failedJobsHistoryLimit: 3
restartPolicy: OnFailure
# Resource limits
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
# Security context
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop:
- ALL
# RBAC settings
rbac:
enabled: true
create: true
# ServiceAccount settings
serviceAccount:
enabled: true
create: true
name: "freeleaps-backup-sa"
annotations: {}
# Backup configuration
backup:
namespace: "freeleaps-prod"
pvcs:
- "gitea-shared-storage"
- "data-freeleaps-prod-gitea-postgresql-ha-postgresql-0"
snapshotClass: "csi-azuredisk-vsc"
timeout: 300 # seconds
# Labels and annotations
labels: {}
annotations: {}

View File

@ -0,0 +1,2 @@
kubernetes==28.1.0
PyYAML==6.0.1