In my quest to get everything that was previously running in Docker on my Synology to (micro)K8s, I now want to run my Unifi controller on it.
Of course I need persistent storage for this, for that I will be using NFS, just like my SonarQube setup. Because the Unifi devices need a fixed IP to talk to I also will be using the MetalLB loadbalancer that comes with MicroK8s.
The image that I'm using will be the same as on my Synology: this one. So I quickly came up with a yaml that will deploy this on K8s:
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-unifi
spec:
storageClassName: "" # same storage class as pvc
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
nfs:
server: 192.168.1.2 # ip addres of nfs server
path: "/volume1/nfs/unifi" # path to directory
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-unifi
spec:
storageClassName: ""
accessModes:
- ReadWriteMany # must be the same as PersistentVolume
resources:
requests:
storage: 8Gi
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: unifi-controller
spec:
replicas: 1
selector:
matchLabels:
name: unifi-controller
template:
metadata:
name: unifi-controller
labels:
name: unifi-controller
spec:
volumes:
- name: nfs-unifi
persistentVolumeClaim:
claimName: nfs-unifi
containers:
- name: unifi-controller
image: 'jacobalberty/unifi:6.0.45'
ports:
- containerPort: 3478
protocol: UDP
- containerPort: 8080
protocol: TCP
- containerPort: 8443
protocol: TCP
- containerPort: 8843
protocol: TCP
- containerPort: 8880
protocol: TCP
- containerPort: 6789
protocol: TCP
volumeMounts:
- name: nfs-unifi
mountPath: /unifi
---
kind: Service
apiVersion: v1
metadata:
name: unifi-controller
labels:
app: unifi-controller
spec:
ports:
- name: '3478'
protocol: UDP
port: 3478
targetPort: 3478
- name: '8080'
protocol: TCP
port: 8080
targetPort: 8080
- name: '8443'
protocol: TCP
port: 8443
targetPort: 8443
- name: '8843'
protocol: TCP
port: 8843
targetPort: 8843
- name: '8880'
protocol: TCP
port: 8880
targetPort: 8880
- name: '6789'
protocol: TCP
port: 6789
targetPort: 6789
selector:
name: unifi-controller
Now the configuration of the loadbalancer took me some research, because the Unifi controller uses both UDP and TCP. And you cannot mix those in a LB configuration. The solution is to create two configs with the same IP. To allow this you need a special annotation metallb.universe.tf/allow-shared-ip: 'true'
. With this the whole LB config will become this:
kind: Service
apiVersion: v1
metadata:
name: lb-unifi
annotations:
metallb.universe.tf/allow-shared-ip: 'true'
spec:
ports:
- name: '8080'
protocol: TCP
port: 8080
targetPort: 8080
- name: '8443'
protocol: TCP
port: 8443
targetPort: 8443
- name: '8843'
protocol: TCP
port: 8843
targetPort: 8843
- name: '8880'
protocol: TCP
port: 8880
targetPort: 8880
- name: '6789'
protocol: TCP
port: 6789
targetPort: 6789
selector:
name: unifi-controller
type: LoadBalancer
loadBalancerIP: 192.168.1.21
---
kind: Service
apiVersion: v1
metadata:
name: lb-unifi-udp
annotations:
metallb.universe.tf/allow-shared-ip: 'true'
spec:
ports:
- name: '3478'
protocol: UDP
port: 3478
targetPort: 3478
selector:
name: unifi-controller
type: LoadBalancer
loadBalancerIP: 192.168.1.21
I'm already running a Ingress with wildcard certificates, so I also want to expose the Unifi dashboard through this. Easy enough with this yaml:
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: ingress-unifi
annotations:
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
spec:
rules:
- host: unifi.app.singel.home
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: unifi-controller
port:
number: 8443
This and giving it a DNS record will make it available on port 443 with my existing ingress certificate.
Now, I'm already running the Unifi controller so all my devices point to the Docker (Synology) IP. I've found numerous ways to migrate to a new Unifi controller ranging from logging in on all devices and starting all over again. The easiest one that worked for me is:
- Backup the config on the old controller
- Restore this config on the new controller
- Use the UI in the OLD controller to announce the new one
This last step is done by entering the new IP/hostname here and checking the Override inform host with controller hostname/IP
:
After a few minutes all your devices will log on to the new controller, and you are done!
The Unifi controller is running on K8s. Hope this helps.