Skip to content

[tcp-balancer] Fix HAProxy 3.3 startup regression - #2321

Closed
Asish Kumar (officialasishkumar) wants to merge 4 commits into
cozystack:mainfrom
officialasishkumar:fix/tcp-balancer-haproxy-3-3
Closed

Asish Kumar (officialasishkumar) wants to merge 4 commits into
cozystack:mainfrom
officialasishkumar:fix/tcp-balancer-haproxy-3-3

Conversation

@officialasishkumar

@officialasishkumar Asish Kumar (officialasishkumar) commented Apr 2, 2026 •

Copy link
Copy Markdown

What this PR does

Fixes the tcp-balancer chart so it starts correctly with HAProxy 3.3+.

  • renames the generated backends in haproxy.cfg so they no longer collide with frontend names
  • pins the HAProxy image to the chart appVersion instead of pulling haproxy:latest

Fixes #1966

Validation

  • rendered the chart with both HTTP/HTTPS and Kubernetes/Talos listeners enabled
  • validated the rendered haproxy.cfg with haproxy:3.3 haproxy -c -f /usr/local/etc/haproxy/haproxy.cfg

Release note

[tcp-balancer] Fix tcp-balancer startup with HAProxy 3.3+ by renaming generated backends and pinning the HAProxy image to the chart appVersion.

Summary by CodeRabbit

Release Notes

  • Updates
    • Renamed HAProxy backend identifiers for clearer, consistent naming across frontends and backends.
    • HAProxy container image reference now follows the chart's app version instead of a fixed tag.
    • Chart appVersion updated to a newer release to align runtime image and chart metadata.

@coderabbitai

coderabbitai Bot commented Apr 2, 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: 0ef931fb-ab63-4c96-b163-e043a8e99a57

📥 Commits

Reviewing files that changed from the base of the PR and between 0222254 and 79270a5.

📒 Files selected for processing (3)
  • packages/apps/tcp-balancer/Chart.yaml
  • packages/apps/tcp-balancer/templates/configmap.yaml
  • packages/apps/tcp-balancer/templates/deployment.yaml
✅ Files skipped from review due to trivial changes (2)
  • packages/apps/tcp-balancer/Chart.yaml
  • packages/apps/tcp-balancer/templates/deployment.yaml

📝 Walkthrough

Walkthrough

Renamed HAProxy backend identifiers to add a _backend suffix to avoid frontend/backend name collisions introduced by HAProxy 3.3, and changed the HAProxy image reference to use the chart appVersion instead of :latest. Chart appVersion was updated accordingly.

Changes

Cohort / File(s) Summary
HAProxy Configuration
packages/apps/tcp-balancer/templates/configmap.yaml
Renamed backend blocks and updated frontend default_backend directives: http→http_backend, https→https_backend, kubernetes→kubernetes_backend, talos→talos_backend to fix HAProxy 3.3 collision error.
Container Image & Chart Metadata
packages/apps/tcp-balancer/templates/deployment.yaml, packages/apps/tcp-balancer/Chart.yaml
Replaced haproxy:latest with haproxy:{{ .Chart.AppVersion }} in the Deployment template and updated appVersion from "2.9.7" to "3.3.6" in Chart.yaml to pin image version via chart metadata.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I hopped through configs, names in tow,

Frontend and backend no longer a foe.
Version snugged in, no more surprise,
HAProxy leaps forward with wiser eyes.
✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically identifies the main change: fixing a HAProxy 3.3 startup regression in tcp-balancer, which directly matches the core problem and solution in the PR.
Linked Issues check ✅ Passed The PR fully implements both suggested fixes from issue #1966: renaming backends to avoid name collisions (http→http_backend, https→https_backend, kubernetes→kubernetes_backend, talos→talos_backend) and pinning HAProxy image to chart appVersion.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing issue #1966: backend renaming in configmap.yaml, image pinning in deployment.yaml, and appVersion update in Chart.yaml. No unrelated modifications present.
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

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.

@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 updates the HAProxy configuration by renaming backends to include a '_backend' suffix and modifies the deployment to use a versioned HAProxy image. The reviewer noted that while the image is now versioned, the current Chart.yaml appVersion (2.9.7) is incompatible with the intended HAProxy 3.3+ requirement, and recommends updating the Chart.yaml to reflect a compatible version.

topologyKey: kubernetes.io/hostname
containers:
- image: haproxy:latest
- image: "haproxy:{{ .Chart.AppVersion }}"

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

This change pins the HAProxy image to {{ .Chart.AppVersion }}, but the appVersion in Chart.yaml is "2.9.7". The goal of this PR is to fix compatibility with HAProxy 3.3+, but this change will result in using haproxy:2.9.7.

To align with the PR's goal, the appVersion in Chart.yaml should be updated to a HAProxy 3.3+ version. This will ensure the new configuration is used with a compatible HAProxy version.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good catch. Updated appVersion in Chart.yaml from 2.9.7 to 3.3.6 so the deployment template now pulls the correct HAProxy 3.3 image.

@officialasishkumar
Asish Kumar (officialasishkumar) marked this pull request as ready for review April 2, 2026 09:09
@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 Apr 2, 2026
Updated Chart.yaml appVersion from 2.9.7 to 3.3.6 to match the
configuration changes in this PR. The deployment template references
.Chart.AppVersion for the image tag, so this ensures the correct
HAProxy 3.3 image is used rather than the old 2.9.7 version.

Signed-off-by: Asish Kumar <[email protected]>
Copilot AI review requested due to automatic review settings April 4, 2026 10:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Fixes a HAProxy 3.3+ breaking change in the tcp-balancer Helm chart by ensuring frontend/backend names no longer collide and by pinning the HAProxy image tag to the chart’s appVersion (instead of :latest), aligning with issue #1966.

Changes:

  • Renamed generated HAProxy backends (e.g., http_backend, https_backend) to avoid name collisions with frontends on HAProxy 3.3+.
  • Updated the Deployment to use haproxy:{{ .Chart.AppVersion }} rather than haproxy:latest.
  • Bumped chart appVersion to 3.3.6.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
packages/apps/tcp-balancer/templates/deployment.yaml Pins HAProxy image tag to the chart appVersion to prevent unexpected breakage from :latest.
packages/apps/tcp-balancer/templates/configmap.yaml Renames backends and updates default_backend references to prevent HAProxy 3.3 name-collision startup failure.
packages/apps/tcp-balancer/Chart.yaml Updates appVersion to 3.3.6 to match the intended HAProxy version used by the chart.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@crossRT

Copy link
Copy Markdown
Contributor

hi guys, thank you for the contribution.
may I know when will this get merged?
As this issue is blocking users to create the tcp-balancer.

@freznicek

Copy link
Copy Markdown

Dear all,
I just ran into same problem here.
Can someone comment on what is blocking this PR from being merged?

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.

NOT LGTM — the rename itself is correct and verified, but the PR rewrites frontend blocks that contain a second fatal config bug with the same "pod won't start" symptom, and the fix ships without any regression test.

Business context: haproxy:latest started resolving to 3.3+, where identical frontend/backend names are a fatal config error, so tcp-balancer pods fail to start (#1966).

Blockers

B1: Undefined ACL whitelist is a fatal config error in the same frontends this PR rewrites

File: packages/apps/tcp-balancer/templates/configmap.yaml:92-98 (and the talos block below)

Issue: tcp-request content accept if whitelist / tcp-request content reject render unconditionally in the kubernetes/talos frontends, while acl whitelist src ... only renders when .Values.whitelist is non-empty (default: []). Same trap in http/https when whitelistHTTP: true with an empty whitelist.

Evidence: rendered the chart with kubernetesAndTalos.endpoints set and the default empty whitelist, then validated with haproxy:3.3.6 haproxy -c:

[ALERT] config : parsing [...] : 'tcp-request content accept' : error detected in frontend 'kubernetes' while parsing 'if' condition : no such ACL : 'whitelist'
[ALERT] config : Fatal errors found in configuration.

This is fatal on every HAProxy version, not just 3.3 — pre-existing, but it produces the exact failure mode this PR claims to fix, in the exact lines it touches.

Impact: any kubernetesAndTalos deployment without a whitelist keeps crash-looping even after this fix.

Fix: move the acl + accept + reject trio inside one shared {{- with $.Values.whitelist }} guard (empty whitelist → no filtering).

B2: No regression test pinning the fix

File: packages/apps/tcp-balancer/ (no tests/ directory)

Issue: CI runs make unit-tests (hack/helm-unit-tests.sh, auto-discovers per-chart tests/, see packages/apps/mongodb/tests/ for the pattern), but nothing asserts the renamed backends or the pinned image. The next template refactor can silently reintroduce the collision.

Fix: add a minimal helm-unittest suite asserting (a) every backend name in the rendered haproxy.cfg differs from every frontend name, (b) the deployment image equals haproxy:<appVersion> and never latest, (c) once B1 is fixed — accept if whitelist never renders without a matching acl whitelist line.

B3: kubernetesAndTalos is used by the template but declared nowhere

File: packages/apps/tcp-balancer/values.yaml, values.schema.json, README.md

Issue: the PR renames backends inside the kubernetesAndTalos blocks, but that key is absent from values.yaml, the schema, the README and the generated types — the values contract for the area being modified is out of sync with the template.

Fix: add the @param annotations and run make generate in the package.

Non-blocking follow-ups

  1. HAProxy 3.3 is a short-term branch (EOL 2027-Q1). Consider pinning an LTS instead — 3.2.x (supported to 2030) or 3.4.x (to 2031); at minimum bump to the current patch (3.3.10 — 3.3.6 is four patch releases behind). The renamed config validates on 3.2/3.3 alike.
  2. The identical bug (haproxy:latest + frontend http/backend http) exists in packages/apps/http-cache; the config half is already addressed by open PR #2654 — no action needed here, noting for completeness.
  3. PR title isn't in Conventional Commits format (fix(tcp-balancer): ...), so the auto-labeler applied no area/* label; the title also feeds the changelog.
  4. Please squash the appVersion follow-up commit into the main commit — this repo merges with merge commits, so both messages land in history as-is.

bind :::6443 v4v6
mode tcp
default_backend kubernetes
default_backend kubernetes_backend

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.

B1: this kubernetes frontend (and the talos one below) renders tcp-request content accept if whitelist unconditionally, but the acl whitelist line only renders when .Values.whitelist is non-empty. With the default empty whitelist, HAProxy fails to start: no such ACL : 'whitelist' (verified with haproxy:3.3.6 haproxy -c). Same symptom as #1966, fatal on every HAProxy version. Please wrap the acl + accept + reject trio in one shared {{- with $.Values.whitelist }} guard while you're touching these blocks.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Guarded the whitelist ACL, accept, and reject lines together in 57ccc6d. Rendered both empty and non-empty whitelist configs and validated them with HAProxy 3.4.1.

topologyKey: kubernetes.io/hostname
containers:
- image: haproxy:latest
- image: "haproxy:{{ .Chart.AppVersion }}"

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.

Pinning to appVersion is the right move, but note HAProxy 3.3 is a short-term branch (EOL 2027-Q1). Consider an LTS instead — 3.2.x (supported to 2030) or 3.4.x (to 2031). The renamed config validates fine on both.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Updated the chart to HAProxy 3.4.1 in 57ccc6d and validated the rendered config with that image.

Comment thread packages/apps/tcp-balancer/Chart.yaml Outdated
type: application
version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process
appVersion: "2.9.7"
appVersion: "3.3.6"

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.

3.3.6 is four patch releases behind (current 3.3 tag is 3.3.10), and 3.3 itself is a short-term branch — see the comment on the deployment image line: an LTS (3.2.x / 3.4.x) would be a better long-term pin.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Updated appVersion to 3.4.1 in 57ccc6d.

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.

Re-reviewing on 57ccc6d3. The whitelist ACL problem I raised in June is genuinely fixed, and the rename is complete: all four frontend and backend pairs renamed with every default_backend updated, and backendoptions takes a mode string rather than a backend name so it was never affected. Pinning the image to {{ .Chart.AppVersion }} instead of haproxy:latest is the right move and I would take that on its own.

Still NOT LGTM, because the fix introduced a new state that is worse in one specific way.

With whitelistHTTP: true and whitelist left empty, the http frontend now renders with no access-control rules at all. I rendered both branches to be sure. On main that combination emits tcp-request content accept if whitelist while the acl whitelist line is inside the with block and never emitted, so HAProxy refuses to start with no such ACL: 'whitelist'. On this branch the whole block is gone and the frontend comes up clean, passing everything. Nobody's working configuration changes, since that combination never started, so this is not a regression against a functioning setup. But an explicit security opt-in silently becoming a no-op is worse than a loud crash, because the crash gets noticed within a minute and this does not.

The fix is small: a fail when whitelistHTTP is true and whitelist is empty, matching the pattern already at templates/configmap.yaml:11. This is only needed for the http and https pair. For the kubernetes and talos frontends an empty list correctly means no filtering, because there whitelist is itself the toggle.

Still carried from June, and it is the reason this file has now shipped two independent fatal-config bugs: packages/apps/tcp-balancer has no tests/ directory. CI discovers per-chart helm unittest suites automatically, and a handful of app charts already have them. A suite pinning the rendered config for the default case, the whitelist-set case and the new failure case would have caught both bugs and costs very little.

One correction to my own earlier review: I flagged .Values.kubernetesAndTalos being referenced at configmap.yaml:88 while absent from values.yaml, the schema, the README and the API type. That is entirely pre-existing and this diff neither introduces nor worsens it, so I am not holding the PR on it. It is worth a follow-up while the file is open in front of you.

Two smaller things. haproxy:3.4.2 shipped in July, so the pin is one patch behind the current LTS line, though 3.4 is the right line to be on. And the PR title and one commit message still say 3.3 while the value is 3.4.1, which will read oddly in the changelog.

Non-blocking observation worth acting on separately: nothing will ever bump this pin. .github/renovate.json sets enabledManagers without the helm managers and has no custom matcher for chart image literals, which is the same rot the existing custom matchers were written to prevent. An entry covering chart appVersion image pins would keep this from going stale the way latest did, just in the opposite direction.

Separately from the code: DCO is red. The head commit and the merge commit carry no Signed-off-by, and the two signed commits use a different address than the others. That blocks merge regardless of the review.

Aleksei Sviridkin (lexfrei) added a commit that referenced this pull request Sep 25, 2026
…s on 3.3+ (#4366)

## What this PR does

`haproxy:latest` now resolves to 3.3 and newer. Since 3.3 a backend
named like a frontend is a fatal config error, so every tcp-balancer pod
fails at config parse (#1966). We hit it on Cozystack 1.6.1 with
`haproxy:3.4.4` behind the tag.

- backends get a `_backend` suffix and every `default_backend` follows;
the rename is the one from #2321 by @officialasishkumar
- the image is `haproxy:{{ .Chart.AppVersion }}` with `appVersion:
3.4.4`, the current 3.4 LTS tag
- the whitelist `acl`, `accept` and `reject` lines of each frontend
render inside one guard
- `tests/` holds helm-unittest suites, and the package `Makefile` gets
the `test` target the sweep looks for
- the `whitelistHTTP` description says it needs a non-empty `whitelist`

Two inputs change behaviour on upgrade. On `main` both fail at config
parse with `no such ACL : 'whitelist'` on every HAProxy version, because
the `acl` line sits inside the `with` and `accept if whitelist` does
not:

- `whitelistHTTP: true` with an empty `whitelist` now fails the render
with `whitelistHTTP is enabled but whitelist is empty`. Its HelmRelease
upgrade fails and the release stays on its old revision, which is
already crash-looping.
- `kubernetesAndTalos` with an empty `whitelist` now starts, and ports
6443 and 50000 accept any source. With `external: true` the Service is a
LoadBalancer and carries both ports. `whitelist` is the only switch
those frontends have, so an empty list means no filtering.

Every other input renders the same config apart from the backend names.
The image and the `checksum/config` annotation change, so the Deployment
rolls, and for releases already crash-looping on `latest` the rollout is
the fix.

Validation: renders of `main` and of this branch for the default,
whitelist and empty-whitelist inputs were checked with `haproxy -c` on
2.9.7 and 3.4.4. `helm unittest .` passes 9/9, and removing the `reject`
or `accept` line from any single frontend turns a test red.

Fixes #1966

### Screenshots

Not a UI change.

### Downstream repositories

Walked the trigger map against the diff: chart templates, `Chart.yaml`,
the package `Makefile`, `tests/`, and a description-only change in
`values.yaml` with its generated carriers. No field is added, removed or
renamed and no default changes, so nothing in the map fires.

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

### Release note

```release-note
fix(tcp-balancer): rename HAProxy backends and pin the image to the chart appVersion so the balancer starts on HAProxy 3.3+. whitelistHTTP with an empty whitelist now fails the render; kubernetesAndTalos with an empty whitelist leaves ports 6443 and 50000 unfiltered.
```
@lexfrei

Copy link
Copy Markdown
Contributor

This is fixed on main by #4366, merged as 12cc48d. It renames the backends to *_backend, pins HAProxy and fixes the whitelist guards. Closing as superseded, thanks for the work on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/networking Issues or PRs related to networking (ingress, gateway, vpn, metallb, kube-ovn) 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.

tcp-balancer: HAProxy 3.3 breaks due to frontend/backend name collision

6 participants