PMM-15394 Let HAProxy start without waiting for every PMM replica - #937
Merged
Conversation
The HAProxy pod ran an init container that required every PMM replica to answer HTTP 200 before HAProxy could start, and exited 1 after five minutes - so the pod CrashLoopBackOffs at Init:0/1 and HAProxy never starts at all. Every fresh install races this, and the chart guarantees it will. The StatefulSet uses the default OrderedReady policy, so pmm-ha-1 is created only after pmm-ha-0 is Ready and pmm-ha-2 only after pmm-ha-1. For most of the five-minute budget the later replicas do not exist, their names do not resolve, and curl returns 000. PMM Server is a multi-GB image that also runs database migrations on first boot, so three replicas started one after another routinely exceed the budget. PMM-15202 is this failure, closed as Not a Bug. The gate was also redundant. haproxy.cfg carries "init-addr last,libc,none", so a backend whose name does not resolve is held with no address rather than aborting startup, and "http-check expect status 200" against /v1/server/leaderHealthCheck brings it UP only once it is genuinely serving. HAProxy running before any PMM pod exists is the designed behaviour: it returns 503 until a backend is up, which beats not running. The init container added no capability - it only turned "HAProxy up, no backends yet" into "no HAProxy". Verified on a live 3-replica cluster. Before the change HAProxy was already serving with seven of ten server-template slots in MAINT (resolution), i.e. unresolved names. After removing the init container, deleting a follower and restarting HAProxy in the same moment brought all three pods to 1/1 Running in under ten seconds with zero restarts, and PMM stayed reachable throughout. The chart's own init script, run unmodified against two absent replicas, exits 1 while three healthy replicas are serving. Removing it also drops the alpine:latest image and its "apk add --no-cache curl" at every HAProxy start, which required egress to the Alpine mirrors. Signed-off-by: theTibi <tkorocz@gmail.com>
theTibi
marked this pull request as ready for review
August 27, 2026 20:15
theTibi
requested review from
4nte and
ademidoff
and removed request for
a team
August 27, 2026 20:15
theTibi
added a commit
to theTibi/percona-helm-charts
that referenced
this pull request
Aug 28, 2026
percona#937 (PMM-15394) removes templates/haproxy-init-configmap.yaml and the haproxy.initContainers readiness gate. This PR referenced it in three places, so merging both would have failed the ha-peers suite and left stale docs: - tests/ha-peers_test.yaml: dropped the template from the suite and the data["wait-for-pmm.sh"] assertion. - values.yaml, README.md: the HAProxy ConfigMap note now describes the one ConfigMap left after percona#937 - haproxy.cfg, which carries maxReplicas. After percona#937 only one value is embedded in an HAProxy ConfigMap, so the guidance gets simpler rather than weaker. Signed-off-by: theTibi <tkorocz@gmail.com>
JiriCtvrtka
approved these changes
Sep 3, 2026
The only conflict was modify/delete on charts/pmm-ha/templates/haproxy-init-configmap.yaml: PMM-15151 (percona#868) renamed .Release.Name to pmm.fullname in the wait-for-pmm.sh host loop, in the same file this branch removes. Resolved by keeping the deletion - the script's only consumer was the wait-for-pmm-ready init container, which this branch also drops, and nothing else in the chart references the ConfigMap. Also removed pmm-ha-haproxy-init-script from the list of fixed-name namespaced objects in the pmm-ha-dependencies README, since that ConfigMap is no longer created. Signed-off-by: theTibi <tkorocz@gmail.com>
theTibi
requested review from
DhruthiKV,
egegunes,
eleo007,
gkech,
hors,
jvpasinatto,
mayankshah1607,
nmarukovich,
oksana-grishchenko,
pooknull and
valmiranogueira
as code owners
September 3, 2026 21:08
PMM-15151 (percona#868) added a lint-test step asserting that the wait-for-pmm.sh host loop renders pmm_host="<fullname>-$i..." - an assertion on the very file this branch deletes, so it failed the moment PMM-HA-GA was merged in. Git saw no conflict because the assertion and the deletion live in different files. HAProxy no longer builds per-pod names at all: it resolves backends through the headless service with server-template + init-addr, so there is nothing left to assert. The PMM_HA_PEERS half of the check, which does still build per-pod names from pmm.fullname, is kept as-is. Signed-off-by: theTibi <tkorocz@gmail.com>
theTibi
added a commit
to theTibi/percona-helm-charts
that referenced
this pull request
Sep 3, 2026
Two conflicts, both from work that landed on PMM-HA-GA after this branch forked: - charts/pmm-ha/Chart.yaml: percona#937 bumped 1.6.1 -> 1.6.2 and appVersion to "3.9.1" while this branch bumped to 1.7.0. Kept 1.7.0 (still ahead of 1.6.2, and the render-breaking even-replicas check justifies the minor) with appVersion "3.9.1". - charts/pmm-ha/templates/haproxy-init-configmap.yaml: percona#937 (PMM-15394) deleted the file; this branch had fixed its pmm_host loop to use pmm.fullname. Took the deletion - the fix has nothing left to apply to. Nothing references the ConfigMap, the init container or wait-for-pmm.sh any more. Silent, non-conflicting overlaps checked by hand: - _helpers.tpl pmm.haPeers: percona#868 (PMM-15151) landed the same .Release.Name -> pmm.fullname fix, and this branch had already adopted that block verbatim, so the merge is a no-op there. The peer-addressing suite stays as a regression guard. - README.md: dropped the upgrade bullet announcing the PMM_HA_PEERS change. It ships in 1.6.2 via percona#868, so attributing it to 1.7.0 is now wrong. The even-replicas breaking change is unchanged. - ci/ci-values.yaml: percona#946 (PMM-15441) rewrote the file and already sets clickhouse.keeper.replicasCount, so this branch's fix for the ignored clickhouse.keeper.replicas key is subsumed. - The new examples/ and docs/SIZING.md from percona#935 set no PMM replicas value, so the new validators do not reject them. helm unittest: 3 suites, 27 tests passed. Renders verified against the merged tree - replicas=4, replicas=12 and clickhouse.keeper.replicasCount=2 all fail with the intended messages. Signed-off-by: theTibi <tkorocz@gmail.com>
theTibi
added a commit
to theTibi/percona-helm-charts
that referenced
this pull request
Sep 3, 2026
Resolve charts/pmm-ha/values.yaml against PMM-15394 (percona#937), which removed the HAProxy init container while this branch was rewriting the same block. Keep from PMM-15393: topologySpreadConstraints and the PodDisruptionBudget that replace the required podAntiAffinity, so replicaCount can exceed the worker-node count without leaving pods Pending. Take from PMM-15394: the removal of haproxy.initContainers and the extraVolumes that mounted pmm-ha-haproxy-init-script. That ConfigMap template is deleted on PMM-HA-GA, so keeping the init container would mount a ConfigMap that no longer exists and block HAProxy startup. Its explanatory comment is preserved. Signed-off-by: theTibi <tkorocz@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PMM-15394
Removes the HAProxy init container. That is the whole change —
init-addr last,libc,noneis already inhaproxy.cfgtoday, so nothing is added.The gate turns a healthy cluster into no ingress
templates/haproxy-init-configmap.yamlrequired every PMM replica to answer HTTP 200 before HAProxy could start, thenexit 1after 60 attempts at 5s. The pod CrashLoopBackOffs atInit:0/1and HAProxy never starts.Every fresh install races this, and the chart guarantees it will. The StatefulSet has no
podManagementPolicy, so it defaults toOrderedReady:pmm-ha-1is created only oncepmm-ha-0is Ready, andpmm-ha-2only oncepmm-ha-1is. For most of the five-minute budget the later replicas do not exist — no pod, no IP, no DNS record — andcurlreturns000. PMM Server is a multi-GB image that also runs database migrations on first boot, so three replicas started one after another routinely exceed it.PMM-15202 is this failure: all three HAProxy pods at
Init:0/1with ~100 restarts over 11 hours. Closed as Not a Bug after the reporter reinstalled with more resources.It was also redundant
init-addr … noneholds a slot with no address instead of aborting startup when the name does not resolve;resolvers k8spicks it up later;http-check expect status 200against/v1/server/leaderHealthCheckbrings it UP only once it is genuinely serving. HAProxy running before any PMM pod exists is the designed behaviour — it returns 503 until a backend is up, which beats not running.The init container added no capability. It only converted "HAProxy up, no backends yet" into "no HAProxy at all".
Verified on a live cluster
Before — HAProxy was already serving with 7 of 10 slots holding unresolvable names:
The gate, run unmodified from the live ConfigMap against two absent replicas:
Three healthy replicas serving, and it still fails.
After — deleted a follower and restarted HAProxy in the same moment:
Rollout complete in ~47s, zero restarts,
readyzandleaderHealthCheck200 throughout. A follower was targeted deliberately so Raft quorum held at 2/3.Changes
templates/haproxy-init-configmap.yamlvalues.yamlhaproxy.initContainersandhaproxy.extraVolumes— that volume only ever fed the scriptChart.yamlVerified locally:
helm lintclean, rendered manifests drop 38 → 37 (the removed ConfigMap), the HAProxy Deployment renders noinitContainers, and bothinit-addr last,libc,noneand the leader health check are still present.Notes for reviewers
Version.
1.6.0→1.6.2..github/ct.yamlsetstarget-branch: main, soct lint --check-version-increment=truecompares against main, which is already at1.6.1— a bump to1.6.1here would fail the check, and1.6.0would read as a decrement. Worth noting that #935 currently carries noChart.yamlbump and last passed CI before main moved to1.6.1; it will likely hit the same check on its next run.Interaction with #936. That PR (targeting
main) fixes a line in the file this one deletes — its HAProxy readiness probe addressed pods by.Release.Namerather than the StatefulSet name. Whichever lands second resolves trivially in favour of the deletion.Test coverage. The
helm unittestharness lives in #936 againstmain. Once the bases converge I will add a suite asserting HAProxy renders no init container and thatinit-addr … noneplus the leader health check stay inhaproxy.cfg, so this cannot silently come back.Also fixed for free
The init container was
alpine:latestrunningapk add --no-cache curlat every start, so HAProxy could not start without egress to the Alpine package mirrors. Air-gapped and restricted clusters are affected.Not in scope
podManagementPolicy: Parallelwould remove the serialized startup that makes the budget impossible in the first place, and is arguably right for a Raft cluster wherepmm-ha-0currently has to reach Ready with no peers. It is an immutable StatefulSet field, so flipping it breakshelm upgradeon every existing install and needs a documented--cascade=orphanrecreate. Worth its own ticket; this change does not depend on it.🤖 Generated with Claude Code