[postgres] add backup and restore - #1086
Conversation
WalkthroughThis change refactors the PostgreSQL backup and restore system in the Helm chart. It removes custom backup scripts, Dockerfiles, and CronJobs, replacing them with native ScheduledBackup resources and updating configuration to use more generic, cloud-agnostic parameters. Documentation and schema are updated, and version references are incremented. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Helm
participant Kubernetes API
participant CNPG Operator
User->>Helm: Install/upgrade postgres chart with backup/bootstrap enabled
Helm->>Kubernetes API: Apply cluster CRD with backup/bootstrap config
Helm->>Kubernetes API: Apply ScheduledBackup resource (if enabled)
Helm->>Kubernetes API: Apply S3 credentials secret
Kubernetes API->>CNPG Operator: Notify of new/updated resources
CNPG Operator->>Kubernetes API: Schedule backups, manage restores
Possibly related PRs
Suggested labels
Poem
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
6e8ff27 to
7021174
Compare
7021174 to
948d7fa
Compare
There was a problem hiding this comment.
Actionable comments posted: 6
🔭 Outside diff range comments (1)
packages/apps/postgres/README.md (1)
71-80: Correct bootstrap parameter paths
The docs listresourcesandresourcesPreset, but the chart expectsbootstrap.resourcesandbootstrap.resourcesPreset. Please update the table to show the full parameter paths.
🧹 Nitpick comments (14)
packages/apps/postgres/templates/backup-secret.yaml (2)
1-10: Expand secret rendering and rename keys
This template now renders when either backup or bootstrap is enabled and renames the secret to{{ .Release.Name }}-s3-credswithAWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEYfields. Verify that all consumers (e.g.,db.yaml) use the new secret name and that bootstrap workflows correctly pull credentials from.Values.backup.
1-1: Suppress YAMLlint false positive
Helm directives like{{- if ... }}trigger YAMLlint errors but are valid in templates. Consider configuring your linter to ignore template control statements.packages/apps/postgres/README.md (1)
61-70: Fix typo in backup parameters
The description forbackup.enabledreads “pereiodic” and should be “periodic.” Also clarify that the cron schedule uses a six-field expression (seconds included).packages/apps/postgres/templates/backup.yaml (1)
1-1: Suppress YAMLlint false positive
The leading{{- if .Values.backup.enabled }}triggers a syntax warning in YAMLlint. You can ignore or disable linting for Helm template directives.packages/apps/postgres/templates/db.yaml (3)
8-21: UsetoYaml+nindentfor DRY templating
You can replace the manual block with:{{- if .Values.backup.enabled }} {{- toYaml .Values.backup | nindent 2 }} {{- end }}This avoids duplication if new
backupprops are added.
22-22: Remove trailing whitespace
YAMLlint flagged trailing spaces on this blank line. Please remove them to clean up the template.
31-43: Consolidate duplicated S3 credentials block
Thes3Credentialsstanza is duplicated underbackup.barmanObjectStoreandexternalClusters. You could factor it into a named template or usetoYamlto inject a single definition.packages/apps/postgres/values.schema.json (5)
68-72: Clarify cron format in schema
The default uses a 6-field expression ("0 2 * * * *"), but the description doesn’t mention seconds. Add a note to thedescriptionor apply a JSON Schemapatternto enforce the six-field cron format.
73-77: ValidateretentionPolicyformat
Currently any string is accepted. You may want to add apattern(e.g.^\d+[dhm]$) to catch invalid values early.
78-82: EnforcedestinationPathURL pattern
Consider adding apatternor"format": "uri"to ensuredestinationPathis a valid URL (e.g.^s3://.+).
83-87: Add URL validation forendpointURL
Use"format": "uri"in the schema or apatternto validate the endpoint URL.
128-128: Note changed default forresourcesPreset
The default moved fromnanotomicro, which increases resource requests on upgrade. Ensure this bump is documented in the changelog.packages/apps/postgres/values.yaml (2)
64-67: Align key order with doc comments
Theschedule,retentionPolicy,destinationPath, andendpointURLproperties are out of order relative to their@paramdoc headers. Reordering to match documentation improves readability.
101-101: Document upgrade impact ofresourcesPresetdefault
Since you’ve bumped the default from"nano"to"micro", specify in the README or upgrade notes that resource usage will increase on chart upgrades.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
Makefile(0 hunks)packages/apps/postgres/Chart.yaml(1 hunks)packages/apps/postgres/Makefile(0 hunks)packages/apps/postgres/README.md(1 hunks)packages/apps/postgres/images/postgres-backup.tag(0 hunks)packages/apps/postgres/images/postgres-backup/Dockerfile(0 hunks)packages/apps/postgres/templates/backup-cronjob.yaml(0 hunks)packages/apps/postgres/templates/backup-script.yaml(0 hunks)packages/apps/postgres/templates/backup-secret.yaml(1 hunks)packages/apps/postgres/templates/backup.yaml(1 hunks)packages/apps/postgres/templates/db.yaml(1 hunks)packages/apps/postgres/values.schema.json(3 hunks)packages/apps/postgres/values.yaml(2 hunks)packages/apps/versions_map(1 hunks)
💤 Files with no reviewable changes (6)
- packages/apps/postgres/images/postgres-backup/Dockerfile
- packages/apps/postgres/images/postgres-backup.tag
- Makefile
- packages/apps/postgres/templates/backup-script.yaml
- packages/apps/postgres/templates/backup-cronjob.yaml
- packages/apps/postgres/Makefile
🧰 Additional context used
🪛 YAMLlint (1.37.1)
packages/apps/postgres/templates/backup.yaml
[error] 1-1: syntax error: expected the node content, but found '-'
(syntax)
packages/apps/postgres/templates/backup-secret.yaml
[error] 1-1: syntax error: expected the node content, but found '-'
(syntax)
packages/apps/postgres/templates/db.yaml
[error] 22-22: trailing spaces
(trailing-spaces)
[error] 9-9: syntax error: could not find expected ':'
(syntax)
🪛 Gitleaks (8.26.0)
packages/apps/postgres/values.yaml
75-75: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
76-76: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Build
🔇 Additional comments (2)
packages/apps/postgres/Chart.yaml (1)
19-19: Confirm version bump to 0.15.0
The Chart version has been incremented to 0.15.0 to reflect the backup/restore overhaul. Ensure downstream docs and CI flows recognize the new chart version.packages/apps/versions_map (1)
90-91: Update versions map for postgres
The mapping forpostgres 0.14.0now pins to commit62cb694d, and0.15.0points toHEAD, matching the Chart.yaml bump. This keeps the package registry in sync with your release.
| {{- if .Values.bootstrap.enabled }} | ||
| bootstrap: | ||
| recovery: | ||
| source: {{ .Values.bootstrap.oldName }} | ||
| {{- if .Values.bootstrap.recoveryTime }} | ||
| recoveryTarget: | ||
| targetTime: {{ .Values.bootstrap.recoveryTime }} | ||
| {{- end }} | ||
| externalClusters: |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Enforce oldName when bootstrapping
If bootstrap.enabled is true, .Values.bootstrap.oldName must be non-empty or the recovery source will be invalid. Consider using:
source: {{ required "bootstrap.oldName is required when bootstrap.enabled=true" .Values.bootstrap.oldName }}
🤖 Prompt for AI Agents
In packages/apps/postgres/templates/db.yaml around lines 23 to 31, the bootstrap
recovery source uses .Values.bootstrap.oldName without validation, which can
lead to an invalid source if oldName is empty. Replace the source line with the
Helm required function to enforce that oldName is provided when
bootstrap.enabled is true, using: source: {{ required "bootstrap.oldName is
required when bootstrap.enabled=true" .Values.bootstrap.oldName }}.
| {{- if .Values.backup.enabled }} | ||
| backup: | ||
| barmanObjectStore: | ||
| destinationPath: {{ .Values.backup.destinationPath }} | ||
| endpointURL: {{ .Values.backup.endpointURL }} | ||
| s3Credentials: | ||
| accessKeyId: | ||
| name: {{ .Release.Name }}-s3-creds | ||
| key: AWS_ACCESS_KEY_ID | ||
| secretAccessKey: | ||
| name: {{ .Release.Name }}-s3-creds | ||
| key: AWS_SECRET_ACCESS_KEY | ||
| retentionPolicy: {{ .Values.backup.retentionPolicy }} | ||
| {{- end }} |
There was a problem hiding this comment.
Missing backup schedule field
The Helm template defines backup.retentionPolicy but omits schedule, so CNPG will never schedule backups. Add:
backup:
schedule: {{ .Values.backup.schedule }}
retentionPolicy: {{ .Values.backup.retentionPolicy }}
barmanObjectStore:
...🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 9-9: syntax error: could not find expected ':'
(syntax)
🤖 Prompt for AI Agents
In packages/apps/postgres/templates/db.yaml around lines 8 to 21, the backup
configuration is missing the schedule field, which prevents CNPG from scheduling
backups. Add the schedule field under backup by including `schedule: {{
.Values.backup.schedule }}` alongside retentionPolicy and barmanObjectStore to
ensure backups are properly scheduled.
| "bootstrap": { | ||
| "type": "object", | ||
| "properties": { | ||
| "enabled": { | ||
| "type": "boolean", | ||
| "description": "Restore cluster from backup", | ||
| "default": false | ||
| }, | ||
| "recoveryTime": { | ||
| "type": "string", | ||
| "description": "Time stamp up to which recovery will proceed, expressed in RFC 3339 format, if empty, will restore latest", | ||
| "default": "" | ||
| }, | ||
| "resticPassword": { | ||
| "oldName": { | ||
| "type": "string", | ||
| "description": "The password for Restic backup encryption", | ||
| "default": "ChaXoveekoh6eigh4siesheeda2quai0" | ||
| "description": "Name of cluster before deleting", | ||
| "default": "" | ||
| } | ||
| } | ||
| }, |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Require oldName when bootstrap enabled
The bootstrap object needs at least oldName (and possibly recoveryTime) when enabled: true. Add a "required": ["oldName"] (or conditional requirements via dependencies) to catch misconfiguration.
🤖 Prompt for AI Agents
In packages/apps/postgres/values.schema.json around lines 100 to 119, the
bootstrap object lacks validation to require oldName when enabled is true. Add a
"required" field or use JSON Schema "dependencies" or "if-then" constructs to
enforce that oldName is present whenever bootstrap.enabled is true, ensuring
misconfigurations are caught during validation.
| bootstrap: | ||
| enabled: false | ||
| # example: 2020-11-26 15:22:00.00000+00 | ||
| recoveryTime: "" | ||
| oldName: "" |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Enforce bootstrap.oldName on enable
Bootstrapping with an empty oldName will fail silently. Either document that oldName is required when bootstrap.enabled=true or add a Helm required check:
oldName: {{ required "bootstrap.oldName is required when enabled" .Values.bootstrap.oldName }}
🤖 Prompt for AI Agents
In packages/apps/postgres/values.yaml around lines 84 to 88, the
bootstrap.oldName field is empty by default, which causes silent failures when
bootstrap.enabled is true. To fix this, add a Helm required check for
bootstrap.oldName in the Helm template files, ensuring it throws an error if
oldName is not set when bootstrap.enabled is true. Alternatively, update the
documentation to clearly state that oldName must be provided when enabling
bootstrap.
| retentionPolicy: 30d | ||
| destinationPath: s3://BUCKET_NAME/ | ||
| endpointURL: http://minio-gateway-service:9000 | ||
| schedule: "0 2 * * * *" | ||
| s3AccessKey: oobaiRus9pah8PhohL1ThaeTa4UVa7gu | ||
| s3SecretKey: ju3eum4dekeich9ahM1te8waeGai0oog |
There was a problem hiding this comment.
Remove hardcoded credentials from values.yaml
Those default access/secret keys appear real and triggered Gitleaks. You should not store credentials here. Consider removing s3AccessKey/s3SecretKey from values.yaml and requiring users to provide a Kubernetes Secret instead.
🧰 Tools
🪛 Gitleaks (8.26.0)
75-75: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
76-76: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🤖 Prompt for AI Agents
In packages/apps/postgres/values.yaml around lines 71 to 76, the s3AccessKey and
s3SecretKey are hardcoded, which is a security risk and triggered Gitleaks.
Remove these keys from values.yaml and update the deployment to require users to
provide these credentials via a Kubernetes Secret, referencing that secret in
the configuration instead of embedding the keys directly.
Signed-off-by: kklinch0 <[email protected]>
948d7fa to
7c45335
Compare
Signed-off-by: Timofei Larkin <[email protected]>
There was a problem hiding this comment.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
packages/apps/postgres/README.md (1)
20-37: Update restore instructions to match new backup mechanism
The “How to restore backup” section still referencesrestic, but the new implementation uses CNPG’sbootstrapflow andScheduledBackupresources. Please remove or update these instructions to reflect the new process.
♻️ Duplicate comments (4)
packages/apps/postgres/templates/db.yaml (2)
8-21: Missingschedulefield under cluster backup spec
The CNPG clusterbackupblock defines retention and object store settings but lacks thescheduleproperty, which is required to schedule backups. Add:spec: {{- if .Values.backup.enabled }} backup: + schedule: {{ .Values.backup.schedule | quote }} barmanObjectStore: destinationPath: {{ .Values.backup.destinationPath }} endpointURL: {{ .Values.backup.endpointURL }} retentionPolicy: {{ .Values.backup.retentionPolicy }} {{- end }}
23-31: EnforceoldNamevalidation when bootstrapping
Ifbootstrap.enabledis true,.Values.bootstrap.oldNamemust be non-empty to generate a valid recovery source. Use:source: {{ required "bootstrap.oldName is required when bootstrap.enabled=true" .Values.bootstrap.oldName }}packages/apps/postgres/values.schema.json (1)
100-119: Schema should requireoldNamewhen bootstrap is enabled
Thebootstrapobject lacks arequiredconstraint foroldName(and possiblyrecoveryTimewhen needed). Consider adding a"required": ["oldName"]or using anif/thenJSON Schema construct to enforce this.packages/apps/postgres/values.yaml (1)
78-88: Enforcebootstrap.oldNamewhen enabled
Thebootstrap.oldNamefield must be set whenbootstrap.enabled=trueto avoid silent failures. Add a Helmrequiredassertion in your templates (or document this dependency clearly).
🧹 Nitpick comments (2)
packages/apps/postgres/README.md (1)
61-69: Typo in backup parameters table
Found “Enable pereiodic backups” – please correct the typo to “Enable periodic backups”.packages/apps/postgres/values.schema.json (1)
63-71: Typo in JSON Schema description
Thebackup.enableddescription reads “Enable pereiodic backups”. Please correct to “Enable periodic backups”.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
Makefile(0 hunks)packages/apps/postgres/Chart.yaml(1 hunks)packages/apps/postgres/Makefile(0 hunks)packages/apps/postgres/README.md(1 hunks)packages/apps/postgres/images/postgres-backup.tag(0 hunks)packages/apps/postgres/images/postgres-backup/Dockerfile(0 hunks)packages/apps/postgres/templates/backup-cronjob.yaml(0 hunks)packages/apps/postgres/templates/backup-script.yaml(0 hunks)packages/apps/postgres/templates/backup-secret.yaml(1 hunks)packages/apps/postgres/templates/backup.yaml(1 hunks)packages/apps/postgres/templates/db.yaml(1 hunks)packages/apps/postgres/values.schema.json(3 hunks)packages/apps/postgres/values.yaml(2 hunks)packages/apps/versions_map(1 hunks)
💤 Files with no reviewable changes (6)
- packages/apps/postgres/Makefile
- Makefile
- packages/apps/postgres/templates/backup-script.yaml
- packages/apps/postgres/images/postgres-backup/Dockerfile
- packages/apps/postgres/images/postgres-backup.tag
- packages/apps/postgres/templates/backup-cronjob.yaml
✅ Files skipped from review due to trivial changes (1)
- packages/apps/postgres/Chart.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/apps/versions_map
🧰 Additional context used
🪛 LanguageTool
packages/apps/postgres/README.md
[uncategorized] ~79-~79: This verb does not appear to agree with the subject. Consider using a different form.
Context: ... 2xlarge). This is ignored if resources is set (resources is recommended for produ...
(AI_EN_LECTOR_REPLACEMENT_VERB_AGREEMENT)
[uncategorized] ~79-~79: This verb does not appear to agree with the subject. Consider using a different form.
Context: ... ignored if resources is set (resources is recommended for production). | micro ...
(AI_EN_LECTOR_REPLACEMENT_VERB_AGREEMENT)
🪛 YAMLlint (1.37.1)
packages/apps/postgres/templates/backup-secret.yaml
[error] 1-1: syntax error: expected the node content, but found '-'
(syntax)
packages/apps/postgres/templates/backup.yaml
[error] 1-1: syntax error: expected the node content, but found '-'
(syntax)
packages/apps/postgres/templates/db.yaml
[error] 22-22: trailing spaces
(trailing-spaces)
[error] 9-9: syntax error: could not find expected ':'
(syntax)
🪛 Gitleaks (8.26.0)
packages/apps/postgres/values.yaml
75-75: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
76-76: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🔇 Additional comments (5)
packages/apps/postgres/templates/backup-secret.yaml (1)
1-10: Secret condition and key alignment looks good
Expanding the conditional to include bootstrap and renaming the Secret keys to AWS standard environment variables is appropriate, and therequiredcalls ensure missing credentials are caught.packages/apps/postgres/templates/backup.yaml (1)
1-12: Validate ScheduledBackup spec completeness
The newScheduledBackuptemplate only includesscheduleandbackupOwnerReference, but omits fields such as retention policy, destination path, endpoint URL, and S3 credentials, which may be required by the CNPG CRD to perform backups. Please verify the CRD definition and include all necessary spec fields.packages/apps/postgres/values.yaml (3)
64-66: Documented generic backup parameters
The new docs forbackup.retentionPolicy,backup.destinationPath, andbackup.endpointURLlook good. Ensure that the corresponding Helm templates consume these values and surface them correctly in theScheduledBackupresource.
71-74: Validate default backup settings
- Confirm that the
30dformat forretentionPolicyaligns with the CRD’s expected duration syntax (e.g., ISO8601).- Verify that the six-field cron expression (
"0 2 * * * *") is supported by theScheduledBackupcontroller.
101-101: UpdateresourcesPresetdefault to “micro”
Switching fromnanotomicroincreases CPU/RAM—verify that this meets your intended SLAs and update any related documentation or README examples to reflect the new default.
| s3AccessKey: oobaiRus9pah8PhohL1ThaeTa4UVa7gu | ||
| s3SecretKey: ju3eum4dekeich9ahM1te8waeGai0oog |
There was a problem hiding this comment.
Remove hardcoded S3 credentials
Storing real s3AccessKey/s3SecretKey defaults in values.yaml is a security risk (Gitleaks alert). Remove these entries and require users to supply a Kubernetes Secret, then reference it in the chart.
🧰 Tools
🪛 Gitleaks (8.26.0)
75-75: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
76-76: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🤖 Prompt for AI Agents
In packages/apps/postgres/values.yaml at lines 75 to 76, remove the hardcoded
s3AccessKey and s3SecretKey values to avoid security risks. Instead, update the
chart to require users to provide these credentials via a Kubernetes Secret and
modify the chart templates to reference this Secret for accessing the S3 keys.
Update kamaji from edge-26.2.4 to 26.3.5-edge and remove patches that have been accepted upstream: - increase-startup-probe-threshold.diff: upstream PR #1086 added configurable startupProbeFailureThreshold field - disable-datastore-check.diff: upstream PR #1087 refactored DataStore initialization, removing the blocking startup check The remaining fix-kubelet-config-compat.diff patch (PR #1084) is still needed as the maintainer has not accepted the upstream fix for kubelet config compatibility with K8s < 1.35. Also update Makefile to match the new upstream tag format (26.x.x-edge instead of edge-26.x.x) introduced in PR #1094. Assisted-By: Claude <[email protected]> Signed-off-by: Aleksei Sviridkin <[email protected]>
## What this PR does Update kamaji from edge-26.2.4 to 26.3.5-edge and remove two patches that have been accepted upstream: - `increase-startup-probe-threshold.diff` → upstream #1086 added configurable startupProbeFailureThreshold - `disable-datastore-check.diff` → upstream #1087 refactored DataStore initialization The remaining `fix-kubelet-config-compat.diff` (PR #1084) is still needed — the maintainer has not accepted the upstream fix for kubelet config compatibility with K8s < 1.35. Also updates Makefile to match the new upstream tag format (`26.x.x-edge` instead of `edge-26.x.x`) introduced in upstream PR #1094. Note: `make image` needs to be run to rebuild the container image and update `values.yaml` with the new tag/digest. Changes: - Makefile: update tag grep pattern for new format - Dockerfile: bump VERSION to 26.3.5-edge - Remove 2 upstreamed patches - Update vendored charts from 26.3.5-edge ### Release note ```release-note [kamaji] Update to 26.3.5-edge, drop 2 upstreamed patches ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Configurable probe tuning for Control Plane components (API Server, Controller Manager, Scheduler) * DataStore readiness visible in kubectl and status conditions tracking * **Improvements** * Stronger networkProfile validation (CIDR checks, DNS/IP consistency) * DataStore driver is immutable after creation * **Chores** * Removed two validating webhooks * Updated default packaged manager version used for builds <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Summary by CodeRabbit
New Features
Improvements
Removals
Documentation