Tag: kubernetes

  • Home Automation – Kubernetes Style

    Home Automation – Kubernetes Style

    I’ve been using Smartthings as my smart home hub for a while. And I’d like to migrate to something that’s open source (or more importantly, self-hosted). There’s been a few horror stories out there that make me worry about the potential “hostage” situation. (e.g. manufacturers charging a monthly price for the service, or flat-out discontinuing the service).

    Hardware

    Image 31 - Dell Wyse N03D Thin Client Celeron CPU N2807 1.58GHz 16GB SSD, 4GB DDR3 (NEW)
    Dell Wyse N03D
    Z-Wave + Zigbee Dongle

    I bought a Dell Wyse N03D Thin Client off eBay at $35 each, complete with power supply, keyboard and mouse. The thin client is definitely not a powerhouse, but it’s dual core x86-64 processor and 4GB of RAM should be plenty sufficient for my use case. To let it connect to Z-Wave and ZigBee devices, I also paired it with a dongle.

    Software

    OS

    The thin client came with Windows 7 Embedded pre-installed, which I absolutely don’t need. I replaced it with a fresh install of Ubuntu Server 20.04 LTS. As the thin client only has 16G of onboard storage, I modified the default partitioning scheme to get more space to the rootfs.

    Kubernetes

    I chose k3s for this project. It’s small size is a perfect fit. For the installation, running the following snippet is sufficient.

    curl -sfL https://get.k3s.io | sh -

    Running rancher is always a good idea. To have rancher installed on k3s, add the following manifest to /var/lib/rancher/k3s/server/manifests

    ---
    apiVersion: v1
    kind: Namespace
    metadata:
      name: cattle-system
    ---
    apiVersion: helm.cattle.io/v1
    kind: HelmChart
    metadata:
      name: rancher
      namespace: kube-system
    spec:
      chart: https://releases.rancher.com/server-charts/stable/rancher-2.5.8.tgz
      targetNamespace: cattle-system
      valuesContent: |-
        hostname: [REDACTED]
        tls: external
        replicas: 1

    This works because k3s comes with a helm CRD.

    Following that, apply the following manifest to get home-assistant and its friends installed.

    ---
    apiVersion: v1
    kind: Namespace
    metadata:
      name: home-assistant
    ---
    apiVersion: v1
    kind: Service
    metadata:
      namespace: home-assistant
      name: home-assistant
    spec:
      selector:
        app: home-assistant
      ports:
      - name: http
        protocol: TCP
        port: 80
        targetPort: 8123
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      namespace: home-assistant
      name: home-assistant
      labels:
        app: home-assistant
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: home-assistant
      template:
        metadata:
          labels:
            app: home-assistant
        spec:
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: kubernetes.io/hostname
                    operator: In
                    values:
                    - homelab-us-east-1-nano-1
          containers:
          - name: home-assistant
            image: homeassistant/home-assistant:stable
            ports:
            - containerPort: 8123
            volumeMounts:
            - mountPath: /config
              name: config
            - mountPath: /dev/ttyUSB1
              name: zigbee
            securityContext:
              privileged: true
          volumes:
          - name: config
            hostPath:
              path: /etc/home-assistant
              type: DirectoryOrCreate
          - name: zigbee
            hostPath:
              path: /dev/ttyUSB1
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      namespace: home-assistant
      name: home-assistant
    spec:
      rules:
      - host: [REDACTED]
        http:
          paths:
          - pathType: Prefix
            path: /
            backend:
              service:
                name: home-assistant
                port:
                  number: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      namespace: home-assistant
      name: zwavejs2mqtt
    spec:
      selector:
        app: zwavejs2mqtt
      type: NodePort
      ports:
      - name: http
        protocol: TCP
        port: 8091
        targetPort: 8091
        nodePort: 30091
      - name: ws
        protocol: TCP
        port: 3000
        targetPort: 3000
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      namespace: home-assistant
      name: zwavejs2mqtt
      labels:
        app: zwavejs2mqtt
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: zwavejs2mqtt
      template:
        metadata:
          labels:
            app: zwavejs2mqtt
        spec:
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: kubernetes.io/hostname
                    operator: In
                    values:
                    - homelab-us-east-1-nano-1
          containers:
          - name: zwavejs2mqtt
            image: zwavejs/zwavejs2mqtt:4.5.1
            ports:
            - containerPort: 8091
            - containerPort: 3000
            volumeMounts:
            - mountPath: /usr/src/app/store
              name: config
            - mountPath: /dev/ttyUSB0
              name: zwave
            securityContext:
              privileged: true
          volumes:
          - name: config
            hostPath:
              path: /etc/zwavejs2mqtt
              type: DirectoryOrCreate
          - name: zwave
            hostPath:
              path: /dev/ttyUSB0

    Done

    I also used Cloudflare Argo tunnel to allow me to control my home automation outside of my house.