Neuigkeiten von trion.
Immer gut informiert.

Docker-Registry in Kubernetes Raspberry PI

Wie ein Docker-Image für die Docker-Registry für ARM 64, z.B. für Raspberry PI oder ODROID C2, erzeugt wird, wurde im letzten Artikel beschrieben: Cross-Build von Docker Image Registry für ARM 64. Nun geht es darum, mit diesem Image in Kubernetes eine Docker-Registry aufzubauen, um damit Container-Images im Cluster zur Verfügung zu stellen.

Für die TLS-Absicherung sorgt traefik, der in Kubernetes als Ingress fungiert und von Let’s Encrypt SSL-Zertifikate ausstellen läßt. (Die Einrichtung von traefik als Kubernetes-Ingress kann hier nachgelesen werden: Traefik als Kubernetes Ingress. )

Die Docker-Registry benötigt für die Container-Images viel Speicherplatz. Da die verwendeten ODROID-C2-Einplatinencomputer wenig eigenen Speicher besitzen, wird auf Cluster-Speicher zurückgegriffen. Hier kommt das in NFS Volume in Kubernetes für Raspberry PI beschriebene NFS Storage Setup zum Einsatz.

Zunächst wird aus Gründen der Übersichtlichkeit ein Namespace angelegt, in dem alle zur Docker-Registry gehörenden Resourcen in Kubernetes organisiert werden.

Namespace für die Docker-Registry
---
kind: Namespace
apiVersion: v1
metadata:
  name: docker-registry
  labels:
    name: docker-registry

Nun kann ein PersistentVolume angelegt werden, das später durch den Registry-Container als PersistentVolumeClaim eingebunden werden kann.

NFS Speicher als PersistentVolume
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: registry-volume
spec:
  capacity:
    storage: 20Gi
  storageClassName: standard
  accessModes:
  - ReadWriteMany
  nfs:
    server: 10.23.15.1
    path: "/volume2/rpi-k8s-nfs"
  persistentVolumeReclaimPolicy: Retain

Während das PersistentVolume noch eine Cluster-Resource ist, wird der PersistentVolumeClaim im Namespace der anderen zur Docker-Image-Registry gehörenden Resourcen angelegt.

Reservieren von Speicher durch PersistentVolumeClaim
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: registry-pvc
  namespace: docker-registry
spec:
  accessModes:
  - ReadWriteMany
  storageClassName: standard
  resources:
    requests:
      storage: 20Gi

Im nun folgenden Deployment wird das erzeugte PersistentVolumeClaim verwendet, um als Speicher für die Container-Images nach /var/lib/registry im Registry-Container gemounted zu werden.
Damit die Registry nur auf Master-Nodes läuft, wurde ein entsprechender Node-Selector konfiguriert. Zudem wurde eine Toleration eingefügt, die die Ausführung des Pods auch auf Master-Nodes, die normalerweise nicht als Ziel für normale Pods fungieren, erlaubt.

Als Image wird registry:2 verwendet - unter dem Namen ist das ARM Image auf der Master-Node bereits zur Verfügung gestellt worden. Bei x86 Architekturen ist unter dem Namen auch regulär das Docker-Registry-Image zu beziehen.

Deployment der Docker-Registry in Kubernetes
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: registry
  namespace: docker-registry
spec:
  replicas: 1
  selector:
    matchLabels:
      app: registry
  template:
    metadata:
      labels:
        app: registry
        name: registry
    spec:
      nodeSelector:
        node-role.kubernetes.io/master: ""
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: registry
        image: registry:2
        ports:
        - containerPort: 5000
        volumeMounts:
        - name: registry-storage
          mountPath: /var/lib/registry
          subPath: registry
      volumes:
      - name: registry-storage
        persistentVolumeClaim:
          claimName: registry-pvc

Nachdem die Docker-Registry im Cluster läuft, muss diese noch via Ingress von außen zur Verfügung gestellt werden. Dazu wird als erstes ein Service angelegt, der die Pods im Cluster unter einem symbolischen Namen verfügbar macht.

Der Service wird dann in einem Ingress als Ziel referenziert. Bei traefik werden Ingress-Rules verwendet, um zu bestimmen, welcher Service aufgerufen werden soll. Im Beispiel wird als Regel host: registry.demo verwendet, so dass bei einem HTTP Aufruf mit dem Hostnamen registry.demo auf die Registry weitergeleitet wird.

Konfiguration von Service und Ingress für Docker-Registry in Kubernetes
---
kind: Service
apiVersion: v1
metadata:
 name: registry
 namespace: docker-registry
spec:
  ports:
  - protocol: TCP
    port: 5000
    targetPort: 5000
  selector:
    app: registry
  type: ClusterIP
---
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
  name: registry-ingress
  namespace: docker-registry
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  rules:
  - host: registry.demo
    http:
      paths:
      - backend:
          serviceName: registry
          servicePort: 5000

Ab jetzt können entprechend getaggte Images in diese Registry gepusht und auch von da bezogen werden. Bei dem Beispiel-Setup findet keinerlei Authentifizierung oder Berechtigungsprüfung statt, so dass jeder den Dienst aufrufen kann. Für den produktiven Einsatz sind hier also noch weitere Maßnahmen zu treffen, im einfachsten Fall per HTTP Basic-Auth als traefik-Konfiguration.




Zu den Themen Kubernetes, Docker und Cloud Architektur bieten wir sowohl Beratung, Entwicklungsunterstützung als auch passende Schulungen an:

Auch für Ihren individuellen Bedarf können wir Workshops und Schulungen anbieten. Sprechen Sie uns gerne an.

Feedback oder Fragen zu einem Artikel - per Twitter @triondevelop oder E-Mail freuen wir uns auf eine Kontaktaufnahme!

Zur Desktop Version des Artikels