diff --git a/kubernetes/apps/authentik/blueprints-configmap.yaml b/kubernetes/apps/authentik/blueprints-configmap.yaml index 221f5b7b..775cd638 100644 --- a/kubernetes/apps/authentik/blueprints-configmap.yaml +++ b/kubernetes/apps/authentik/blueprints-configmap.yaml @@ -131,7 +131,7 @@ data: state: absent # shelly-manager.home.renner.uno is gated by authentik-gate-sync - # (kubernetes/apps/home-assistant/shelly-manager-ingress.yaml), which + # (kubernetes/apps/home-assistant-iot/shelly-manager-ingress.yaml), which # admits this group. Members are managed in Authentik. - model: authentik_core.group identifiers: diff --git a/kubernetes/apps/home-assistant-iot/kustomization.yaml b/kubernetes/apps/home-assistant-iot/kustomization.yaml new file mode 100644 index 00000000..ea19f14c --- /dev/null +++ b/kubernetes/apps/home-assistant-iot/kustomization.yaml @@ -0,0 +1,35 @@ +# The home-assistant workloads attached to the IoT VLAN (v30iot). Separate from +# ../home-assistant so that HA and what depends on it do not wait on a VLAN +# the node may not have; the pods run only where it does +# (net.renner.uno/iot-vlan). +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - shelly-manager-pvc.yaml + - shelly-manager-network-attachment.yaml + - shelly-manager-firmware-rbac.yaml + - shelly-ble-proxy-key-externalsecret.yaml + # shelly-manager-auth comes from ../home-assistant: mqtt-account-controller + # mounts it too, and that Kustomization comes first. + - shelly-manager-llat-externalsecret.yaml + - shelly-manager-deployment.yaml + - shelly-manager-service.yaml + - shelly-manager-ingress.yaml + # mDNS relay — carries IoT-VLAN announcements into HA's zeroconf listener as + # unicast, which is the only direction the CNI will move them. Without it HA + # never learns that a device's DHCP lease moved. See the header comment in + # mdns-relay-deployment.yaml. + - mdns-relay-network-attachment.yaml + - mdns-relay-service.yaml + - mdns-relay-deployment.yaml +configMapGenerator: + # shelly-manager api-proxy sidecar config (REN-935). Hash suffix disabled + # (name stays stable), so editing shelly-manager-api-proxy.conf does not + # auto-roll the pod — restart manually with + # `kubectl rollout restart deploy/shelly-manager -n home-assistant`. + - name: shelly-manager-api-proxy + namespace: home-assistant + files: + - api.conf.template=shelly-manager-api-proxy.conf +generatorOptions: + disableNameSuffixHash: true diff --git a/kubernetes/apps/home-assistant/mdns-relay-deployment.yaml b/kubernetes/apps/home-assistant-iot/mdns-relay-deployment.yaml similarity index 98% rename from kubernetes/apps/home-assistant/mdns-relay-deployment.yaml rename to kubernetes/apps/home-assistant-iot/mdns-relay-deployment.yaml index cceabccb..a981372a 100644 --- a/kubernetes/apps/home-assistant/mdns-relay-deployment.yaml +++ b/kubernetes/apps/home-assistant-iot/mdns-relay-deployment.yaml @@ -47,6 +47,9 @@ spec: homelab.renner.uno/restarted-for: "2026-10-06 cni-plugins v1.9.1 attach check" k8s.v1.cni.cncf.io/networks: mdns-relay-iot spec: + # Runs where the node patch declares the IoT VLAN (ens19). + nodeSelector: + net.renner.uno/iot-vlan: "true" enableServiceLinks: false securityContext: runAsNonRoot: true diff --git a/kubernetes/apps/home-assistant/mdns-relay-network-attachment.yaml b/kubernetes/apps/home-assistant-iot/mdns-relay-network-attachment.yaml similarity index 100% rename from kubernetes/apps/home-assistant/mdns-relay-network-attachment.yaml rename to kubernetes/apps/home-assistant-iot/mdns-relay-network-attachment.yaml diff --git a/kubernetes/apps/home-assistant/mdns-relay-service.yaml b/kubernetes/apps/home-assistant-iot/mdns-relay-service.yaml similarity index 100% rename from kubernetes/apps/home-assistant/mdns-relay-service.yaml rename to kubernetes/apps/home-assistant-iot/mdns-relay-service.yaml diff --git a/kubernetes/apps/home-assistant/shelly-ble-proxy-key-externalsecret.yaml b/kubernetes/apps/home-assistant-iot/shelly-ble-proxy-key-externalsecret.yaml similarity index 100% rename from kubernetes/apps/home-assistant/shelly-ble-proxy-key-externalsecret.yaml rename to kubernetes/apps/home-assistant-iot/shelly-ble-proxy-key-externalsecret.yaml diff --git a/kubernetes/apps/home-assistant/shelly-manager-api-proxy.conf b/kubernetes/apps/home-assistant-iot/shelly-manager-api-proxy.conf similarity index 100% rename from kubernetes/apps/home-assistant/shelly-manager-api-proxy.conf rename to kubernetes/apps/home-assistant-iot/shelly-manager-api-proxy.conf diff --git a/kubernetes/apps/home-assistant/shelly-manager-deployment.yaml b/kubernetes/apps/home-assistant-iot/shelly-manager-deployment.yaml similarity index 97% rename from kubernetes/apps/home-assistant/shelly-manager-deployment.yaml rename to kubernetes/apps/home-assistant-iot/shelly-manager-deployment.yaml index 1ef51599..a3335472 100644 --- a/kubernetes/apps/home-assistant/shelly-manager-deployment.yaml +++ b/kubernetes/apps/home-assistant-iot/shelly-manager-deployment.yaml @@ -47,10 +47,10 @@ spec: spec: # eth0 (Cilium-managed pod network) is still the primary — it # carries the ingress, mosquitto LB return path, etc. The macvlan - # above is additive. No explicit edge exclusion is needed: the - # `workload-class=pinned:NoSchedule` taint on k8s-edge already - # keeps this pod off there (we never tolerate it), and the NAD's - # `master: ens19` (stable predictable name for the v30iot NIC) is present on every k8s-{1,2,3} worker. + # above is additive. + # Runs where the node patch declares the IoT VLAN (ens19). + nodeSelector: + net.renner.uno/iot-vlan: "true" enableServiceLinks: false # Grants shelly-manager the in-cluster identity used by the firmware # pipeline to create esphome flash Jobs and stream their logs. RBAC is diff --git a/kubernetes/apps/home-assistant/shelly-manager-firmware-rbac.yaml b/kubernetes/apps/home-assistant-iot/shelly-manager-firmware-rbac.yaml similarity index 100% rename from kubernetes/apps/home-assistant/shelly-manager-firmware-rbac.yaml rename to kubernetes/apps/home-assistant-iot/shelly-manager-firmware-rbac.yaml diff --git a/kubernetes/apps/home-assistant/shelly-manager-ingress.yaml b/kubernetes/apps/home-assistant-iot/shelly-manager-ingress.yaml similarity index 100% rename from kubernetes/apps/home-assistant/shelly-manager-ingress.yaml rename to kubernetes/apps/home-assistant-iot/shelly-manager-ingress.yaml diff --git a/kubernetes/apps/home-assistant/shelly-manager-llat-externalsecret.yaml b/kubernetes/apps/home-assistant-iot/shelly-manager-llat-externalsecret.yaml similarity index 100% rename from kubernetes/apps/home-assistant/shelly-manager-llat-externalsecret.yaml rename to kubernetes/apps/home-assistant-iot/shelly-manager-llat-externalsecret.yaml diff --git a/kubernetes/apps/home-assistant/shelly-manager-network-attachment.yaml b/kubernetes/apps/home-assistant-iot/shelly-manager-network-attachment.yaml similarity index 100% rename from kubernetes/apps/home-assistant/shelly-manager-network-attachment.yaml rename to kubernetes/apps/home-assistant-iot/shelly-manager-network-attachment.yaml diff --git a/kubernetes/apps/home-assistant/shelly-manager-pvc.yaml b/kubernetes/apps/home-assistant-iot/shelly-manager-pvc.yaml similarity index 100% rename from kubernetes/apps/home-assistant/shelly-manager-pvc.yaml rename to kubernetes/apps/home-assistant-iot/shelly-manager-pvc.yaml diff --git a/kubernetes/apps/home-assistant/shelly-manager-service.yaml b/kubernetes/apps/home-assistant-iot/shelly-manager-service.yaml similarity index 100% rename from kubernetes/apps/home-assistant/shelly-manager-service.yaml rename to kubernetes/apps/home-assistant-iot/shelly-manager-service.yaml diff --git a/kubernetes/apps/home-assistant/kustomization.yaml b/kubernetes/apps/home-assistant/kustomization.yaml index 6ffb8cd1..088d1d22 100644 --- a/kubernetes/apps/home-assistant/kustomization.yaml +++ b/kubernetes/apps/home-assistant/kustomization.yaml @@ -21,26 +21,11 @@ resources: - mosquitto-iot-service.yaml - mosquitto-deployment.yaml - mosquitto-evcc-credentials-externalsecret.yaml - - shelly-manager-pvc.yaml - - shelly-manager-network-attachment.yaml - - shelly-manager-firmware-rbac.yaml - - shelly-ble-proxy-key-externalsecret.yaml - - shelly-manager-auth-externalsecret.yaml - - shelly-manager-llat-externalsecret.yaml - - shelly-manager-deployment.yaml - - shelly-manager-service.yaml - - shelly-manager-ingress.yaml + # shelly-manager and the mDNS relay sit on the IoT VLAN: ../home-assistant-iot. - esphome-pvc.yaml - esphome-deployment.yaml - esphome-service.yaml - esphome-ingress.yaml - # mDNS relay — carries IoT-VLAN announcements into HA's zeroconf listener as - # unicast, which is the only direction the CNI will move them. Without it HA - # never learns that a device's DHCP lease moved. See the header comment in - # mdns-relay-deployment.yaml. - - mdns-relay-network-attachment.yaml - - mdns-relay-service.yaml - - mdns-relay-deployment.yaml # Zigbee2MQTT — ZHA replacement bridge. Ships scaled to 0; the cutover # runbook (zigbee2mqtt-migration-runbook.md) scales it up. The MQTT # `zigbee2mqtt` broker user is provisioned by mosquitto-bootstrap.yaml @@ -66,6 +51,8 @@ resources: # Register: mqtt-accounts.yaml (configMapGenerator). - mosquitto-dynsec-test.yaml - mqtt-account-controller.yaml + # Also mounted by shelly-manager (../home-assistant-iot), which runs after this. + - shelly-manager-auth-externalsecret.yaml configMapGenerator: # nginx config for the reverse-proxy sidecar. Hash suffix disabled so # the cm name stays stable; editing proxy.conf does not auto-roll the @@ -116,13 +103,5 @@ configMapGenerator: namespace: home-assistant files: - mqtt-accounts.yaml - # shelly-manager api-proxy sidecar config (REN-935). Hash suffix disabled - # (name stays stable), so editing shelly-manager-api-proxy.conf does not - # auto-roll the pod — restart manually with - # `kubectl rollout restart deploy/shelly-manager -n home-assistant`. - - name: shelly-manager-api-proxy - namespace: home-assistant - files: - - api.conf.template=shelly-manager-api-proxy.conf generatorOptions: disableNameSuffixHash: true diff --git a/kubernetes/apps/matter-server/deployment.yaml b/kubernetes/apps/matter-server/deployment.yaml index 9621177d..2587aec9 100644 --- a/kubernetes/apps/matter-server/deployment.yaml +++ b/kubernetes/apps/matter-server/deployment.yaml @@ -32,11 +32,9 @@ spec: # OTBR via OTBR's ClusterIP Service). The macvlan attachment # above is additive, not a replacement. # - # No nodeSelector/toleration: this pod only needs v30iot (present - # on all nodes), not the edge USB devices. Dropping the - # workload-class=pinned toleration lets the edge taint keep it off - # the (tiny) edge box, reserving that node for the USB-bound - # home-assistant + zwave-js pods. + # Runs where the node patch declares the IoT VLAN (ens19). + nodeSelector: + net.renner.uno/iot-vlan: "true" containers: - name: matter-server # Use the HAOS-published image from `ghcr.io/matter-js/...`, diff --git a/kubernetes/apps/monitoring-rules/probes-blackbox.yaml b/kubernetes/apps/monitoring-rules/probes-blackbox.yaml index f2009161..83df9a47 100644 --- a/kubernetes/apps/monitoring-rules/probes-blackbox.yaml +++ b/kubernetes/apps/monitoring-rules/probes-blackbox.yaml @@ -269,9 +269,9 @@ spec: # per the app's own test (shelly-manager repo, # AuthenticationTests.Health_IsUnauthenticated); it is also the pod's # kubelet liveness/readiness path - # (../home-assistant/shelly-manager-deployment.yaml). AllowedHosts is + # (../home-assistant-iot/shelly-manager-deployment.yaml). AllowedHosts is # "*", so the cluster-local Host header is accepted. Service :80 -> - # container :8080 (../home-assistant/shelly-manager-service.yaml). + # container :8080 (../home-assistant-iot/shelly-manager-service.yaml). # # NO CiliumNetworkPolicy change: the home-assistant default-deny # admits the whole monitoring namespace on every port diff --git a/kubernetes/apps/music-assistant/deployment.yaml b/kubernetes/apps/music-assistant/deployment.yaml index 4dcecdb3..828ddd4e 100644 --- a/kubernetes/apps/music-assistant/deployment.yaml +++ b/kubernetes/apps/music-assistant/deployment.yaml @@ -33,12 +33,9 @@ spec: k8s.v1.cni.cncf.io/networks: music-assistant-iot spec: enableServiceLinks: false - # No nodeSelector/toleration: MA only needs a node on v30iot (all - # of them) for audio-sync L2, not the edge USB devices. It's the - # heaviest of the formerly edge-pinned pods (2Gi limit), so - # dropping the workload-class=pinned toleration — which lets the - # edge taint keep it off the tiny edge box — is the main capacity - # win for this step. + # Runs where the node patch declares the IoT VLAN (ens19). + nodeSelector: + net.renner.uno/iot-vlan: "true" initContainers: # MA advertises a stored publish_ip to players (Sendspin / Snapcast / # SlimProto) and binds its stream + Sendspin servers to a stored diff --git a/kubernetes/apps/otbr/deployment.yaml b/kubernetes/apps/otbr/deployment.yaml index d260664f..25381a25 100644 --- a/kubernetes/apps/otbr/deployment.yaml +++ b/kubernetes/apps/otbr/deployment.yaml @@ -30,11 +30,10 @@ spec: # the IoT VLAN for mDNS/SRP advertisements and RA listening. k8s.v1.cni.cncf.io/networks: otbr-iot spec: - # No nodeSelector/toleration: OTBR only needs v30iot L2 presence - # (macvlan master: ens19, present on every node), not the edge USB - # devices, and its Thread RCP is reached over the network - # (slzb-thread.renner.uno). Dropping the workload-class=pinned - # toleration lets the edge taint keep it off the tiny edge box. + # Runs where the node patch declares the IoT VLAN (ens19). Its Thread + # RCP is reached over the network (slzb-thread.renner.uno). + nodeSelector: + net.renner.uno/iot-vlan: "true" containers: # The Thread RCP is a network-attached radio (Serial-over-IP), so the # spinel transport needs a TCP-to-PTY bridge. Two obvious approaches diff --git a/kubernetes/clusters/homelab/home-assistant.yaml b/kubernetes/clusters/homelab/home-assistant.yaml index d6014835..9c092d1c 100644 --- a/kubernetes/clusters/homelab/home-assistant.yaml +++ b/kubernetes/clusters/homelab/home-assistant.yaml @@ -35,7 +35,7 @@ spec: # it took speech-to-phrase, zone-configurator and matter-server down with # it, since all three wait on home-assistant. - name: infrastructure-cnpg-barman - - name: gitea # shelly-manager, mqtt-account-controller images are in Gitea's registry + - name: gitea # mqtt-account-controller's image is in Gitea's registry - name: influxdb # HA's InfluxDB integration writes there --- apiVersion: kustomize.toolkit.fluxcd.io/v1 @@ -58,6 +58,29 @@ spec: - name: infrastructure-crds - name: infrastructure-ceph-cluster --- +# shelly-manager and the mDNS relay: home-assistant's IoT-VLAN workloads. +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: home-assistant-iot + namespace: flux-system +spec: + interval: 10m + retryInterval: 1m + timeout: 10m + sourceRef: + kind: GitRepository + name: flux-system + path: ./kubernetes/apps/home-assistant-iot + prune: true + wait: true + dependsOn: + - name: infrastructure + - name: infrastructure-crds + - name: infrastructure-ceph-cluster + - name: gitea # shelly-manager's image is in Gitea's registry + - name: home-assistant # both serve HA: its API, its zeroconf listener +--- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: