Niet de meest simpele oplossing om Home Assistant te installeren, maar toch… ’ter lering ende vermaeck‘ hieronder een uitleg over mijn Home Assistant installatie zoals ik die in Kubernetes heb geïnstalleerd.
Qua hardware een server die genoeg resources heeft om virtuele machines te draaien, een HP Z800 met 24 cores, 96 Gb geheugen en iets van 3Tb aan SSD disks.
’t Kost wat aan stroomverbruik, zo’n 200 Watt, dus alleen voor Home Assistant kun je beter een Raspberry Pi gebruiken.
Verder is een Sonoff USB dongle op de USB poort aangesloten voor de Zigbee devices, daarover later meer.
Qua software een hypervisor (Proxmox), daarop virtuele machines met Ubuntu en dan Kubernetes. Het beheer van Kubernetes wordt met behulp van Rancher gedaan, er komt dus eerst een Rancher management cluster en daarnaast een apart cluster voor o.a. Home Assistant en bijbehorende add-on’s.
Proxmox Virtual Environment (pve) is een open source platform voor virtualisatie, voorzien van een mooie grafische web-interface voor het beheer.
Zoals gezegd, eerst een Rancher Management cluster bouwen. Dit cluster bestaat uit 3 nodes (VM’s) met 4 CPU cores en 8Gb geheugen. De installatie is beschreven op deze pagina: http://www.digitalinfo.nl/rancher-installatie-rke2/ en hiermee is er een 3-node cluster voor het beheer van zogenaamde ‘downstream clusters‘.
Er zijn allerlei manieren om een downstream cluster uit te rollen, binnen Rancher zijn er een aantal Cluster Providers die ingesteld kunnen worden, zoals bijvoorbeeld Suse Harvester. Aangezien ik hier gebruik maak van Proxmox kan ik met een Ansible script vrij snel een aantal Virtuele Machines aanmaken in Proxmox en deze gebruiken voor het aanmaken van een ‘Custom‘ cluster in Rancher’s Cluster Management.
Mijn configuratie voor het downstream cluster voor Home Assistant bestaat uit 3 nodes, één Kubernetes control-plane/etcd en twee worker-nodes. De cluster heb ik ‘Speeltuin‘ genoemd.
De USB dongle voor het Zigbee netwerk is aangesloten op de USB poort van de Proxmox server en toegevoegd aan de hardware van de VM ‘speeltuin-03‘. Om deze te kunnen onderscheiden van de andere worker-node is een label toegevoegd aan deze node, ‘zigbee-dongle:connected‘.
Services
Om een LoadBalancer te kunnen gebruiken is ‘MetalLB‘ geïnstalleerd van waaruit een IP adres uit het thuisnetwerk gekozen kan worden. Hiervoor is een IPAddressPool aangemaakt waarin de range wordt bepaald. Meer informatie over MetalLB vind je hier: http://www.digitalinfo.nl/raspberry-pi/kubernetes-cluster-via-kubeadm/loadbalancer-met-metallb/
Voor de ClusterIP services van de meeste applicaties wordt een Ingress ingesteld en de externalDNS zal hier een DNS-record aanmaken op mijn piHole DNS server.
Storage
Om ervoor te zorden dat de data die gebruikt wordt door de diverse componenten in Home Assistant, maak ik gebruik van Suse Longhorn om volumes aan te maken op de aangesloten disks. De installatie geschiedt met de Apps vanuit Rancher, de uitleg voor Longhorn configuraties vind je op deze pagina: http://www.digitalinfo.nl/rancher/longhorn/
Tot zover hebben we nu een Rancher Management server voor het beheer van de downstream cluster genaamd ‘speeltuin’. Voor de installatie van applicaties maak ik gebruik van Rancher Fleet. Een uitgebreide uitleg over Fleet vind je hier: http://www.digitalinfo.nl/rancher/continuous-delivery-in-rancher/
GitOps
Via Fleet worden op het nieuwe cluster Cert-manager, externalDNS, Gatekeeper, Longhorn en Monitoring geïnstalleerd. Met de target optie ‘All clusters in the workspace‘ wordt dit automatisch op elk nieuw cluster uitgevoerd.
De GitOps repositories voor Home Assistant heb ik op GitHub geplaatst:
- Home Assistant – https://github.com/NicoOosterwijk/home-assistant-k8s.git
- Mosquitto MQTT Broker – https://github.com/NicoOosterwijk/mosquitto-k8s.git
- Node-RED – https://github.com/NicoOosterwijk/node-red-k8s.git
- Zigbee2MQTT – https://github.com/NicoOosterwijk/zigbee2mqtt-k8s.git
- ESPHome – https://github.com/NicoOosterwijk/esphome-k8s.git
- Frigate – https://github.com/NicoOosterwijk/frigate-k8s.git
Let op! De ingress manifests hebben allen een host voor mijn interne netwerk!
Voor de target ‘kijkt’ Fleet nu naar een label op een cluster dat overeenkomt met de instelling in de Fleet Cluster Group. In die groups zijn als voorwaarde voor installatie ingesteld dat het cluster een bepaald label dient te hebben. Als dat overeenkomt dan wordt in het betreffende cluster de software vanuit de GitRepo geïnstalleerd.
Wijzigingen in een manifest voor één van de software applicaties worden dus uitsluitend via de GitHub repo’s gedaan middels een commit en merge request.
Een overzicht van de GitRepo’s voor het speeltuin-cluster:
Home Assistant is ‘exposed‘ via een IP adres van het thuisnetwerk en kan daardoor via een browser vanaf mijn laptop bereikt worden. De ingress gebruikt als host: ha.digitalinfo.local
Koppelingen
Kubernetes gebruikt een interne DNS voor het bereiken van services en pods. De opbouw van de DNS voor een service is [service-naam].[namespace].svc.cluster.local en daarmee kunnen we de diverse applicatie met elkaar koppelen.
Om vanuit Node-RED de Home Assistant nodes te kunnen bereiken is het nodig om de ‘Home Assistant websocket‘ palette te installeren in Node-RED (rechtsboven hamburger-menu -> Manage palette). Hierna komen dan de Home Assistant nodes beschikbaar maar moet nog wel de Home Assistant server ingesteld worden. Aangezien er tussen de namespaces van de applicaties (nog) geen NetworkPolicy aanwezig is kunnen alle pods bij andere pods en services. Hierdoor is de koppeling eenvoudig te realiseren. De service van Home Assistant heeft de naam ‘ha-lb-svc‘ in de namespace ‘homeassistant‘ en is daarmee via de interne DNS van Kubernetes bereikbaar op ha-lb-svc.homeassistant.svc.cluster.local, samen met een long-lived-token uit Home Assistant.
Op dezelfde manier kan een koppeling gemaakt worden vanuit Node-RED naar de Mosquitto MQTT broker. De heeft als servicenaam ‘mosquitto-svc‘ in de namespace ‘mosquitto‘, dus de servernaam in de mqtt-nodes wordt dan: mosquitto-svc.mosquitto.svc.cluster.local (poort 8883)
Via Home Assistant instellingen -> Integraties kan de MQTT integratie toegevoegd worden aan Home Assistant. Voor de MQTT servernaam wordt dezelfde service-url gebruikt zoals in Node-RED, namelijk mosquitto-svc.mosquitto.svc.cluster.local en ook weer poort 8883.
De Zigbee2MQTT instellingen voor de MQTT server zijn ingesteld via een ConfigMap voor Kubernetes. Deze vind je terug in de GitOps repository en verwijst ook naar de naam van de mosquitto service, mosquitto-svc.mosquitto.svc.cluster.local
The proof is in the pudding…
In Zigbee2MQTT heb ik een Zigbee motionsensor toegevoegd
en deze exposed de sensors naar MQTT en dat kunnen we zien in de Home Assistant integratie voor MQTT:
In Home Assistant kan dan ook een dashboard weergave gemaakt worden met de entiteit kaart voor deze sensor:
Binnen Node-RED kan de status van de sensor een notificatie sturen, bijvoorbeeld naar Home Assistant:
en daarmee is de basis-configuratie gereed. Tijd voor wat beveiliging.
Security
Ik ga een en ander beveiligen met behulp van networkPolicies. Er zijn twee types networkPolicies:
- Ingress – inkomend verkeer
- Egress – Uitgaan verkeer
Standaard is er geen policy voor Ingress, alle inkomend verkeer is toegestaan. Een pod is geïsoleerd voor inkomend verkeer als er een networkPolicy aanwezig is met hierin een verwijzing naar de pods en een policyTypes
genaamd ‘Ingress’. Zodra een pod geïsoleerd is door een networkPolicy kan er alleen verkeer op binnen komen van de node waarin de pod zich bevindt en van pods die expliciet zijn toegestaan in de Ingress-networkPolicy.
Standaard is er geen policy voor Egress, al het uitgaand verkeer is toegestaan. Een pod is geïsoleerd voor uitgaand verkeer als er een networkPolicy aanwezig is met hierin een verwijzing naar de pods en een policyTypes
genaamd ‘Egress’. Zodra een pod geïsoleerd is door een networkPolicy kan er alleen verkeer uitgaan naar de pods die expliciet zijn toegestaan in de Egress-networkPolicy.
Communicatie tussen een source pod en een destination pod geschiedt uitsluitend als er een Egress policy is voor de source pod en een Ingress policy voor de destination pod.
We beginnen met een blokkade (deny) voor al het inkomende verkeer naar de namespace homeassistant: netpol-deny-all-ingress.yml
Hierna staan we inkomend verkeer toe naar de pod met het label ‘app=home-assistant’ komend vanaf specifieke namespaces. Verkeer vanaf andere namespaces wordt dus steeds niet toegestaan. Verder mag alleen naar TCP port 8123 verbonden worden: netpol-ha-allow-namespaces.yml
Om de IoT devices, met name de diverse bridges en gateways, in HA te kunnen gebruiken als integraties, en om met een browser vanaf mijn lokale netwerk de Home Assistant GUI te kunnen bereiken laat ik ook mijn netwerk IP segment toe middels een Network Policy: netpol-ha-allow-ip.yml
Door deze Network Policies toe te voegen aan de Home Assistant GitLab repository in de base, worden ze door Fleet toegevoegd aan de namespace ‘homeassistant’.