Point HA peer URLs at per-pod ClusterIP Services #7

Merged
benvin merged 1 commits from benvin/ha-peer-clusterip into main 2026-08-09 19:07:05 +10:00
Owner

Why

kea-dhcp4 crash-loops at HA hook load (kea-0 restartCount 200+). kea 2.6's HA hook parses each peer url host as an IP literal and never resolves DNS, so the StatefulSet headless hostnames are rejected:

HA_CONFIGURATION_FAILED ... bad url 'http://kea-0.kea-headless.dhcp-system:8000/': Failed to convert string to address ...

Proven in-cluster: only an IP works — short name and FQDN both fail; and kea-dhcp4 -t does not exercise HA-hook load, which is why the v0.1.3/#6 -t wait never caught it. Pod IPs cannot be baked into the config (they change on restart and would roll-loop the StatefulSet via the config hash), and config load only needs a valid IP literal (not a reachable peer), so stable ClusterIPs both satisfy the hook and break the HA bootstrap deadlock.

How

  • create one ClusterIP Service per HA peer, selecting the pod by its statefulset.kubernetes.io/pod-name label, with publishNotReadyAddresses so peers are routable during bootstrap
  • render each HA peer url as that peer Service's ClusterIP (a stable IP literal, safe in the config hash); reconcile Services before the ConfigMap and requeue until the ClusterIPs are allocated

Tests: new guards that peer URLs are ClusterIP literals (never kea-headless) and that render requeues until ClusterIPs exist; existing tests seed the per-pod Services.

Ships in the next release (v0.1.4, together with the already-merged #6 initContainer refactor).

## Why kea-dhcp4 crash-loops at HA hook load (kea-0 restartCount 200+). kea 2.6's HA hook parses each peer `url` host as an **IP literal and never resolves DNS**, so the StatefulSet headless hostnames are rejected: ``` HA_CONFIGURATION_FAILED ... bad url 'http://kea-0.kea-headless.dhcp-system:8000/': Failed to convert string to address ... ``` Proven in-cluster: only an IP works — short name **and** FQDN both fail; and `kea-dhcp4 -t` does not exercise HA-hook load, which is why the v0.1.3/#6 `-t` wait never caught it. Pod IPs cannot be baked into the config (they change on restart and would roll-loop the StatefulSet via the config hash), and config *load* only needs a valid IP literal (not a reachable peer), so stable ClusterIPs both satisfy the hook and break the HA bootstrap deadlock. ## How - create one **ClusterIP Service per HA peer**, selecting the pod by its `statefulset.kubernetes.io/pod-name` label, with `publishNotReadyAddresses` so peers are routable during bootstrap - render each HA peer `url` as that peer Service's **ClusterIP** (a stable IP literal, safe in the config hash); reconcile Services before the ConfigMap and requeue until the ClusterIPs are allocated Tests: new guards that peer URLs are ClusterIP literals (never `kea-headless`) and that render requeues until ClusterIPs exist; existing tests seed the per-pod Services. Ships in the next release (v0.1.4, together with the already-merged #6 initContainer refactor).
unkinben added 1 commit 2026-08-09 18:59:35 +10:00
Point HA peer URLs at per-pod ClusterIP Services
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
66ae5f5f3c
## Why
kea-dhcp4 crash-loops at HA hook load: kea 2.6's HA hook parses each peer url host as an IP literal and never resolves DNS, so the StatefulSet headless hostnames are rejected ("Failed to convert string to address ..."). Verified in-cluster that only an IP works (short name, FQDN both fail; `kea-dhcp4 -t` does not exercise this, which is why the v0.1.3 wait did not catch it). Pod IPs cannot be baked into the config because they change on restart and would roll-loop the StatefulSet via the config hash.

## How
- create one ClusterIP Service per HA peer, selecting the pod by its statefulset.kubernetes.io/pod-name label, with publishNotReadyAddresses so peers are routable during bootstrap
- render each HA peer url as its peer Service ClusterIP (a stable IP literal, safe in the config hash); reconcile Services before the ConfigMap and requeue until the ClusterIPs are allocated
benvin merged commit 7bc380eef8 into main 2026-08-09 19:07:05 +10:00
benvin deleted branch benvin/ha-peer-clusterip 2026-08-09 19:07:05 +10:00
Sign in to join this conversation.