The microk8s preset hardcodes metallb:10.64.140.43-10.64.140.49 in its addon list. This range is for Canonical's internal network. On GitHub Actions runners, MetalLB sometimes never allocates a usable LoadBalancer IP from this range within a reasonable wait window. The result is that charms requiring a LoadBalancer (e.g., Traefik in COS Lite) get stuck in blocked state indefinitely.
For a sample failure, see https://github.com/canonical/operator/actions/runs/32157684730/job/95778751483.
The Observability team worked around this by not using Concierge at all. They compute the MetalLB IP dynamically from the runner's own primary IP.
In Ops, I'm planning to avoid the issue by switching to the k8s preset - which we already use in the K8s charm tutorial.
But I think the issue is still worth fixing in Concierge's microk8s provider. Here's what my agent recommends:
-
Auto-detect the MetalLB IP when no range is explicitly configured. Instead of hardcoding 10.64.140.43-10.64.140.49, detect the host's primary IP using ip -4 -j route get 2.2.2.2 | jq -r '.[] | .prefsrc' and use that single IP as the MetalLB range. This is the same approach the Observability team uses in their CI. It works universally because the IP is on the runner's own network interface, so L2 ARP always succeeds. Users who explicitly set a MetalLB range in their config are unaffected.
-
Validate the IPAddressPool after enabling. The microk8s metallb addon creates an IPAddressPool CR and an L2Advertisement. After enabling, check that the IPAddressPool exists and contains the expected addresses. If it doesn't (MetalLB silently discards invalid configs), patch the IPAddressPool directly with the detected IP. This catches the silent-failure cases that make the current bug hard to diagnose.
The
microk8spreset hardcodesmetallb:10.64.140.43-10.64.140.49in its addon list. This range is for Canonical's internal network. On GitHub Actions runners, MetalLB sometimes never allocates a usable LoadBalancer IP from this range within a reasonable wait window. The result is that charms requiring a LoadBalancer (e.g., Traefik in COS Lite) get stuck inblockedstate indefinitely.For a sample failure, see https://github.com/canonical/operator/actions/runs/32157684730/job/95778751483.
The Observability team worked around this by not using Concierge at all. They compute the MetalLB IP dynamically from the runner's own primary IP.
In Ops, I'm planning to avoid the issue by switching to the
k8spreset - which we already use in the K8s charm tutorial.But I think the issue is still worth fixing in Concierge's microk8s provider. Here's what my agent recommends:
Auto-detect the MetalLB IP when no range is explicitly configured. Instead of hardcoding
10.64.140.43-10.64.140.49, detect the host's primary IP usingip -4 -j route get 2.2.2.2 | jq -r '.[] | .prefsrc'and use that single IP as the MetalLB range. This is the same approach the Observability team uses in their CI. It works universally because the IP is on the runner's own network interface, so L2 ARP always succeeds. Users who explicitly set a MetalLB range in their config are unaffected.Validate the IPAddressPool after enabling. The microk8s metallb addon creates an
IPAddressPoolCR and anL2Advertisement. After enabling, check that theIPAddressPoolexists and contains the expected addresses. If it doesn't (MetalLB silently discards invalid configs), patch theIPAddressPooldirectly with the detected IP. This catches the silent-failure cases that make the current bug hard to diagnose.