If you use Ubiquiti for your wireless routing hardware you will need to run the Unifi Network Application to manage your hardware. In this post I’ll show you how to run the Unifi Network Application on a local Kubernetes instance. In this case I am using MicroK8s, but the approach should work for any Kubernetes stack.
This post leverages load balancing and the endpoint is secured with TLS. Setting up load balancing is another topic entirely so I won’t cover that here, for more information see Load Balancing with MicroK8s Kubernetes
Installing the Unifi Network Application
Please create each Kubernetes component, in the order as follows (top to bottom).
Persistent-Volume.yaml
Create a persistent volume to ensure that data is maintained between recycles and container upgrades. There are several types of persistent volumes, this example leverages a local folder on the Kubernetes worker node at /data/unifi
. Create this folder on each of your worker nodes first. Alternatively, you could mount a network volume.
apiVersion: v1
kind: PersistentVolume
metadata:
name: unifi-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
local:
path: /data/unifi
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- MicroK8sWorker1.local
Persistent-Volume-Claim.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: unifi-pv-claim
labels:
app: unifi
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: "" # Empty string must be explicitly set otherwise default StorageClass will be set
volumeName: unifi-pv
Deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: unifi-deployment
labels:
app: unifi
spec:
replicas: 1
selector:
matchLabels:
app: unifi
template:
metadata:
labels:
app: unifi
spec:
containers:
- name: unifi
image: linuxserver/unifi-controller:latest
ports:
- containerPort: 3478
protocol: UDP
- containerPort: 10001
protocol: UDP
- containerPort: 8080
protocol: TCP
- containerPort: 8443
protocol: TCP
- containerPort: 1900
protocol: UDP
- containerPort: 8843
protocol: TCP
- containerPort: 8880
protocol: TCP
- containerPort: 6789
protocol: TCP
- containerPort: 5514
protocol: UDP
volumeMounts:
- name: unifi-persistent-storage
mountPath: /config
volumes:
- name: unifi-persistent-storage
persistentVolumeClaim:
claimName: unifi-pv-claim
Service.yaml
apiVersion: v1
kind: Service
metadata:
name: unifi
spec:
type: ClusterIP
selector:
app: unifi
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
- name: https
port: 443
targetPort: 8443
protocol: TCP
- name: port3478
port: 3478
targetPort: 3478
protocol: UDP
- name: unifidiscovery
port: 10001
targetPort: 10001
protocol: UDP
- name: port8080
port: 8080
targetPort: 8080
protocol: TCP
- name: port8443
port: 8443
targetPort: 8443
protocol: TCP
- name: port1900
port: 1900
targetPort: 1900
protocol: UDP
- name: port8843
port: 8843
targetPort: 8843
protocol: TCP
- name: port8880
port: 8880
targetPort: 8880
protocol: TCP
- name: port6789
port: 6789
targetPort: 6789
protocol: TCP
- name: port5514
port: 5514
targetPort: 5514
protocol: UDP
Service-Lb-Udp.yaml
The UDP and TCP services are separated due to Kubernetes requirement. Multiple protocols cannot currently be described within the same service.
apiVersion: v1
kind: Service
metadata:
name: unifi-ingress-udp
namespace: ingress
annotations:
metallb.universe.tf/allow-shared-ip: "unifi-shared-ip"
spec:
selector:
name: nginx-ingress-microk8s
type: LoadBalancer
# loadBalancerIP is optional. MetalLB will automatically allocate an IP
# from its pool if not specified. You can also specify one manually.
# loadBalancerIP: x.y.z.a
ports:
- name: udp-1900
protocol: UDP
port: 1900
targetPort: 1900
- name: udp-3478
protocol: UDP
port: 3478
targetPort: 3478
- name: udp-5514
protocol: UDP
port: 5514
targetPort: 5514
- name: udp-10001
protocol: UDP
port: 10001
targetPort: 10001
Service-Lb-Tcp.yaml
apiVersion: v1
kind: Service
metadata:
name: unifi-ingress-tcp
namespace: ingress
annotations:
metallb.universe.tf/allow-shared-ip: "unifi-shared-ip"
spec:
selector:
name: nginx-ingress-microk8s
type: LoadBalancer
# loadBalancerIP is optional. MetalLB will automatically allocate an IP
# from its pool if not specified. You can also specify one manually.
# loadBalancerIP: x.y.z.a
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
- name: https
protocol: TCP
port: 443
targetPort: 443
- name: tcp-8080
protocol: TCP
port: 8080
targetPort: 8080
- name: tcp-8443
protocol: TCP
port: 8443
targetPort: 8443
- name: tcp-6789
protocol: TCP
port: 6789
targetPort: 6789
- name: tcp-8843
protocol: TCP
port: 8843
targetPort: 8843
- name: tcp-8880
protocol: TCP
port: 8880
targetPort: 8880
Secret-Tls.yaml
This is where you will determine the host name which will be used to serve the Unifi Network Application. To create the TLS secret, you’ll need to first create or obtain a TLS key and certificate associated with your desired host name. Convert the key and cert files to base64 with:
base64 -w 0 /path/to/your/cert
Insert the base64 encoded values into the following yaml and create the secret.
apiVersion: v1
kind: Secret
metadata:
name: unifi-tls
type: kubernetes.io/tls
data:
tls.crt: (single line base64 encoded certificate goes here)
tls.key: (single line base64 encoded key goes here)
Ingress.yaml
Replace “unifi.local” with the host name that matches certificate from the above step. Ensure that this name is setup in your local DNS and can be resolved by your Ubiquiti hardware. You can find the IP for the Unifi Network Application by running microk8s.kubektl get svc -n ingress
. Look for the External-Ip under unifi-ingress-tcp.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: unifi-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
tls:
- hosts:
- unifi.local
secretName: unifi-tls
rules:
- host: unifi.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: unifi
port:
number: 443
Ingress-Udp-Config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-ingress-udp-microk8s-conf
namespace: ingress
data:
1900: "default/unifi:1900"
3478: "default/unifi:3478"
5514: "default/unifi:5514"
10001: "default/unifi:10001"
Ingress-Tcp-Config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-ingress-tcp-microk8s-conf
namespace: ingress
data:
6789: "default/unifi:6789"
8080: "default/unifi:8080"
8443: "default/unifi:8443"
8843: "default/unifi:8843"
8880: "default/unifi:8880"
You should be able to log into your Unifi Network Application at https://unifi.local or the name chosen when creating the TLS secret.
Upgrading the Unifi Network Application
Before upgrading, always take a backup and store it in a secure location. Failure to do so may lead to irretrievable loss and require access to all hardware for reset.
To upgrade the Unifi Network Application run the following, and replace ‘latest’ with the desired version:
microk8s.kubectl set image deployment unifi-deployment unifi=linuxserver/unifi-controller:latest