Skip to content

[mariadb] fix: always enable replication for consistent service naming - #2279

Merged
Andrei Kvapil (kvaps) merged 2 commits into
mainfrom
fix/mariadb-always-enable-replication
Mar 30, 2026
Merged

[mariadb] fix: always enable replication for consistent service naming#2279
Andrei Kvapil (kvaps) merged 2 commits into
mainfrom
fix/mariadb-always-enable-replication

Conversation

@sircthulhu

@sircthulhu Kirill Ilin (sircthulhu) commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Enables replication unconditionally in the MariaDB CR, regardless of replica count.

Previously, single-replica MariaDB instances created a general service (mariadb-<name>) without -primary/-secondary suffixes. This caused:

  • Dashboard not displaying the service (both dashboard-resourcemap RBAC and the ApplicationDefinition expect -primary/-secondary)
  • Backup CronJob referencing non-existent <name>-secondary service

Also removes a duplicate template key in the backup-cronjob YAML that was silently ignored by the parser.

BREAKING CHANGE: Single-replica MariaDB instances will now expose services as <name>-primary and <name>-secondary instead of the bare <name>. Applications connecting via the old service DNS name must update their connection strings.

Release note

[mariadb] BREAKING: MariaDB now always enables replication, creating -primary/-secondary services even for single-replica instances. This fixes dashboard visibility and backup functionality for single-replica setups. Existing single-replica users must update connection strings from `<name>` to `<name>-primary`.

Summary by CodeRabbit

  • Bug Fixes
    • Removed a redundant backup job restart policy that could cause conflicting behavior.
    • Ensured replication is consistently enabled across all deployment sizes.
    • Made external service LoadBalancer settings apply more predictably for external deployments.
    • Adjusted database host selection so single-replica deployments target the primary instance, improving connection correctness.

Enable replication unconditionally regardless of replica count.
Previously, single-replica instances created a general service
without -primary/-secondary suffixes, causing dashboard and
backup-cronjob to reference non-existent services.

Also fix duplicate YAML key in backup-cronjob template.

BREAKING CHANGE: Single-replica MariaDB instances will now have
service names with -primary/-secondary suffixes instead of the
bare instance name. Applications connecting via the old service
DNS name need to be updated.

Assisted-By: Claude AI
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
@coderabbitai

coderabbitai Bot commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e02fa1fa-eb7a-44a3-897a-1abbcd334cac

📥 Commits

Reviewing files that changed from the base of the PR and between d2030be and 1d58c18.

📒 Files selected for processing (1)
  • packages/apps/mariadb/templates/backup-cronjob.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/apps/mariadb/templates/backup-cronjob.yaml

📝 Walkthrough

Walkthrough

The MariaDB Helm templates were updated: the backup CronJob removed a redundant nested restartPolicy and altered MYSQL_HOST to choose primary when replicas==1; the main MariaDB manifest now always enables replication and unconditionally applies LoadBalancer for primaryService when .Values.external is true.

Changes

Cohort / File(s) Summary
Backup CronJob Configuration
packages/apps/mariadb/templates/backup-cronjob.yaml
Removed redundant jobTemplate.spec.template.spec.restartPolicy: OnFailure, leaving only spec.template.spec.restartPolicy: Never. Updated MYSQL_HOST env var to be conditional: use {{ .Release.Name }}-primary when int .Values.replicas == 1, otherwise {{ .Release.Name }}-secondary.
MariaDB Manifest Service & Replication
packages/apps/mariadb/templates/mariadb.yaml
Made spec.replication.enabled: true unconditional (removed surrounding conditionals). Removed the conditional block that emitted spec.service.metadata.type: LoadBalancer for single-replica external deployments. Changed spec.primaryService LoadBalancer gating to trigger whenever .Values.external is true, regardless of replica count.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through templates, tidy and spry,
Snipped a repeat restart, gave hosts a sly try,
Replicas now always echo a tune,
Services spin up beneath the same moon. ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately summarizes the main change: enabling replication unconditionally in MariaDB for consistent service naming.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/mariadb-always-enable-replication

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sircthulhu
Kirill Ilin (sircthulhu) marked this pull request as ready for review March 27, 2026 06:05
@dosubot dosubot Bot added size/S This PR changes 10-29 lines, ignoring generated files kind/bug Categorizes issue or PR as related to a bug labels Mar 27, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request simplifies the MariaDB configuration by enabling replication by default and streamlining service type logic. A critical issue was identified where this change breaks backups for single-replica instances, as the backup cronjob targets a secondary service that will not have active endpoints; a fix was suggested to adjust the backup host dynamically.

Comment on lines 32 to 36
replication:
enabled: true
#primary:
# podIndex: 0
# automaticFailover: true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

While always enabling replication provides consistent service naming, it appears to break backups for single-replica instances, which this PR also aims to fix.

The backup-cronjob.yaml is hardcoded to use the ...-secondary service. With replicas: 1, this service will have no endpoints as the single pod will be the primary, causing backups to fail.

To fix this, the MYSQL_HOST in backup-cronjob.yaml should point to the primary service when replicas: 1. For example:

- name: MYSQL_HOST
  value: "{{ .Release.Name }}-{{ if eq (int .Values.replicas) 1 }}primary{{ else }}secondary{{ end }}"

I'm adding this comment here because the issue is a direct consequence of this change, even though the fix is in a file not fully included in this PR's diff.

@sircthulhu Kirill Ilin (sircthulhu) Mar 27, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Verified the operator source — reconcileSecondaryService creates the service with ExcludeSelectorLabels: true and relies on a manually managed EndpointSlice populated by ListMariaDBSecondaryPods(), which filters out the primary pod. With replicas: 1 this results in zero endpoints.

Fixed in 1d58c18 — the backup cronjob now targets the primary service when replicas=1.

When replicas=1, the secondary service has no endpoints because the
only pod is the primary. Route backups to the primary service in this
case to ensure they work correctly.

Assisted-By: Claude AI
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
@kvaps
Andrei Kvapil (kvaps) merged commit 68c7e81 into main Mar 30, 2026
7 checks passed
@kvaps
Andrei Kvapil (kvaps) deleted the fix/mariadb-always-enable-replication branch March 30, 2026 18:07
@kvaps Andrei Kvapil (kvaps) added the backport Should change be backported on previous release label May 14, 2026
@github-actions

Copy link
Copy Markdown

Backport failed for release-1.3, because it was unable to cherry-pick the commit(s).

Please cherry-pick the changes locally and resolve any conflicts.

git fetch origin release-1.3
git worktree add -d .worktree/backport-2279-to-release-1.3 origin/release-1.3
cd .worktree/backport-2279-to-release-1.3
git switch --create backport-2279-to-release-1.3
git cherry-pick -x d2030bef87c747bbf59e9757037162cc63c33e90 1d58c18ff782c822119c20bc4df9375841b46e07

@kvaps Andrei Kvapil (kvaps) added backport-previous Backport target — previous release line and removed backport Should change be backported on previous release labels May 14, 2026
@github-actions

Copy link
Copy Markdown

@kvaps Andrei Kvapil (kvaps) removed the backport-previous Backport target — previous release line label May 14, 2026
Andrei Kvapil (kvaps) added a commit that referenced this pull request May 14, 2026
Minimal backport from #2279 to release-1.2 — only the dup-key removal,
without the breaking service-naming / replication changes.

Signed-off-by: Andrei Kvapil <andrei.kvapil@aenix.io>
Co-Authored-By: Claude <noreply@anthropic.com>
Andrei Kvapil (kvaps) added a commit that referenced this pull request May 14, 2026
Minimal backport from #2279 to release-1.2 — only the dup-key removal,
without the breaking service-naming / replication changes.

Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Andrei Kvapil (kvaps) added a commit that referenced this pull request May 14, 2026
… backup CronJob (#2652)

## Summary

Minimal backport from #2279 to `release-1.2` — only the
duplicate-`template:` key removal in
`packages/apps/mariadb/templates/backup-cronjob.yaml`, without the
breaking service-naming / forced-replication changes from #2279 (those
are not appropriate for a patch release).

Fixes the `yaml: unmarshal errors: line 17: mapping key "template"
already defined at line 14` error when deploying MariaDB with
`backup.enabled: true` on v1.2.x.

Related: #2293

## Test plan
- [ ] `helm template` of the mariadb chart with `backup.enabled: true`
renders without YAML duplicate-key errors
- [ ] CronJob deploys successfully on a v1.2.x cluster
Andrei Kvapil (kvaps) added a commit that referenced this pull request May 14, 2026
## Summary

Adds `docs/changelogs/v1.2.4.md` so the `Update Release Notes` workflow
can publish the existing `v1.2.4` draft release.

`v1.2.4` is a hotfix patch backporting only the duplicate-`template:`
key removal from #2279 — the breaking service-naming changes in that PR
were intentionally omitted as not appropriate for a patch (see #2652 for
the minimal-backport details).

The `Generate Changelog` step on the tag-push workflow failed twice in a
row (yesterday's cron run and today's manual dispatch) due to `402 You
have no quota` on the Copilot API, so this changelog is hand-written
following `docs/changelogs/patch-template.md` and matches the v1.2.3
style.

## Test plan
- [x] file follows `patch-template.md` structure
- [x] author attribution verified against `gh pr view` for #2279 and
#2652
- [ ] CI passes
- [ ] after merge, `Update Release Notes` picks up the file and
publishes draft release `v1.2.4`
Andrei Kvapil (kvaps) added a commit to kvaps/cozystack that referenced this pull request May 14, 2026
Hand-written patch changelog for v1.2.4 (Copilot quota exhausted on the
automatic Generate Changelog step). Single fix: minimal backport of the
MariaDB backup CronJob duplicate-key removal from cozystack#2279 via cozystack#2652.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
scooby87 added a commit that referenced this pull request Jul 2, 2026
…tor webhook (#3180)

## What this PR does

Fixes a regression where **single-replica MariaDB can no longer be
created**.

[PR #2279](#2279) made
`replication.enabled: true` unconditional in the MariaDB CR so the
operator would always create `<release>-primary` / `<release>-secondary`
Services (expected by the dashboard RBAC and the ApplicationDefinition).
But the vendored mariadb-operator's validating webhook
(`vmariadb-v1alpha1.kb.io`) **rejects `replication.enabled: true` when
`spec.replicas == 1`** — replication needs a primary + at least one
replica. As a result, single-replica installs never became Ready (the
HelmRelease failed at admission).

The webhook rule lives in the operator's Go code (not in the vendored
CRD — there is no CEL rule tying replication to replica count), so the
failing path is reproduced by an e2e test rather than a schema
assertion.

### Fix — re-guard replication, teach consumers about the bare service

The operator provisions a bare `<release>` Service in **both**
topologies; `-primary`/`-secondary` exist **only** when replication is
on (`replicas>1`). Instead of forcing replication for everyone, this PR
lets replication track the replica count and makes the service-name
consumers handle the single-replica bare service:

- **`mariadb.yaml`** — gate `replication` on `replicas>1`; restore
single-replica external access via `service.type: LoadBalancer`, and
keep `primaryService: LoadBalancer` for `replicas>1` only. (Effectively
reverts #2279's two hunks.)
- **`backup-cronjob.yaml`** — single-replica dumps target the bare
service (no `-secondary` exists without replication); `replicas>1` still
offloads to `-secondary`.
- **`dashboard-resourcemap.yaml`** — always grant RBAC on the bare
service, plus `-primary`/`-secondary` when `replicas>1`, matching what
the ApplicationDefinition lists.
- **`mariadb-rd`** — list the bare service in `services.include` so
single-replica installs are visible in the dashboard.
- **`hack/e2e-apps/mariadb.bats`** — new `Create single-replica MariaDB`
test that reproduces the webhook rejection and guards against
regression.

Verified: `helm template` at `replicas=1`/`2` renders the intended
CR/RBAC/backup host; `helm unittest` passes; `update-crd.sh` keeps the
RD stable; `select-e2e.sh` maps the change to the mariadb suite.

### Release note

```release-note
fix(mariadb): single-replica instances can be created again — replication is now enabled only for replicas>1 (matching the operator webhook), while the dashboard, RBAC, and backups correctly target the bare service for single-replica setups
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added an end-to-end test covering MariaDB deployments with a single
replica, including validation of the main service, endpoints,
StatefulSet replica count, and metrics components.

* **Bug Fixes**
* Updated MariaDB chart behavior to correctly handle single-replica vs
multi-replica configurations for external access, replication settings,
and backup host selection.
* Refined dashboard RBAC and secret inclusion so access applies to the
main MariaDB service in addition to replica-specific services.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
pull Bot pushed a commit to medampudi/cozystack that referenced this pull request Jul 2, 2026
…tor webhook

PR cozystack#2279 made `replication.enabled: true` unconditional so the operator would
always create -primary/-secondary services. But the mariadb-operator validating
webhook (vmariadb-v1alpha1.kb.io) rejects replication when spec.replicas == 1,
so single-replica MariaDB could no longer be created — the HelmRelease never
became Ready.

Re-guard replication on replicas>1 and teach the service-name consumers about
the bare <release> service the operator provisions in both topologies:

- mariadb.yaml: gate `replication` on replicas>1; restore single-replica
  external access via `service.type: LoadBalancer` and keep `primaryService`
  LoadBalancer for replicas>1 only.
- backup-cronjob.yaml: route single-replica dumps to the bare service
  (no -secondary exists without replication).
- dashboard-resourcemap.yaml: always grant RBAC on the bare service, plus
  -primary/-secondary when replicas>1, matching the ApplicationDefinition.
- mariadb-rd: list the bare service in services.include so single-replica
  installs are visible in the dashboard.

Adds a single-replica e2e test that reproduces the webhook rejection and
guards against regression.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Алексей Артамонов <alexeyartamonov1987@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/bug Categorizes issue or PR as related to a bug size/S This PR changes 10-29 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants