From c2e6f5cd000a848aecd6adb9211c1936d0139a41 Mon Sep 17 00:00:00 2001 From: Konstantin Renner Date: Wed, 13 May 2026 08:30:06 +0200 Subject: [PATCH] cilium(l2-announce): exclude iot-vlan services from default policy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default L2AnnouncementPolicy had no serviceSelector, so iot-vlan services matched both default and iot policies. Leader election then included every node, and the lease for home-assistant-iot landed on k8s-3 — a node with no v30iot interface — making 10.2.30.224 unreachable. Adding a `iot-vlan DoesNotExist` selector keeps the default policy off IoT services so only k8s-edge can hold the lease. Co-Authored-By: Claude Opus 4.7 (1M context) --- kubernetes/infrastructure/post-crds/cilium-l2.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kubernetes/infrastructure/post-crds/cilium-l2.yaml b/kubernetes/infrastructure/post-crds/cilium-l2.yaml index 767793a5..9794b5c1 100644 --- a/kubernetes/infrastructure/post-crds/cilium-l2.yaml +++ b/kubernetes/infrastructure/post-crds/cilium-l2.yaml @@ -9,6 +9,12 @@ spec: - start: fd40::40 stop: fd40::ff --- +# default policy must NOT cover Services labelled `iot-vlan: "true"`. +# Without this exclusion both policies match IoT services, leader +# election runs across all nodes (default has no nodeSelector), and +# the lease can land on a node that has no v30iot interface — making +# the IoT LB IP unreachable until the lease happens to expire onto +# k8s-edge. apiVersion: cilium.io/v2alpha1 kind: CiliumL2AnnouncementPolicy metadata: @@ -18,6 +24,10 @@ spec: externalIPs: true interfaces: - ^eth[0-9]+ + serviceSelector: + matchExpressions: + - key: iot-vlan + operator: DoesNotExist --- # IoT VLAN pool — k8s-edge has a NIC on v30iot, so Services that need to # be addressable from IoT devices that can't do DNS or proxy ingress get