Du hast ein brand neues Kubernetes Cluster und willst jetzt loslegen? Aber egal, ob bei Dir ein lokales minikube läuft oder ob Du ein Managed Kubernetes mit allen Schikanen hast, die ersten Kubernetes-Objekte im super einfachem YAML-Format lassen fast jeden erstmal die Stirn runzeln. Was sind eigentlich deployments, services und Co? Und wozu die ganzen Labels? Versuchen wir Licht ins Dunkle zu bekommen.
Die wichtigsten Kubernetes-Objekte
Zum Verwalten und Steuern eins Kubernetes Clusters verwendet man Kubernetes-API-Objekte, in welchen man den gewünschten Zustand des Clusters beschreibt. Diese werden im einfachen YAML-Format mit Hilfe von kubectl an das Cluster gesendet. Neben einer API-Version, Metadaten und der Objektart gibt es meistens noch den Abschnitt spec. In diesem beschreibt man den gewünschten Zustand seiner Anwendung. spec kann für jedes Objekt unterschiedlich definiert sein und ist in vielen Fällen verschachtelt. Zum Beispiel enthält ein Objekt deployment Attribute für ein Objekt replicaSet, welches wiederum im eigenen spec Abschnitt Attribute für ein pod Objekt hat. Aber bevor es zu kompliziert wird, erstmal eine kurze Erklärung dieser drei wichtigen Objekte:
deployment
Ein deployment beschreibt einen gewünschten Zustand einer Anwendung und versucht, beständig diesen herzustellen. Mit deployments lassen sich Anwendungen starten, skalieren, aktualisieren, zurückrollen und löschen. In der Regel verwendet man deployment Objekte, um Anwendungen zu verwalten.
replicaSet
Ein replicaSet gewährleistet die Verfügbarkeit einer definierten Anzahl identischer Pods. Gegebenenfalls werden neue Pods gestartet und auch gestoppt. replicaSet verwendet man im Normalfall nur indirekt durch ein deployment.
pod
Ein pod definiert eine Gruppe von Containern (oftmals nur einer), die sich einen gemeinsamen Namespace auf einen Host teilen. Durch die gemeinsamen Namespaces (z.B. gemeinsames Dateisystem oder Netzwerk) ist eine einfache Kommunikation der Container erleichtert. Ein Pod ist immer durch eine eindeutige IP im Cluster erreichbar. Im Normalfall verwendet man Pods nur indirekt durch ein deployment.
Mit diesen drei Objekten können wir unser erstes MariaDB Deployment starten und eine erste Verbindung damit herstellen.
Das erste K8s-Deployment
Als erste einfache Anwendung starten wir eine nicht replizierte MariaDB als deployment. Bevor wir aber einen genauen Blick auf die Definition werfen, sende doch das Objekt mit kubectl apply an Dein Cluster:
Speichere einfach die mariadb.yaml auf Deinem Rechner und sende diese mit apply an Dein Cluster:
kubectl apply -f mariadb.yaml deployment.apps/mariadb-deploy created
apiVersion: apps/v1 kind: Deployment metadata: name: mariadb-deploy labels: app: mariadb spec: replicas: 1 selector: matchLabels: app: mariadb template: metadata: labels: app: mariadb spec: containers: - name: mariadb image: mariadb ports: - containerPort: 3306 name: db-port env: - name: MYSQL_ROOT_PASSWORD value: "123456"
Besserer Überblick mit describe und get
Mit describe und get kannst Du Dir einen schnellen Überblick verschaffen und alle nötigen Details Deiner Anwendungen bekommen. Ein einfaches kubectl describe deployment/mariadb-deploy liefert alle Details zum MariaDB Deployment aus dem Beispiel. get all hingegen listet alle Objekte auf, aber die Ausgabe kann auch schon mit wenigen Anwendungen im Cluster schnell unübersichtlich werden. Deshalb gibt es verschiedene Möglichkeiten zum Filtern der Ausgabe, z.B. anhand des Labels app. Mit folgenden Beispielen hast Du die Ausgabe aber schnell im Griff.
Beispiel für get mit verschiedenen Filtern
kubectl get pods kubectl get deployment kubectl get replicaset -l app=mariadb -o json kubectl get po –field-selector=status.phase=Running
Die Komponenten Deiner MariaDB kannst Du am schnellsten mit dem Label Filter anzeigen:
kubectl get all -l app=mariadb
NAME READY STATUS RESTARTS AGE pod/mariadb-deploy-64bfc599f7-j9twt 1/1 Running 0 64s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/mariadb-deploy 1/1 1 1 64s NAME DESIRED CURRENT READY AGE replicaset.apps/mariadb-deploy-64bfc599f7 1 1 1 64s
Nachdem Du jetzt weißt, wie Du den aktuellen und gewünschten Zustand Deiner Anwendung überprüfst, werfen wir nun einen genaueren Blick auf Pods und Container.
Mit Pods interagieren
Ohne weitere Konfiguration sind Anwendungen nur innerhalb des Kubernetes-Clusters erreichbar. Zudem will man selten eine Datenbank über eine öffentliche IP erreichbar machen. kubectl bietet deswegen mit proxy und port-forward zwei Möglichkeiten, um Zugriffe auf interne Pods und Services zu gewährleisten. Für MariaDB benutzen wir port-forward und senden sämtlichen Traffic der lokal auf Port 3306 ankommt durch kubectl an unseren MariaDB Pod. Du kannst übrigens direkt den Namen des deployments verwenden. Die Namen von pod und replicaSet führen aber zum selben Ergebnis. Mit telnet oder einem MySQL Client prüfst Du am schnellsten, ob die Verbindung funktioniert:
kubectl port-forward deployment.apps/mariadb-deploy 3306:3306 mysql -h 127.0.0.1 -P 3306 -u root -p123456 telnet 127.0.0.1 3306
Weitere Möglichkeiten, um mit seinem Container zu interagieren, bietet kubectl mit log und exec. Ersteres zeigt Dir natürlich stdout Deines Pods. exec hingegen wird wohl meistens zum Starten einer interaktiven Shell genutzt. Ähnlich wie bei docker benötigt man die Parameter interactive und tty (-ti), um eine funktionsfähige Bash zu erhalten:
kubectl exec -it mariadb-deploy-64bfc599f7-j9twt — /bin/bash
Mit diesen wenigen Befehlen kannst Du Deine im K8s-Cluster abgeschirmten Pods erreichen und debuggen. Anwendungen, die nur innerhalb des Clusters erreichbar sind, machen natürlich nicht immer Sinn. Damit auch andere darauf zugreifen können, benötigst du einen Kubernetes service mit öffentlicher IP. Hinter einem service steckt aber noch viel mehr.
Verbinde deine Pods mit einem service
Ein service bindet eine feste interne IP-Adresse (ClusterIP) an eine Menge von Pods, welche durch Labels identifiziert werden. Im Vergleich zu einem service sind pods sehr kurzlebig. Sobald wir im Beispiel ein Upgrade der MariaDB anstoßen, verwirft unser deployment den vorhanden Pod und startet einen neuen. Da jeder Pod seine eigenen IP-Adresse hat, ändert sich auch die IP-Adresse, unter welcher deine MariaDB erreichbar ist. Dank der Labels findet der service den neuen Pod und der Traffic wird richtig weitergeleitet. Ein service gewährleistet somit durch die ClusterIP die interne Erreichbarkeit deiner deployments. Zusätzlich kann ein service auch den Typ Loadbalancer haben. Dadurch wird eine öffentliche IP gebunden und sämtlicher Traffic an die ClusterIP weitergegeben. Im folgenden Beispiel siehst siehst Du einen service für deine MariaDB.
apiVersion: v1 kind: Service metadata: name: mariadb-service spec: ports: - port: 3306 targetPort: 3306 protocol: TCP name: mariadb selector: app: mariadb type: LoadBalancer
Was kommt als nächstes?
Mit den hier gezeigten Beispielen kann man seine ersten Anwendungen ausrollen und debuggen. Aber Du ahnst bereits, dass wir nur etwas am Lack von Kubernetes gekratzt haben und es stellen sich natürlich noch viele Fragen! Was passiert mit meinen Daten in MariaDB und wie kann ich die kurzlebigen Pods mit einem persistentem Volume verbinden? Brauche ich für jede Anwendung eine eigene öffentliche IP? Wie komme ich an Metriken und Logs meines Clusters und meiner Anwendungen? Diese und weitere Fragen werden wir natürlich in den folgenden Blogposts beantworten. Also dann, bis nächste Woche!