Si vous souhaitez déployer l’appli UNMS de Ubiquiti sur du Kubernetes, voilà un peu d’inspiration !

devices

Générer un certificat LetsEncrypt

Par défaut, UNMS génère un certificat LetsEncrypt avec un challenge HTTP-01. Mon service n’étant pas accessible depuis l’extérieur et le hostname envoyé n’étant pas le bon (c’est le nom du pod), je génère le certificat à la main pour le fournir directement à UNMS. Vous avez plusieurs solutions pour générer votre certificat. J’ai utilisé acme.sh et le challenge DNS-01 via les DNS d’OVH :

acme.sh --issue -d unms.mon_domaine --dns dns_ovh

Vous trouverez plus de détails sur la page du projet ou plus particulièrement ici pour la partie DNS. Beaucoup de providers sont disponibles.

Les deployments

Il faut ces pods :

$ kubectl --namespace=unms get pod
NAME                             READY     STATUS    RESTARTS   AGE
unms-3445584506-kp3cv            1/1       Running   0          11h
unms-postgres-779404299-vxv7c    1/1       Running   0          12h
unms-rabbitmq-1799011288-2cn8m   1/1       Running   0          12h
unms-redis-1722785268-0dssb      1/1       Running   0          12h

Voici les deployments associés… Pour faire simple, j’utilise un hostPath pour les volumes à persister. A adapter avec un claim si vous avez le nécessaire. Pour démarrer UNMS, faites un kubectl apply -f deployment.yaml --record des deployments suivants :

Le postgres

apiVersion: apps/v1
kind: Deployment
metadata:
  name: unms-postgres
  labels:
    app: unms
    component: unms-postgres
spec:
  selector:
    matchLabels:
      app: unms
      component: unms-postgres
  template:
    metadata:
      labels:
        app: unms
        component: unms-postgres
    spec:
      nodeSelector:
        beta.kubernetes.io/arch: amd64
      containers:
      - name: unms-postgres
        image: postgres:9.6.1-alpine
        imagePullPolicy: Always
        env:
        - name: POSTGRES_DB
          value: unms
        - name: POSTGRES_PGDATA
          value: /var/lib/postgresql/data/pgdata
        ports:
        - containerPort: 5432
          name: pg
        volumeMounts:
        - name: pgdata
          mountPath: /var/lib/postgresql
      volumes:
      - name: pgdata
        hostPath:
          path: /mnt/nas/pg/data

Le RabbitMQ

apiVersion: apps/v1
kind: Deployment
metadata:
  name: unms-rabbitmq
  labels:
    app: unms
    component: unms-rabbitmq
spec:
  selector:
    matchLabels:
      app: unms
      component: unms-rabbitmq
  template:
    metadata:
      labels:
        app: unms
        component: unms-rabbitmq
    spec:
      nodeSelector:
        beta.kubernetes.io/arch: amd64
      containers:
      - name: unms-rabbitmq
        image: rabbitmq:3
        imagePullPolicy: Always
        ports:
        - containerPort: 5672

Le Redis

apiVersion: apps/v1
kind: Deployment
metadata:
  name: unms-redis
  labels:
    app: unms
    component: unms-redis
spec:
  selector:
    matchLabels:
      app: unms
      component: unms-redis
  template:
    metadata:
      labels:
        app: unms
        component: unms-redis
    spec:
      nodeSelector:
        beta.kubernetes.io/arch: amd64
      containers:
      - name: unms-redis
        image: redis:3.2.8-alpine
        imagePullPolicy: Always
        command:
        - redis-server
        - --appendonly
        - "yes"
        - --dir
        - /data/db/
        ports:
        - containerPort: 6379
          name: redis
        volumeMounts:
        - name: data
          mountPath: /data/db
      volumes:
      - name: data
        hostPath:
          path: /mnt/nas/redis/data

UNMS

apiVersion: apps/v1
kind: Deployment
metadata:
  name: unms
  labels:
    app: unms
    component: unms
spec:
  selector:
    matchLabels:
      app: unms
      component: unms
  template:
    metadata:
      labels:
        app: unms
        component: unms
    spec:
      nodeSelector:
        kubernetes.io/hostname: hebus
      containers:
      - name: unms
        image: ubnt/unms:0.12.0
        imagePullPolicy: Always
        env:
        - name: PUBLIC_WS_PORT
          value: "443"
        - name: SSL_CERT
          value: /usr/local/sbin/acme.sh/unms.mon_domaine/unms.mon_domaine.cer
        - name: SSL_CERT_KEY
          value: /usr/local/sbin/acme.sh/unms.mon_domaine/unms.mon_domaine.key
        - name: SSL_CERT_CA
          value: /usr/local/sbin/acme.sh/unms.mon_domaine/ca.cer
        ports:
        - containerPort: 8080
          name: http
        - containerPort: 8443
          name: https
        volumeMounts:
        - name: data
          mountPath: /home/app/unms/data
        - name: ssl
          mountPath: /etc/ssl
        - name: letsencrypt
          mountPath: /home/app/unms/data/cert/usr/local/sbin/acme.sh/unms.mon_domaine
      volumes:
      - name: data
        hostPath:
          path: /mnt/nas/unms/data
      - name: ssl
        hostPath:
          path: /etc/ssl
      - name: letsencrypt
        hostPath:
          path: /usr/local/sbin/acme.sh/unms.mon_domaine

Exposer les services

La méthode dépendra un petit peu de la façon utilisée pour accéder à vos services à l’extérieur de votre cluster (nodePort, proxy, ingress, lb…). J’utilise une externalIP annoncée par BGP. Le seul service qui doit être accessible depuis l’extérieur est UNMS :

$ kubectl --namespace=unms get svc
NAME       TYPE        CLUSTER-IP       EXTERNAL-IP      PORT(S)    AGE
postgres   ClusterIP   10.106.251.46    <none>           5432/TCP   1m
rabbitmq   ClusterIP   10.108.223.52    <none>           5672/TCP   1m
redis      ClusterIP   10.100.176.222   <none>           6379/TCP   1m
unms       ClusterIP   10.97.64.38      192.168.90.120   443/TCP    4s

Pour exposer les services :

kubectl --namespace=unms expose deployment unms-postgres
kubectl --namespace=unms expose deployment unms-rabbitmq
kubectl --namespace=unms expose deployment unms-redis
kubectl --namespace=unms expose deployment unms --port=443 --target-port=8443 --external-ip=192.168.90.120

La dernière ligne est donc à adapter en fonction de votre infra. Bons tests !

Quelques captures d’écran

Les firmwares :

Liste des firmwares

Logs :

Les logs

Sites :

Sites