Einführung in Docker und Kubernetes

Große verteilte Systeme, die aus mehreren zusammenarbeitenden Diensten bestehen, werden immer wichtiger. Diese Systeme laufen auf Clustern von Hunderten, Tausenden oder mehr Servern. Diese Systeme effizient und wirtschaftlich zu entwickeln, zu implementieren und zu warten, ist eine große Aufgabe.

Virtualisierung und neuere Containerisierung ermöglichen die flexible Freigabe und Verwaltung von Ressourcen. Docker machte die Containerisierung populär. In diesem Artikel von Envato Tuts + finden Sie eine großartige Einführung: Der Tramper-Leitfaden für Docker und Modulus.

Google betreibt seit Jahren seine immense Software und Rechenzentren im Bereich Containerisierung und sammelte ein Menge Erfahrung und Knowhow. Kubernetes ist ein Open-Source-Projekt von Google, das all dieses Wissen den Massen zugänglich macht.

In diesem Artikel werde ich Docker kurz erkunden und dann tief in Kubernetes eintauchen. Als laufendes Beispiel verwende ich einen REST-API-Dienst von Python 3. Lass uns rein springen.

Der Angebotsservice

Der Angebotsservice ist eine REST-API, mit der Sie Angebote hinzufügen und eine Liste aller Angebote erhalten können. Es wird als Python 3-Webdienst unter Verwendung der exzellenten hug-Bibliothek implementiert. Es macht einen einzelnen Endpunkt verfügbar, der / Anführungszeichen genannt wird. Sie können alle Angebote einholen oder ein neues Angebot erstellen. Fügen wir ein paar Zitate hinzu:

curl http: // localhost: 8000 / quotes -d "quote = TV kaut Kaugummi für die Augen. ~ Frank Lloyd Wright" curl http: // localhost: 8000 / quotes -d "quote = Es ist besser, auf Ihrem zu sterben Füße als auf den Knien leben. ~ Emiliano Zapata "curl http: // localhost: 8000 / quotes -d" quote = Wir müssen sehr vorsichtig sein, wenn wir jüngeren Leuten Rat geben: Manchmal folgen sie ihr! ~ Edsger W. Dijkstra "

Wenn Sie zu http: // localhost: 8000 / Anführungszeichen Du wirst kriegen: ["Der Fernseher kaut Kaugummi für die Augen. ~ Frank Lloyd Wright", "Es ist besser, an den Füßen zu sterben, als auf den Knien zu leben. ~ Emiliano Zapata", "Wir müssen sehr vorsichtig sein, wenn wir jüngeren Leuten Rat geben manchmal folgen sie dem! ~ Edsger W. Dijkstra "] Wenn Sie nur die automatisch generierte Dokumentation von HUG anzeigen möchten, navigieren Sie zu: http: // localhost: 8000

"404": "Der API-Aufruf, den Sie ausführen wollten, wurde nicht definiert. Hier ist eine Definition der API, die Ihnen beim Einstieg helfen soll :)", "Dokumentation": "/ quotes": "GET": "Beispiele ": [" http: // localhost: 8000 / quotes "]," output ": " content_type ":" application / json "," format ":" JSON (Javascript Serialized Object Notation) "," POST " : "ausgaben": "content_type": "application / json", "format": "JSON (Javascript Serialized Object Notation)", "input": "quote": "type": "Basic text / Zeichenfolgewert "

Docker-Grundlagen

Ich werde nicht zu viel über Docker erklären und es nur auf den Angebotsservice anwenden.

Eine Python-App verderben

Zuerst brauchen wir eine Dockerfile. Es führt die folgenden Schritte aus:

  1. Basierend auf dem neuesten Ubuntu-Image
  2. Installiert Python 3 und einige andere Abhängigkeiten
  3. Kopieren Sie das Zitatdienstverzeichnis
  4. Installiert die Zitat-Dienst-Abhängigkeiten aus der Datei request.txt
  5. Macht den 8000-Port frei
  6. Starten Sie den Zitat-Service per Umarmung

FROM ubuntu: neueste MAINTAINER Gigi Sayfan "[email protected]" RUN apt-get Update -y RUN apt-get installieren -y python3 python3-pip python3-dev build-essential COPY. / quote-service WORKDIR / quote-service RUN pip3 install -r Anforderungen.txt EXPOSE 8000 ENTRYPOINT hug -f app.py

Bild erstellen

Im nächsten Schritt erstellen Sie ein Docker-Image. Das ist so einfach wie:

Docker bauen .

Ich mag es auch Bilder zu markieren:

Docker-Tag 715624b7e22a g1g1 / quote-service

g1g1 ist mein Benutzername bei Docker Hub.

Um zu überprüfen, ob das Image erfolgreich erstellt wurde, geben Sie Folgendes ein:

docker ps --all 

Sie sollten das neue Bild sehen:

CONTAINER ID BILDBEFEHL ERSTELLTE STATUSPORTE NAMEN 715624b7e22a g1g1 / quote-service "/ bin / sh -c 'hug -f a" 4 Stunden vor 35 Minuten 0.0.0.0:8000->8000/tcp agitated_northcutt

Ein Bild an den Docker Hub senden

Wenn Sie ein Image erstellen, können Sie es auch auf Docker Hub verschieben, sodass es von anderen Personen (oder von Ihnen selbst auf einem anderen Computer) verwendet werden kann..

Docker-Push g1g1 / quote-service

Beachten Sie, dass Sie ein Konto in Docker Hub erstellen und sich lokal mit folgendem anmelden müssen:

Docker-Login

Ausführen einer Dockerized App

OK. Lassen Sie uns das Angebotsservice-Image ausführen und den Port 8000 für den Host verfügbar machen.

Docker-Run -i -t -p 8000 g1g1 / quote-service

Das solltest du sehen: / ############################################### #################### \ '.---- "… -------…" .----. : / ::::: -: ---------: - ::::: //… + :::: ---- ## / - / oo +: - ## - --- :::: // '// :: ------- / oosoo ------- ::: //. ## ## ## ## ##### .-: ------./++ o / o -.------ :: - ' ## ## ## ## ## ----.-./ + o +:… ----. .: ///. ######## ## ## ## '----.- :::::: ------' .- :::: //. ## ## ## ## ## ####: // ::--. -:… -----… ": - :::::: -. ' ## ## ## ## ## ##: / ::::::::: -:- ". :::::-. ## ## #### ###### .--::::::::… :::."… ::… :: DIE APIs DER ZUKUNFT UMFASSEN :: -.: - - :: :: - VERSION 1.9.6 :: - - :: -::- -:: - ############################################# ######################## Copyright (C) 2015 Timothy Edmund Crosley Unter der MIT-Lizenz

Auf Port 8000 servieren ... "Das ist ziemlich cool. Bevor Sie versuchen, über Port 8000 auf Ihren hervorragenden Angebotsservice zuzugreifen, müssen Sie abhängig von Ihrer Umgebung möglicherweise zusätzliche Arbeit verrichten.

Wenn Sie Mac OS X mit VirtualBox und Docker-Computer ausführen, müssen Sie möglicherweise Port 8000 auf VirtualBox veröffentlichen, um ihn auf dem Host verfügbar zu machen.

Angenommen, Sie haben versucht, zu browsen http: // localhost: 8000 / Anführungszeichen. Ach nein. Interner Serverfehler! Was ist passiert?

Schauen wir uns den Code an:

redis_host = os.environ.get ('QUOTE_STORE_SERVICE_HOST', 'localhost') redis_server = redis.StrictRedis (host = redis_host, Port = 6379, db = 0)

Der Angebotsservice versucht, eine Verbindung zu einem Redis-Server herzustellen. Die Hostadresse kann als Umgebungsvariable konfiguriert werden. Wenn sie nicht festgelegt ist, wird standardmäßig localhost verwendet. Leider ist Redis nicht standardmäßig installiert und läuft nicht im Container. Beheben wir es vorübergehend. Geben Sie den folgenden Befehl ein, um den Shell-Zugriff auf den Container zu erhalten:

docker exec -it 715624b7e22a / bin / bash

Dann erhalten Sie Shell-Zugriff auf den Container und Sie können redis installieren:

root @ 715624b7e22a: / quote-service # apt-get install Redis-Server

Zum Schluss nochmal redis: root @ 715624b7e22a: / quote-service # redis-server [25] 29 Nov 00: 14: 24.546 # Warnung: Es wurde keine Konfigurationsdatei angegeben, die die Standardkonfiguration verwendet. Um eine Konfigurationsdatei anzugeben, verwenden Sie redis-server /path/to/redis.conf _._ _.- "__" -._ _.- ". '_." -._ Redis 2.8.4 (00000000 / 0) 64 Bit -.-."\ / .,"-._ (' , .- | , ) Im Stand-Alone-Modus ausführen-._-… - __… -.-._ | ' .-'| Port: 6379 | -._ . / .-'| PID: 25 -._ -. -./ _.- '_.-' |-.-._ -..-'_.-'_.-' | | -._-._ _.-'_.- '| http://redis.io -._ -._-.__.-'_.- '_.-' |-._-._ -..-'_.-'.-'| | -._-._ .-'.-'| -._ -.-.__.-'_.- '_.-' -. -.__.- '_.-' -._ _.- "-.__.- '

[25] 29 Nov 00: 14: 24.547 # Server gestartet, Redis-Version 2.8.4 [25] 29 Nov 00: 14: 24.547 # WARNUNG overcommit_memory ist auf 0 gesetzt! Hintergrundspeicherung kann bei Speicherplatzmangel fehlschlagen. Um dieses Problem zu beheben, fügen Sie "vm.overcommit_memory = 1" zu /etc/sysctl.conf hinzu und starten Sie den Befehl "sysctl vm.overcommit_memory = 1" neu, oder starten Sie ihn, damit dies wirksam wird. [25] 29 Nov 00: 14: 24.547 * DB von der Festplatte geladen: 0,000 Sekunden [25] 29 Nov 00: 14: 24.547 * Der Server ist jetzt bereit, Verbindungen an Port 6379 anzunehmen. "Jetzt können Sie Anführungszeichen hinzufügen und erhalten Zitate durch das http: // localhost: 8000 / Anführungszeichen Endpunkt.

Das Platzieren der Anwendung (Angebotsservice) und der Datenbank (Redis) funktioniert für einen Server. Aber das skaliert offensichtlich nicht. Betritt Kubernetes.

Kubernetes-Grundlagen

Kubernetes a.k.a. k8s, ist ein Opinionated Framework zum Verwalten und Orchestrieren mehrerer Container. Es hat seine eigene Art, Dinge zu tun, was normalerweise sehr gut ist. Es ist noch in der Entwicklung, daher gibt es hier und da noch ein paar Ecken und Kanten. Kubernetes hat viele Konzepte und ist sehr flexibel. Ich erkläre und demonstriere die Konzepte, indem ich sie auf den Angebotsservice anwende.

Cluster einrichten

Es gibt viele Möglichkeiten, einen Kubernetes-Cluster einzurichten. Kubernetes können auf Bare Metal, auf der Google Container Engine, auf AWS, auf Bare Metal (unter Linux) und lokal auf einem beliebigen Betriebssystem mit virtuellen Maschinen ausgeführt werden. In diesem Artikel habe ich einen Cluster aus einem Master und zwei Schergen erstellt, der den CoreOS OSX GUI k8s Cluster verwendet. Unter Mac OS X gibt es ein kleines Menü, in dem Sie auf viele Cluster-Management-Tools zugreifen können.

Befolgen Sie die Anweisungen, und Sie werden in kürzester Zeit gut sein.

Wenn Sie kein Mac OSX verwenden oder nur wenig auf die grafische Benutzeroberfläche achten, können Sie mit diesem Projekt einen Testcluster in einer Vagrant-VM einrichten.

Ich werde von jetzt an die Befehlszeile verwenden.

Das kubectl-Befehlszeilenprogramm

kubectl ist das Schweizer Taschenmesser von Kubernetes. Sie können Ihren Cluster vollständig von der Konsole aus steuern und verwalten, indem Sie nur kubectl verwenden.

Hier ist die Liste der Befehle: Holen Sie sich eine oder mehrere Ressourcen anzeigen. Zeigen Sie Details zu einer bestimmten Ressource an. create Erstellen Sie eine Ressource nach Dateiname oder stdin-Update. Aktualisieren Sie eine Ressource nach Dateiname oder stdin. Löschen Löscht eine Ressource nach Dateiname, Standard, Ressource und ID oder nach Auswahl von Ressourcen und Etiketten. Namespace SUPERCEDED: Festlegen und Anzeigen des aktuellen Kubernetes-Namespaceprotokolls Drucken Sie die Protokolle für einen Container in einem Pod. Rollup-Update Führen Sie ein Rollup-Update des angegebenen ReplicationControllers durch. Größe ändern Legen Sie eine neue Größe für einen Replikationscontroller fest. exec Führt einen Befehl in einem Container aus. portweiterleitung Leiten Sie einen oder mehrere lokale Ports an einen Pod weiter. Proxy Einen Proxy für den Laufcontainer des Kubernetes-API-Servers ausführen Ein bestimmtes Image im Cluster ausführen. stop Beenden Sie eine Ressource nach ID oder Dateiname. expose Nehmen Sie eine replizierte Anwendung und machen Sie sie als Kubernetes Service-Label verfügbar. Aktualisieren Sie die Labels einer Ressource. config config ändert kubeconfig-Dateien cluster-info Cluster-Info anzeigen API-Versionen Verfügbare API-Versionen drucken. version Drucken Sie die Client- und Server-Versionsinformationen. help Hilfe zu jedem Befehl

Sie können den Hilfebefehl oder die Dokumentation verwenden, um herauszufinden, was jeder tut. Viele von ihnen werden für die Durchführung von manuellen Vorgängen verwendet, die besser mit Konfigurationsdateien in einem großen, skalierbaren, verteilten System ausgeführt werden können. Sie sind jedoch für die schnelle Erkundung und Fehlerbehebung unerlässlich. Die gebräuchlichsten Befehle, die ich häufig verwenden werde, sind: Holen, Erstellen, Löschen und Starten.

Schoten

Ein Pod ist die Basiseinheit für die Bereitstellung und Verwaltung in Kubernetes. Ein Pod ist eine Gruppe von einem oder mehreren Behältern. Sie können einen Pod mithilfe einer dedizierten YAML-Datei oder als Teil eines Kubernetes-Dienstes angeben (siehe unten). Ein Pod wird immer auf einem einzelnen Host bereitgestellt, und alle Container in einem Pod können über localhost auf einander zugreifen. Alle Container der Pod werden immer zusammen gestartet, gestoppt und skaliert.

Um alle Pods im Cluster auszuchecken, geben Sie Folgendes ein:

kubectl bekommt Hülsen

Das Ergebnis wird ungefähr so ​​aussehen: NAME READY STATUS RESTARTS AGE quote-frontend-4kyns 1/1 Laufen 0 1h quote-frontend-v4xk1 1/1 Laufen 0 1h quote-store-controller-y4ya1 1/1 Laufen 0 23h Volumen

Container sollen keinen permanenten Zustand aufrechterhalten. Wenn ein Container abstürzt oder neu startet, wird sein lokales Dateisystem gelöscht. Wenn Sie den permanenten Status beibehalten möchten, sollten Sie permanente Volumes verwenden. Da alles in Kubernetes auf Pods basiert, müssen Sie auch Volumes in einem Pod definieren. Hier ist eine Pod-Definitionsdatei mit einem persistenten Volume: apiVersion: v1 Art: Pod-Metadaten: Name: Zitatspeicher Beschriftungen: App: Zitat-API-Rolle: persistente Speicherspezifikation: Container: - Name: Redis Bild: Redis VolumeMounts: - Name: Zitatspeicher-Volume mountPath: / data / redis volume: - name: quote-store-volume emptyDir: Beachten Sie, dass permanente Volumes auf den Knoten beschränkt sind und Containerabstürze und Neustarts überleben, jedoch nicht Knoten / Host-Fehler. Sie müssen immer noch das Replizieren und Sichern wichtiger Daten durchführen.

Replikationscontroller

Eine der wichtigsten Funktionen von Kubernetes ist die Fähigkeit, die Anzahl der Pods zu verwalten und einfach zu skalieren. In der Regel haben Sie verschiedene Arten von Pods in Ihrem System, und Sie sollten angeben können, wie viele Pods jedes Typs betriebsbereit sein sollen.

Begrüßen Sie die Replikationscontroller. Ein Replikationscontroller verfügt über eine Pod-Vorlage, die eine Gruppe von Containern, einen Satz von Bezeichnungen zur Identifizierung dieser Pods sowie die Anzahl der gewünschten Pods definiert. Der Replikationscontroller stellt sicher, dass die Anzahl der durch seine Beschriftungen gekennzeichneten laufenden Pods immer der gewünschten Anzahl entspricht. Wenn ein Pod beendet wird, erstellt der Replikationscontroller sofort einen neuen.

Es gibt mehrere interessante Anwendungsfälle, die von Replikationscontrollern unterstützt werden, wie z. B. Hochverfügbarkeit, elastische Skalierung und fortlaufende Updates. Sie können beispielsweise Pods zur Domäne eines Replikationscontrollers hinzufügen und daraus entfernen, indem Sie deren Bezeichnung ändern.

Replikationscontroller werden natürlich in einer YAML-Datei angegeben. Hier ein Beispiel: "apiVersion: v1 kind: ReplicationController

Metadaten: name: quote-frontend spec: replikate: 2 # -selektor gibt die Menge der Pods an, die dieser # Replikationscontroller für die Verwaltung des Selektors verantwortlich ist: app: quote-api-Rolle: frontend # podTemplate definiert den zum Erstellen von # verwendeten Cookie-Cutter. Neue Pods bei Bedarf Vorlage: Metadaten: Labels: # Wichtig: Diese Labels müssen mit der Auswahl oben übereinstimmen. # Der API-Server erzwingt diese Einschränkung. app: quote-api rolle: frontend-spezifikation: container: - name: quote-service image: g1g1 / quote-service env: - name: GET_HOSTS_FROM # value: dns value: env ports: - containerPort: 8000 "Die Spezifikation der Vorlage für die Quote-Service-Container verwendet das g1g1 / quote-service-Image, das ich zuvor an Docker Hub übertragen habe env Abschnitt, in dem die gemeinsame Nutzung von Informationen über Pods entweder über DNS oder über Umgebungsvariablen erfolgen kann.

Geben Sie Folgendes ein, um einen Replikationscontroller zu erstellen:

kubectl create -f

Geben Sie Folgendes ein, um die aktuellen Replikationscontroller im Cluster anzuzeigen:

kubectl erhalten rc

Sie sollten etwas sehen wie: CONTROLLER CONTAINER (s) IMAGE (S) SELECTOR REPLICAS AGE Zitat-Frontend Zitat-Service g1g1 / Zitat-Dienst app = Zitat-API, Rolle = Frontend 2 1h Zitat-Speicher-Controller-Master Redis App = Zitat-API, Rolle = persistent -speicher 1 1d ### Dienstleistungen

Ein Service macht seinen Pod für den Rest des Clusters verfügbar und möglicherweise extern über Umgebungsvariablen oder DNS. Der Angebotsservice besteht beispielsweise aus zwei Arten von Pods: einem Redis-Store-Pod und einem Front-End-Pod. Der Front-End-Container sollte den Speichercontainer finden können, und Clients sollten in der Lage sein, einen einzelnen öffentlichen Endpunkt zu erreichen, um auf den Dienst zuzugreifen.

Der Kubernetes-Dienst ist in einer weiteren YAML-Datei implementiert. Jede Komponente Ihres Systems, auf die andere Komponenten zugreifen müssen, sollte über eine eigene Servicedatei verfügen. Hier sind die zwei Servicedateien für die Angebotsservicekomponenten:

srv-quote-frontend.yaml

apiVersion: v1 Art: Service-Metadaten: Name: Zitat-Frontend-Spezifikation: Typ: NodePort-Ports: - Port: 8000 # Der Port, an dem dieser Service dienen soll, # der Container auf jedem Pod, zu dem eine Verbindung hergestellt werden kann, kann # sein (z 'www') oder eine Zahl (z. B. 80) targetPort: 80 protocol: TCP # Genau wie der Selektor im Replikationscontroller. # Diesmal wird jedoch die Menge der Pods angegeben, in die der Datenverkehr verteilt werden soll. Selektor: App: Zitat-API-Rolle: Frontend #### srv-quote-store.yaml apiVersion: v1 Art: Service-Metadaten: Name: Quote-Store-Spezifikation: Ports: - Port: 6379 # Der Port, den dieser Service auf TargetPort bereitstellen soll: 6379 #, genau wie der Selektor im Replikationscontroller Satz von Pods, auf die der Verkehr in # geladen werden soll. Selektor: App: Zitat-API-Rolle: Permanenter Speicher Der Host und der Port jedes Dienstes werden jedem Container im Cluster zur Verfügung gestellt. Wenn Sie beispielsweise eine interaktive Shell in einem der Frontend-Container ausführen:

kubectl quote-frontend-4kyns exec -i -t bash

Anschließend können Sie überprüfen, ob die Umgebung die erforderlichen Host- und Port-Informationen enthält, um eine Verbindung zum Angebotsspeicher herzustellen. root @ quote-frontend-4kyns: / quote-service # env | grep STORE QUOTE_STORE_PORT_6379_TCP_ADDR = 10.100.234.192 QUOTE_STORE_PORT_6379_TCP_PROTO = tcp QUOTE_STORE_SERVICE_PORT = 6379 QUOTE_STORE_PORT_6379_TCP_PORT = 6379 QUOTE_STORE_PORT = tcp: //10.100.234.192: 6379 QUOTE_STORE_PORT_6379_TCP = tcp: //10.100.234.192: 6379 QUOTE_STORE_SERVICE_HOST = 10.100.234.192 Um Ihr Gedächtnis aufzufrischen, tut das Frontend genau das: redis_host = os.environ.get ('QUOTE_STORE_SERVICE_HOST', 'localhost') redis_server = redis.StrictRedis (host = redis_host, Port = 6379, db = 0) ## Fazit

Docker und Kubernetes sind aufregende Technologien. Dieser Artikel hat die Oberfläche des Möglichen kaum zerkratzt. Die Vorteile sind enorm, aber die Infrastruktur, die Werkzeuge und Best Practices entwickeln sich immer noch. Wenn Sie sogar aus der Ferne mit großen verteilten Systemen verbunden sind, empfiehlt es sich, diese Technologien zumindest im Auge zu behalten und Ihre Zehen idealerweise einzutauchen und sie tatsächlich zu verwenden. Es gibt viele Möglichkeiten, ohne umfassende Migration Ihrer gesamten Produktionsinfrastruktur zu experimentieren und zu lernen.

In Bezug auf Kubernetes gibt es einige andere Alternativen für das Multi-Container-Management und die Orchestrierung, wie z. B. das etablierte Mesos und das eigene Composer von Docker. Ich glaube, Kubernetes ist architektonisch solider, hat viel Schwung und ist besser als die Alternativen.