Docker rockt Java: Mit Kubernetes in der Entwicklung starten

Die Plattform Kubernetes bietet ein leistungsfähiges Container-Orchestration-System, das von Google und Red Hat gemeinsam entwickelt wird. Kubernetes zielt darauf ab, bessere Möglichkeiten für die Verwaltung verteilter Anwendungen in einer dynamischen Infrastruktur zu schaffen. Docker-Experte und JAX Speaker Peter Roßbach zeigt in dieser Kolumne, welche neuen Herausforderungen sich dabei stellen, die eigene Software betriebsfähig zu liefern.
Kubernetes erzeugt, skaliert und verbindet Gruppen von Containern in einem Cluster von Maschinen. Aktuell unterstützt es Docker- oder CoreOS-Rocket-Container. Eine Gruppe dieser Container nennt sich Pod. Die Container eines Pods teilen sich Konfigurationen, ein Netzwerkinterface und Volumes. Auf jeder Maschine eines Clusters können diese Pods durch einen zentralen Manager gestartet werden (Abb. 1). Außerdem lassen sich die verschiedenen Pods zu einem Service zusammenfassen. Dieser Service bekommt dabei einen eigenen Port und eine eigene IP-Adresse. Mit diesem einfachen Ansatz können andere Pods bereits auf alle Prozesse dieses Service zugreifen. Die Last wird dabei automatisch auf alle Pods eines Service verteilt. Veränderungen der Anzahl der Pods lassen sich so transparent für die Clients berücksichtigen. In der Realität klappt dies nur problemlos, wenn die neuen Pods ein kompatibles API unterstützen und die Clients entsprechende Recovery-Routinen für Netzwerkverbindungen implementiert haben. Um den Anschluss an die externe Welt mit entsprechenden Load Balancern muss man sich allerdings meist selbst kümmern.
Wer Kubernetes in OpenShift oder in der Google Cloud Engine einsetzt, bekommt schon eine leistungsfähige Load-Balancer-Integration. In Kubernetes 1.1 gibt es die Ingress-Load-Balancer-Abstraktion zusätzlich, die weitere Routing-Optionen definiert. Eine weitere wichtige Neuerung ist die Möglichkeit, Autoscaling von Pods auf der Basis des CPU-Verbrauchs zu konfigurieren. Im Detail sind die Konzepte und Lösungen komplex und bieten vielseitige Verwendungsmöglichkeiten. Der Einsatz von Kubernetes erfordert die Bereitstellung einer komplexen Systemumgebung für den Betrieb von vielen Anwendungen. Besonders gut geeignet ist Kubernetes sicherlich für die Entwicklung von Microservices.
Die Anzahl von Angeboten, die Kubernetes in der Cloud oder On Premise bereitstellen, überschlägt sich in den letzten Monaten. Beschreibungen der verschiedenen Varianten und entsprechende Beispiele zur Installation liefert das Kubernetes-Projekt. Auch vielversprechende Ansätze mit Google Cloud Engine, Azure, Vagrant, CoreOS, OpenStack, Mesos, Docker-Swarm und Docker-Compose stehen zur Verfügung. Weitere Tutorials lassen sich in diversen Blogs und konkreten Projekten auf GitHub finden [1]. Die Auswahl ist allerdings schwierig.
Für einen ersten Test und die Entwicklung reicht allerdings meist eine Installation auf nur einer Maschine. Problematisch sind die Bereitstellung eines entsprechenden Netzwerks, die Vergabe von IPs und die externe Erreichbarkeit. Bevor die Entscheidung für einen solchen Aufwand getroffen werden kann, wäre ein einfacher Test sinnvoll. Der Ansatz in diesem Artikel erzeugt eine Kubernetes-Installation auf nur einer Maschine auf der Basis einer Docker-Compose-Beschreibung und weniger Shell-Skripte [2] (Listing 1).
In wenigen Schritten Container orchestrieren
Als erster Schritt wird eine lokale Docker-Maschine erzeugt. Das Kubernetes-Projekt stellt dafür ein Docker-Image zur Installation bereit. Die einzelnen Services benötigen nur noch einen Zugriff auf ETCD als Key-Value-Datenbank. Mit dem Kommando hyperkube lassen sich die verschiedenen Services konfigurieren und starten (Listing 2). Das Kommando kubelet kann beliebige Kubernetes-Manifeste im Verzeichnis /etc/kubernetes/manifests starten. Mit diesem Trick wird die Kubernetes Control Plane aus den Services-APIs, Scheduler und Manager bereitgestellt (Abb. 2). Der API-Service ist ein CRUD-REST-Service, der seine Daten in ETCD speichert. Der Scheduler entscheidet, welche nicht zugeordneten Pods auf welchen Nodes gestartet werden. Der Manager überwacht die Strukturen und entscheidet, welche Aufgaben vorliegen. Damit alle Services auch durch einen DNS-Service erreichbar sind, wird zusätzlich noch ein SkyDNS-Service gestartet. Die entsprechenden Informationen über laufende Services besorgt der Container Kube2Sky vom Kubernetes-API-Service. Der einfache Kube-UI-Service wird als Erweiterung des API gestartet und schafft eine erste Übersicht über einen Kubernetes-Cluster (Abb. 3). Als Netzwerk dient den Pods die lokale Docker Bridge. Erste Experimente, ein Multi-Host-Netzwerk auf Basis von VXLAN und Docker-Swarm zu nutzen, sind auf der DockerCon EU 2015 schon erfolgreich gezeigt worden. Allerdings gibt es noch Probleme mit der Names-Auflösung der Kubelets.
Auf jeder Maschine existiert ein Kubelet, das für die Anbindung an den Docker Daemon sorgt und den Verbrauch der Ressourcen via cAdvisor-API auf dem Port 4194 bereitstellt. Die Bereitstellung der Services und Endpoints im Kubernetes-Cluster wird vom Kube Proxy auf Basis der Konfiguration der IP Tables umgesetzt. Mit dieser Standalone-Installation lassen sich nun alle Konzepte von Kubernetes lokal testen (Listing 3).
$ brew install \ git docker docker-compose docker-machine kubernetes-cli $ git clone https://github.com/infrabricks/kubernetes-standalone $ cd kubernetes-standalone $ docker-machine create -d virtualbox \ --virtualbox-memory "2048" \ --virtualbox-cpu-count "2" kubernetes $ eval $(docker-machine env kubernetes) $ export KUBERNETES_MASTER=http://127.0.0.1:8080 $ ./kube-up.sh $ kubectl cluster-info Kubernetes master is running at http://127.0.0.1:8080 KubeUI is running at http://127.0.0.1:8080/api/v1/proxy/namespaces/kube-system/services/kube-ui
etcd: image: gcr.io/google_containers/etcd:2.2.1 net: "host" container_name: etcd command: ['/usr/local/bin/etcd', '--addr=127.0.0.1:4001', '--bind-addr=0.0.0.0:4001', '--data-dir=/var/etcd/data'] kubelet: image: gcr.io/google_containers/hyperkube:v1.1.2 net: "host" privileged: true volumes: - /:/rootfs:ro - /sys:/sys:ro - /dev:/dev - /var/run/docker.sock:/var/run/docker.sock - /var/lib/docker/:/var/lib/docker:ro - /var/lib/kubelet/:/var/lib/kubelet:rw - /var/run:/var/run:rw - ./manifests:/etc/kubernetes/manifests command: /hyperkube kubelet --containerized --api_servers=http://127.0.0.1:8080 --v=2 --address=0.0.0.0 --enable_server --hostname_override=127.0.0.1 --config=/etc/kubernetes/manifests --cluster-dns=172.17.0.1 --cluster-domain=cluster.local proxy: image: gcr.io/google_containers/hyperkube:v1.1.2 net: "host" privileged: true command: /hyperkube proxy --master=http://127.0.0.1:8080 --v=2 kube2sky: image: gcr.io/google_containers/kube2sky:1.11 net: host command: ['--kube_master_url=http://127.0.0.1:8080', '--domain=cluster.local'] skydns: image: gcr.io/google_containers/skydns:2015-10-13-8c72f8c net: host command: ['--machines=http://localhost:4001', '--addr=0.0.0.0:53', '--domain=cluster.local', '-ns-rotate=false'] environment: - SKYDNS_NAMESERVERS="8.8.8.8:53,8.8.4.4:53"
$ kubectl run nginx --image=nginx —port=80 $ kubectl get pods NAME READY STATUS RESTARTS AGE k8s-master-127.0.0.1 3/3 Running 0 2m nginx-0ycul 1/1 Running 0 11s $ kubectl scale --replicas=2 rc/nginx $ kubectl expose rc nginx --port=80 —external-ip=$(docker-machine ip kubernetes)
Fazit
Kubernetes ist eine mächtige Technologie für die Orchestrierung von Containern. Sie vereinfacht zwar einen komplexen Betrieb von verteilten Anwendungen, aber erschwert noch die Entwicklung. Mit der gezeigten Installationsmethode können Entwickler nun auch beginnen, sich mit der Produktivumgebung vertraut zu machen. Die Voraussetzungen für den Einsatz sind allerdings vorgefertigte Docker-Images. Diese lassen sich mit entsprechenden Dockerfile-Projekten oder für Java-Entwickler mit den verfügbaren Docker-Gradle– oder Maven-Plug-ins erstellen.
Die Integration von Kubernetes in bestehende Load Balancer ist möglich. Es erfordert aber meist eigene Implementierungen. Für HAProxy und nginx gibt es verschiedene Lösungen. Das Projekt Kubernetes hat ein enormes Entwicklungstempo – alle zwei Wochen gibt es ein neues Release. Die Provisionierung von Maschinen und der Basisinfrastruktur ist nicht wirklich Bestandteil des Kubernetes-Projekts. Es gibt noch viel Spielraum für neue Ideen, Erweiterungen und Projekte.
Hinterlasse einen Kommentar