Post

Home-Assistant in Kubernetes [First Part - HA Deployment]

You will learn how to install and Deploy Home-Assistant in Kubernetes

Home-Assistant in Kubernetes [First Part - HA Deployment]

Deploy Home-Assistant in Kubernetes [ Deployment ]

One of the most comfortable ways to deploy Home Assistant in a HomeLab is in Docker, but what if we want to go one step further and deploy it in a Kubernetes cluster to make it more resilient? In this post I will explain how I did it.

  • 1.Home-Assistant Deployment in Kubernetes [First Part - Deployment ].
  • 2.Build your own Bastion-SSH for Deployments from GitHub [Second Part - Bastion ].
  • 3.CI Workflow to Update Home-Assistant configuration [Third Part - CI ].

Some of the specifications are the following

  • Kubernetes: 1.30.0 (K0s)
  • StorageClass: Longhorn (Chart 1.7.2)
  • MetalLB (Chart 0.14.5)
  • Nginx Ingress Controller (Chart 4.12.0) - Optional

Steps: We declare each of the parts that make up the deployment

  • Namespace
  • PersistentVolumeClaim
  • StatefulSet
  • Service or LoadBalancer
  • Ingress (Optional to Publish outside)

1.Namespace

1
2
3
4
apiVersion: v1
kind: Namespace
metadata:
  name: home-assistant

2.PersistentVolumeClaim

The type of Storage is ReadWriteMany, due to the approach we will give later for Continuous Integration.

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: home-assistant-pvc
  namespace: home-assistant
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi # Cambia el tamaño según tus necesidades
  storageClassName: longhorn

3.StatefulSet

We can deploy as Deployment or StatefulSet , but I have found the latter more convenient for the container restarts.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: home-assistant
  namespace: home-assistant
spec:
  replicas: 1
  serviceName: "home-assistant"  
  selector:
    matchLabels:
      app: home-assistant
  template:
    metadata:
      labels:
        app: home-assistant    
    spec:
      imagePullSecrets:
      - name: dockerhub-registry    
      containers:
        - name: ha-core
          image: ghcr.io/home-assistant/home-assistant:2025.3.3
          imagePullPolicy: Always
          resources:
            requests:
              memory: "512Mi"
            limits: 
              memory: "2512Mi"       
          ports:
            - containerPort: 8123
          volumeMounts:
            - name: pv-home-assistant
              mountPath: /config      
      volumes:
        - name: pv-home-assistant
          persistentVolumeClaim:
            claimName: home-assistant-pvc

4.LoadBalancer

In this case i am using a LoadBalancer class with MetalLB. Just to have an internal IP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: v1
kind: Service
metadata:
  name: home-assistant
  namespace: home-assistant
spec:
  type: LoadBalancer
  loadBalancerIP: 192.168.2.3
  selector:
    app: home-assistant
  ports:
    - name: http-initial
      protocol: TCP
      port: 8123
      targetPort: 8123
  externalTrafficPolicy: Local    

5.Ingress

If we want to publish HA externally, we can create an Ingress as follows

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: home-assistant-ingress
  namespace: home-assistant
  annotations:
    # This example is for nginx, if you are using something else, you need to change this file
    kubernetes.io/ingress.class: nginx
spec:
  tls:
    - hosts:
        - home-assistant.mydomain.com
      secretName: my-certificate
  rules:
    # Edit this to a domain you control
    - host: home-assistant.mydomain.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: home-assistant
                port:
                  number: 8123   

Voila🥳!!

Everything should be deployed and working. If we have metalLB we can access the IP you have given us through the port (ip-address:8123).

👉 Next Part: Bastion SSH

This post is licensed under CC BY 4.0 by the author.