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.
---
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.
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.
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.
---
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.
---
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.