HAProxy versions¶
Overview¶
HAPTIC supports multiple HAProxy major.minor series simultaneously. The haproxyVersion value selects the series and controls two things:
- The controller image tag suffix (for example
-haproxy3.2) — must match a version built by CI - The HAProxy pod image tag — defaults to the latest tested patch for that series
The controller image uses major.minor only (-haproxy3.2, not -haproxy3.2.x) because CI builds one image per supported series. Patch versions within a series are API-compatible with the controller.
Supported versions¶
| Series | Status | Community image | Enterprise image |
|---|---|---|---|
| 3.0 | Supported (LTS) | haproxytech/haproxy-debian:3.0.x |
...:3.0r1 |
| 3.1 | Supported (non-LTS) | haproxytech/haproxy-debian:3.1.x |
...:3.1r1 |
| 3.2 | Supported (LTS) | haproxytech/haproxy-debian:3.2.x |
...:3.2r1 |
| 3.3 | Supported (non-LTS) | haproxytech/haproxy-debian:3.3.x |
— |
| 3.4 | Supported (LTS, default) | haproxytech/haproxy-debian:3.4.x |
— |
HAProxy's even-numbered series (3.0, 3.2, 3.4) are LTS with about five years of support; odd-numbered series (3.1, 3.3) get a shorter maintenance window. The chart's default is always the latest LTS — currently 3.4.
One version, both images
The series above is the HAProxy binary version, and it's the only version
that matters: haproxyVersion picks the HAProxy image and the matching
controller image together, and the agent runs the controller's binary inside
the HAProxy pod. Which runtime commands a pod accepts follows that pod's own
HAProxy release, which the agent reports. Config syntax is validated against
the matching HAProxy binary via haproxy -c, which is why a per-series
controller image exists.
During a rolling upgrade the fleet can briefly run two series. HAPTIC renders for the lowest version it sees, and a pod whose agent it cannot compose ops for gets the complete file set plus a reload — never a refusal.
Feature version requirements¶
Most chart features work on every supported series. A few require a minimum HAProxy series:
| Feature | Minimum series | Behavior below the minimum |
|---|---|---|
| SSL/TLS termination, CRT-list management, OCSP stapling | 3.0 | Not applicable — 3.0 is the minimum supported series |
SPOA hub native transport (mode spop) |
3.1 | Auto-falls back to mode tcp; the hub still works |
Reload-free server adds (add server ... init-state) |
3.1 | A new server still joins, but the pod reloads to pick it up |
Reload-free route adds and removals (add backend / del backend) |
3.4 | Routes still work, but adding or removing one reloads the pod |
Shared-memory stats persistence (shm-stats-file) |
3.3 | Silently omitted; stats counters reset on every reload |
Only mode spop (3.1) and shm-stats (3.3) gate chart behavior you can't otherwise get. The rest is about what a change costs: 3.1 adds add server ... init-state, so a new server joins without a reload, and 3.4 adds dynamic backends, so adding or removing a route stops reloading altogether.
Selecting a version¶
Set haproxyVersion to your desired series. The chart defaults to 3.4:
# Use HAProxy 3.0 LTS
helm install haptic oci://registry.gitlab.com/haproxy-haptic/haptic/charts/haptic \
--namespace haptic --create-namespace \
--set haproxyVersion=3.0
# Use HAProxy 3.3
helm install haptic oci://registry.gitlab.com/haproxy-haptic/haptic/charts/haptic \
--namespace haptic --create-namespace \
--set haproxyVersion=3.3
Or in your values file:
Patch version pinning¶
By default, the HAProxy pod image is pinned to the latest patch version tested with the chart, looked up from the haproxyPatchVersions map in charts/haptic/values.yaml. For example, with haproxyVersion: "3.2", the pod uses whichever 3.2.x patch the chart currently pins (for example haproxytech/haproxy-debian:3.2.16). The pin moves forward over time as Renovate updates the chart.
To pin a specific patch version yourself, set haproxy.image.tag:
Keeping patches up to date¶
The chart ships with a haproxyPatchVersions map whose entries are kept current by the project's own Renovate setup. Each chart release picks up the latest patch within every series and ships it as the new default. If you don't override haproxy.image.tag, you inherit those patches automatically when you bump the chart.
If you pin haproxy.image.tag yourself in a GitOps repository and want Renovate to track patches within the pinned series, add a regex custom manager to your renovate.json. The trick is to extract the major.minor from the current value and bake it back into the versioning regex so Renovate stays inside the series:
{
"customManagers": [
{
"customType": "regex",
"fileMatch": ["values\\.ya?ml$"],
"matchStrings": [
"# renovate:\\s*datasource=docker\\s+depName=haproxytech/haproxy-debian[^\\n]*\\n\\s*tag:\\s*\"(?<currentValue>(?<seriesMajor>\\d+)\\.(?<seriesMinor>\\d+)\\.\\d+)\""
],
"datasourceTemplate": "docker",
"depNameTemplate": "haproxy-debian {{{seriesMajor}}}.{{{seriesMinor}}}.x",
"packageNameTemplate": "haproxytech/haproxy-debian",
"versioningTemplate": "regex:^(?<major>{{{seriesMajor}}})\\.(?<minor>{{{seriesMinor}}})\\.(?<patch>\\d+)$"
}
]
}
And annotate the override in your values file so the manager can find it:
haproxyVersion: "3.2"
haproxy:
image:
# renovate: datasource=docker depName=haproxytech/haproxy-debian
tag: "3.2.10"
The chart's own renovate.json (source) uses the same pattern against haproxyPatchVersions — it's the working reference if you need a more elaborate setup (for example handling multiple series in one file).
HAProxy Enterprise¶
Enterprise deployments require:
- Setting
haproxy.enterprise.enabled: true - Configuring
haproxy.podSpec.imagePullSecretswith your registry credentials - Building your own controller image and pointing
controller.image.repository(and optionallycontroller.image.tag) at it — the HAPTIC project doesn't distribute enterprise controller images (see the note below)
haproxyVersion: "3.2"
haproxy:
enterprise:
enabled: true
podSpec:
imagePullSecrets:
- name: hapee-registry-secret
With enterprise.enabled: true, an empty haproxy.image.repository selects
hapee-registry.haproxy.com/haproxy-enterprise, and the tag defaults to the
tested revision from haproxyEnterprisePatchVersions (for example 3.2r1).
The same haproxyVersion also derives the Enterprise binary path, so image and
binary series can't drift. The chart fails if the selected series has no tested
Enterprise revision. To use a custom registry or pin a specific revision:
Check HAProxy Enterprise release notes for available revisions.
Building the controller
Enterprise controller images aren't distributed by the HAPTIC project. You must build the controller yourself and push it to your own registry, then set controller.image.repository and optionally controller.image.tag accordingly.
Upgrading to a new series¶
To move from one major.minor to another (for example 3.2 → 3.3):
- Verify the new series is supported in the chart version you are using
- Update
haproxyVersionin your values - Clear any
haproxy.image.tagoverride, or update it to a patch in the new series -
Run
helm upgrade:
The controller and HAProxy pods restart with the new images.
HAProxy rolls without dropping the fleet. The chart runs haproxy.replicaCount pods (2 by default) behind a RollingUpdate strategy set to maxUnavailable: 0 and maxSurge: 1 (haproxy.updateStrategy). Kubernetes starts a new-version pod and waits for it to pass its readiness probe before terminating an old one, so the number of serving pods never drops below the replica count during the roll. Keep haproxy.replicaCount at 2 or more for a no-downtime series bump — a single replica has nowhere to shift traffic while it restarts.