apiVersion: batch/v1 kind: CronJob metadata: name: postgres-backup namespace: veza-production labels: app: postgres-backup component: backup spec: # Run daily at 3 AM schedule: "0 3 * * *" successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 3 concurrencyPolicy: Forbid jobTemplate: spec: template: metadata: labels: app: postgres-backup spec: restartPolicy: OnFailure containers: - name: postgres-backup image: postgres:15-alpine command: - /bin/sh - -c - | set -e BACKUP_DIR="/backups/postgres" BACKUP_FILE="${BACKUP_DIR}/veza_db_$(date +%Y%m%d_%H%M%S).dump" RETENTION_DAYS=${BACKUP_RETENTION_DAYS:-30} echo "Starting backup at $(date)" # Create backup directory mkdir -p "${BACKUP_DIR}" # Create backup using pg_dump with custom format (compressed) PGPASSWORD="${POSTGRES_PASSWORD}" pg_dump \ -h "${POSTGRES_HOST}" \ -p "${POSTGRES_PORT:-5432}" \ -U "${POSTGRES_USER}" \ -d "${POSTGRES_DB}" \ -F c \ -f "${BACKUP_FILE}" # Verify backup was created if [ ! -f "${BACKUP_FILE}" ]; then echo "ERROR: Backup file was not created!" exit 1 fi BACKUP_SIZE=$(du -h "${BACKUP_FILE}" | cut -f1) echo "Backup created successfully: ${BACKUP_FILE} (${BACKUP_SIZE})" # Cleanup old backups echo "Cleaning up backups older than ${RETENTION_DAYS} days..." find "${BACKUP_DIR}" -name "veza_db_*.dump" -type f -mtime +${RETENTION_DAYS} -delete # List remaining backups echo "Remaining backups:" ls -lh "${BACKUP_DIR}" || true # Optional: Upload to S3 or other storage if [ -n "${S3_BUCKET}" ] && [ -n "${AWS_ACCESS_KEY_ID}" ] && [ -n "${AWS_SECRET_ACCESS_KEY}" ]; then echo "Uploading backup to S3..." # Install aws-cli if not available (alpine) apk add --no-cache aws-cli || true aws s3 cp "${BACKUP_FILE}" "s3://${S3_BUCKET}/postgres-backups/$(basename ${BACKUP_FILE})" || echo "S3 upload failed, continuing..." fi echo "Backup completed at $(date)" env: - name: POSTGRES_HOST valueFrom: secretKeyRef: name: veza-secrets key: postgres-host - name: POSTGRES_PORT value: "5432" - name: POSTGRES_USER valueFrom: secretKeyRef: name: veza-secrets key: postgres-user - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: veza-secrets key: postgres-password - name: POSTGRES_DB valueFrom: secretKeyRef: name: veza-secrets key: postgres-db - name: BACKUP_RETENTION_DAYS value: "30" - name: S3_BUCKET valueFrom: secretKeyRef: name: veza-secrets key: s3-backup-bucket optional: true - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: name: veza-secrets key: aws-access-key-id optional: true - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: name: veza-secrets key: aws-secret-access-key optional: true volumeMounts: - name: backup-storage mountPath: /backups resources: requests: cpu: "200m" memory: "256Mi" limits: cpu: "1000m" memory: "1Gi" volumes: - name: backup-storage persistentVolumeClaim: claimName: postgres-backup-storage --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: postgres-backup-storage namespace: veza-production spec: accessModes: - ReadWriteOnce resources: requests: storage: 100Gi