Enable Auto Discovery for HomeAssistant Running on MicroK8s Kubernetes

Share with:


Running HomeAssistant on MicroK8s Kubernetes is a great way for developers and home users to operate an instance (or several) of HomeAssistant. For information on how setup an instance of HomeAssistant on MicroK8s see my other post here. In this post I will show how to enable the HomeAssistant auto-discover functionality so that it’s easier to discover and integrate with local devices.

HomeAssistant uses a combination of methods to automatically discover devices on a network.

  1. ICMP ping method:
    • Lower-level protocol: ICMP (Internet Control Message Protocol)
    • No specific port is used, but ICMP packets typically use either the ICMP Echo Request message (type 8) or the ICMP Echo Reply message (type 0).
  2. UPnP discovery method:
    • Lower-level protocol: SSDP (Simple Service Discovery Protocol)
    • Port: UDP port 1900 for both source and destination
  3. mDNS/Bonjour discovery method:
    • Lower-level protocol: UDP (User Datagram Protocol)
    • Port: UDP port 5353 for both source and destination

Note that there are other methods not documented here and new methods will continue to be added moving forward. So this is a bit of a moving target.

For the methods which rely on TCP/UDP it’s possible to use the ingress layer to configure each port explicitly. But there are a few notable downsides. First, the ingress layer doesn’t support multicast behavior which is a critical inhibitor for discovery. Second, it doesn’t scale well because it requires new ports to be manually added, though this could also be considered a security feature. Third, it only works for a single deployment per microk8s cluster due to only having one nginx ingess daemon.

Another potential approach is to configure the pod network adapter to use the host level interface. This works well for discovery but can create unexpected conflicts with services running on the host node, and is similarly limited in the number of instances that can use this approach.

The approach below strikes a balance of allowing the pod to have a dedicated network adapter on the smart home network, without being imposed by the limits of the cluster. This should maximize discoverability, allow for mulitple instances per cluster, and if desired, you can lock things down with IP tables within the pod instances.

Step 1: Install Multus Addon

First, we need to enable the multus addon so that we can add network interfaces to the HomeAssistant pod. For ARM64 architecture, the multus addon is currently only supported via the community, and so we must first enable the community addon. Run the following from any cluster node.

microk8s enable community
microk8s enable multus

Next verify the daemonset is running with the following command:

microk8s kubectl get pods -n kube-system --selector=app=multus

Step 2: Create NetworkAttachmentDefinition

First we need to define the NetworkAttachmentDefinition (NAD), save the following template to a file called nad.yaml and adjust the network settings to match your smart device network. The IP range should be free (duh!) and outside of your DHCP range to avoid conficts.

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: lan-network
spec:
  config: '{
    "cniVersion": "0.3.1",
    "name": "lan-network",
    "type": "macvlan",
    "mode": "bridge",
    "master": "eth0",
    "ipam": {
      "type": "host-local",
      "subnet": "192.168.10.0/24",
      "rangeStart": "192.168.10.240",
      "rangeEnd": "192.168.10.241",
      "routes": [
        { "dst": "0.0.0.0/0" }
      ],
      "gateway": "192.168.10.1"
    }
  }'

Step 3: Update Deployment Definition

In this step we need to re-deploy the HomeAssistant instance. Update the deployment yaml configuration to include the annotation detail in the example below. This will cause multus to mount the adapter in the container during the boot sequence.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: homeassist-deployment
  labels:
    app: homeassist
spec:
  replicas: 1
  selector:
    matchLabels:
      app: homeassist
  template:
    metadata:
      labels:
        app: homeassist
      annotations:
        k8s.v1.cni.cncf.io/networks: '[
            {
               "name" : "lan-network",
               "interface": "eth1"
            }
          ]'
...

Delete and redeploy the HomeAssistant deployment (caution: this may delete your instance settings depending on how your pod is configured)

Example deleting and re-creating the deployment:

microk8s.kubectl delete deployment homeassist-deployment
microk8s.kubectl create -f deployment.yaml

Step 4: Enable the lan-network interface

Following the re-deployment from the previous step, the adapter should now be mounted in the container, but it is not yet enabled by HomeAssistant. To enable the new lan-network, we need to first enable admin mode for the user. Login to HomeAssistant and click on your profile name in the lower left corner. Enable “Advanced Mode” on the Profile screen.

Next click on “Settings” and go to “System > Network”. Uncheck the Auto-Configure option, and check the box for the new lan-network Adapter. Leave other settings as-is, scroll down and click “Save” at the bottom.

Step 5: Reboot and Confirm Integration Discovery

In HomeAssistant, navigate to “Developer Tools” and click “Restart > Restart Home Assistant”. Following the reboot, HomeAssistant will start to discover devices on the network, the process can take several minutes per my experience.

Hope this is helpful for others!

Share with:


Leave a Reply

Your email address will not be published. Required fields are marked *

*


The reCAPTCHA verification period has expired. Please reload the page.