{{- if .Values.backup.enabled }} apiVersion: batch/v1 kind: CronJob metadata: name: {{ include "phpmyadmin-nginx.fullname" . }}-backup labels: {{- include "phpmyadmin-nginx.labels" . | nindent 4 }} app.kubernetes.io/component: backup spec: schedule: {{ .Values.backup.schedule | quote }} successfulJobsHistoryLimit: {{ .Values.backup.successfulJobsHistoryLimit }} failedJobsHistoryLimit: {{ .Values.backup.failedJobsHistoryLimit }} concurrencyPolicy: {{ .Values.backup.concurrencyPolicy }} suspend: {{ .Values.backup.suspend }} jobTemplate: spec: backoffLimit: {{ .Values.backup.backoffLimit }} template: metadata: labels: {{- include "phpmyadmin-nginx.selectorLabels" . | nindent 12 }} app.kubernetes.io/component: backup {{- with .Values.backup.podAnnotations }} annotations: {{- toYaml . | nindent 12 }} {{- end }} spec: restartPolicy: OnFailure {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 12 }} {{- end }} serviceAccountName: {{ include "phpmyadmin-nginx.serviceAccountName" . }} securityContext: fsGroup: 999 runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: mysql-backup image: "{{ .Values.backup.image.registry }}/{{ .Values.backup.image.repository }}:{{ .Values.backup.image.tag }}" imagePullPolicy: {{ .Values.backup.image.pullPolicy }} securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 999 env: - name: MYSQL_HOST value: {{ .Values.backup.mysql.host | quote }} - name: MYSQL_PORT value: {{ .Values.backup.mysql.port | quote }} - name: MYSQL_USER valueFrom: secretKeyRef: name: {{ .Values.backup.mysql.existingSecret | default (printf "%s-backup" (include "phpmyadmin-nginx.fullname" .)) }} key: {{ .Values.backup.mysql.userKey | default "mysql-user" }} - name: MYSQL_PASSWORD valueFrom: secretKeyRef: name: {{ .Values.backup.mysql.existingSecret | default (printf "%s-backup" (include "phpmyadmin-nginx.fullname" .)) }} key: {{ .Values.backup.mysql.passwordKey | default "mysql-password" }} - name: BACKUP_TIMESTAMP value: $(date +%Y%m%d_%H%M%S) {{- if .Values.backup.databases }} - name: DATABASES value: {{ join " " .Values.backup.databases | quote }} {{- end }} {{- if .Values.backup.compression.enabled }} - name: COMPRESSION_ENABLED value: "true" - name: COMPRESSION_LEVEL value: {{ .Values.backup.compression.level | quote }} {{- end }} {{- if .Values.backup.retention.enabled }} - name: RETENTION_DAYS value: {{ .Values.backup.retention.days | quote }} {{- end }} command: - /bin/bash - -c - | set -euo pipefail BACKUP_DIR="{{ .Values.backup.destinationPath }}" TIMESTAMP=$(date +%Y%m%d_%H%M%S) DATE_DIR=$(date +%Y%m%d) echo "=== MySQL Backup Started at $(date) ===" echo "Backup destination: ${BACKUP_DIR}/${DATE_DIR}" # Create backup directory mkdir -p "${BACKUP_DIR}/${DATE_DIR}" # Function to backup a database backup_database() { local db=$1 local backup_file="${BACKUP_DIR}/${DATE_DIR}/${db}_${TIMESTAMP}.sql" echo "Backing up database: ${db}" mysqldump \ -h "${MYSQL_HOST}" \ -P "${MYSQL_PORT}" \ -u "${MYSQL_USER}" \ -p"${MYSQL_PASSWORD}" \ --single-transaction \ --quick \ --lock-tables=false \ --routines \ --triggers \ --events \ "${db}" > "${backup_file}" {{- if .Values.backup.compression.enabled }} echo "Compressing backup: ${db}" gzip -{{ .Values.backup.compression.level }} "${backup_file}" backup_file="${backup_file}.gz" {{- end }} # Verify backup file if [ -f "${backup_file}" ]; then size=$(du -h "${backup_file}" | cut -f1) echo "✓ Backup completed: ${backup_file} (${size})" else echo "✗ Backup failed: ${backup_file}" return 1 fi } # Backup specified databases or all databases {{- if .Values.backup.databases }} for db in ${DATABASES}; do backup_database "${db}" || echo "Warning: Failed to backup ${db}" done {{- else }} # Get all databases except system databases DATABASES=$(mysql \ -h "${MYSQL_HOST}" \ -P "${MYSQL_PORT}" \ -u "${MYSQL_USER}" \ -p"${MYSQL_PASSWORD}" \ -N -B -e "SHOW DATABASES" | \ grep -Ev '^(information_schema|performance_schema|mysql|sys)$') for db in ${DATABASES}; do backup_database "${db}" || echo "Warning: Failed to backup ${db}" done {{- end }} {{- if .Values.backup.retention.enabled }} # Cleanup old backups echo "Cleaning up backups older than {{ .Values.backup.retention.days }} days" find "${BACKUP_DIR}" -type f -name "*.sql*" -mtime +{{ .Values.backup.retention.days }} -delete find "${BACKUP_DIR}" -type d -empty -delete {{- end }} # Summary echo "=== Backup Summary ===" echo "Total backup size:" du -sh "${BACKUP_DIR}/${DATE_DIR}" echo "Backup files:" ls -lh "${BACKUP_DIR}/${DATE_DIR}" echo "=== MySQL Backup Completed at $(date) ===" resources: {{- toYaml .Values.backup.resources | nindent 14 }} volumeMounts: - name: backup-storage mountPath: {{ .Values.backup.destinationPath }} - name: tmp mountPath: /tmp volumes: - name: backup-storage {{- if .Values.backup.nfs.enabled }} nfs: server: {{ .Values.backup.nfs.server }} path: {{ .Values.backup.nfs.path }} {{- if .Values.backup.nfs.readOnly }} readOnly: false {{- end }} {{- else }} persistentVolumeClaim: claimName: {{ .Values.backup.existingClaim | default (printf "%s-backup" (include "phpmyadmin-nginx.fullname" .)) }} {{- end }} - name: tmp emptyDir: {} {{- with .Values.backup.nodeSelector }} nodeSelector: {{- toYaml . | nindent 12 }} {{- end }} {{- with .Values.backup.affinity }} affinity: {{- toYaml . | nindent 12 }} {{- end }} {{- with .Values.backup.tolerations }} tolerations: {{- toYaml . | nindent 12 }} {{- end }} {{- end }}