Einführung
Kubernetes ist ein Open-Source-Container-Orchestrierungs-Tool zum Verwalten von containerisierten Anwendungen. Im vorherigen Tutorial in dieser Reihe, A Closer Look at Kubernetes, haben Sie die Bausteine von Kubernetes kennengelernt.
In diesem Lernprogramm wenden Sie die Konzepte der vorherigen Lernprogramme an, um eine End-to-End-Microservices-Anwendung in Kubernetes zu erstellen, bereitzustellen und zu verwalten. Die Beispielwebanwendung, die Sie in diesem Lernprogramm verwenden, ist eine in Node.js geschriebene Aufgabenlistenanwendung, die MongoDB als Datenbank verwendet. Dies ist dieselbe Anwendung, die wir im Tutorial Building Containerized Applications verwendet haben.
Sie erstellen ein Container-Image für diese App aus einer Docker-Datei, übertragen das Image an Docker Hub und stellen es dann in Ihrem Cluster bereit. Dann skalieren Sie die App, um die gestiegene Nachfrage zu befriedigen.
Voraussetzungen
Um dieses Tutorial abzuschließen, benötigen Sie:
-
Ein Kubernetes-Cluster, den Sie im dritten Teil dieser Lernprogrammserie konfigurieren können: Getting Started with Kubernetes.
-
Ein aktives Docker Hub Konto zum Speichern des Images.
-
Git auf Ihrem lokalen Computer installiert. Sie können dem Tutorial Contributing to Open Source: Erste Schritte mit Git folgen, um es zu installieren und einzurichten Git auf Ihrem Computer.
Schritt 1 - Erstellen Sie ein Image mit Dockerfile
Wir beginnen mit der Containerisierung der Webanwendung, indem wir sie in ein Docker-Image packen.
Wechseln Sie zunächst in Ihr Ausgangsverzeichnis und klonen Sie mit Git die Beispielwebanwendung dieses Tutorials aus dem offiziellen Repository auf GitHub.
cd ~
git clone https://github.com/janakiramm/todo-app.git
Erstellen Sie das Container-Image aus der Docker-Datei. Verwenden Sie die Option -t, um das Image mit dem Registrierungsbenutzernamen, dem Image-Namen und einem optionalen Tag zu versehen.
docker build -t sammy/todo .
Die Ausgabe bestätigt, dass das Image erfolgreich erstellt und entsprechend markiert wurde.
OutputSending build context to Docker daemon 8.238MB
Step 1/7 : FROM node:slim
---> 286b1e0e7d3f
Step 2/7 : LABEL maintainer = "[email protected]"
---> Using cache
---> ab0e049cf6f8
Step 3/7 : RUN mkdir -p /usr/src/app
---> Using cache
---> 897176832f4d
Step 4/7 : WORKDIR /usr/src/app
---> Using cache
---> 3670f0147bed
Step 5/7 : COPY ./app/ ./
---> Using cache
---> e28c7c1be1a0
Step 6/7 : RUN npm install
---> Using cache
---> 7ce5b1d0aa65
Step 7/7 : CMD node app.js
---> Using cache
---> 2cef2238de24
Successfully built 2cef2238de24
Successfully tagged sammy/todo-app:latest
Stellen Sie sicher, dass das Image erstellt wurde, indem Sie den Befehl docker images ausführen.
docker images
Sie können die Größe des Bildes zusammen mit der Zeit seit seiner Erstellung sehen.
OutputREPOSITORY TAG IMAGE ID CREATED SIZE
sammy/todo-app latest 81f5f605d1ca 9 minutes ago 236MB
Übertragen Sie das Bild anschließend in die öffentliche Registrierung von Docker Hub. Melden Sie sich dazu bei Ihrem Docker Hub-Konto an:
docker login
Wenn Sie Ihre Anmeldeinformationen eingegeben haben, kennzeichnen Sie Ihr Image mit Ihrem Docker Hub-Benutzernamen:
docker tag /todo-app
Dann senden Sie Ihr Bild an Docker Hub:
docker push
Sie können überprüfen, ob das neue Image verfügbar ist, indem Sie in Ihrem Webbrowser nach Docker Hub suchen.
Nachdem das Docker-Image in die Registrierung verschoben wurde, packen wir die Anwendung für Kubernetes.
Schritt 2 - MongoDB Pod in Kubernetes bereitstellen
Die Anwendung verwendet MongoDB zum Speichern von Aufgabenlisten, die über die Webanwendung erstellt wurden. Um MongoDB in Kubernetes auszuführen, müssen wir es als Pod verpacken. Wenn wir diesen Pod starten, wird eine einzelne Instanz von MongoDB ausgeführt.
Erstellen Sie eine neue YAML-Datei mit dem Namen db-pod.yaml:
nano db-pod.yaml
Fügen Sie den folgenden Code hinzu, der einen Pod mit einem Container basierend auf MongoDB definiert. Wir stellen den von MongoDB verwendeten Standard-Port + 27017 +
zur Verfügung. Beachten Sie, dass die Definition die Bezeichnungen "+ name" und "+ app" enthält. Wir verwenden diese Bezeichnungen, um bestimmte Pods zu identifizieren und zu konfigurieren.
db-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: db
labels:
name: mongo
app: todoapp
spec:
containers:
- image: mongo
name: mongo
ports:
- name: mongo
containerPort: 27017
volumeMounts:
- name: mongo-storage
mountPath: /data/db
volumes:
- name: mongo-storage
hostPath:
path: /data/db
Die Daten werden in dem als "+ mongo-storage " bezeichneten Volume gespeichert, das dem " / data / db +" - Speicherort des Knotens zugeordnet ist. Weitere Informationen zu Volumes finden Sie in der offiziellen Dokumentation zu Kubernetes-Volumes.
Führen Sie den folgenden Befehl aus, um einen Pod zu erstellen.
kubectl create -f db-pod.yml
Sie sehen diese Ausgabe:
Outputpod "db" created
Überprüfen Sie nun die Erstellung des Pods.
kubectl get pods
Die Ausgabe zeigt den Pod und zeigt an, dass er ausgeführt wird:
OutputNAME READY STATUS RESTARTS AGE
db 1/1 0 2m
Lassen Sie uns diesen Pod den internen Verbrauchern des Clusters zugänglich machen.
Erstellen Sie eine neue Datei mit dem Namen "+ db-service.yaml +", die diesen Code enthält, der den Service für MongoDB definiert:
db-service.yaml
apiVersion: v1
kind: Service
metadata:
name: db
labels:
name: mongo
app:
spec:
selector:
name: mongo
type: ClusterIP
ports:
- name: db
port: 27017
targetPort: 27017
Der Dienst erkennt alle Pods im selben Namespace, die mit der Bezeichnung "+ name: db " übereinstimmen. Der Abschnitt " Selector +" der YAML-Datei definiert diese Zuordnung explizit.
Wir geben an, dass der Service innerhalb des Clusters durch die Deklaration + type: ClusterIP +
sichtbar ist.
Speichern Sie die Datei und beenden Sie den Editor. Verwenden Sie dann "+ kubectl +", um es an den Cluster zu senden.
kubectl create -f db-service.yml
Diese Ausgabe zeigt an, dass der Service erfolgreich erstellt wurde:
Outputservice "db" created
Lassen Sie uns den Port ermitteln, an dem der Pod verfügbar ist.
kubectl get services
Sie sehen diese Ausgabe:
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
db ClusterIP 10.109.114.243 <none> 14s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 47m
An dieser Ausgabe können Sie erkennen, dass der Dienst an Port + 27017 +
verfügbar ist. Die Webanwendung kann über diesen Dienst auf MongoDB zugreifen. Wenn der Hostname "+ db +" verwendet wird, löst der in Kubernetes ausgeführte DNS-Dienst die Adresse in die dem Dienst zugeordnete ClusterIP auf. Mit diesem Mechanismus können Pods einander erkennen und miteinander kommunizieren.
Erstellen Sie mit dem vorhandenen Datenbank-Pod und -Dienst einen Pod für die Webanwendung.
Schritt 3 - Stellen Sie die Node.JS-Webanwendung als Pod bereit
Packen Sie das Docker-Image, das Sie im ersten Schritt dieses Lernprogramms erstellt haben, als Pod und stellen Sie es im Cluster bereit. Dies fungiert als Front-End-Webanwendungsebene, auf die Endbenutzer zugreifen können.
Erstellen Sie eine neue YAML-Datei mit dem Namen "+ web-pod.yaml +":
nano web-pod.yaml
Fügen Sie den folgenden Code hinzu, der einen Pod mit einem Container basierend auf dem Docker-Image + sammy / todo-app +
definiert. Es wird über das TCP-Protokoll auf dem Port "+ 3000 +" angezeigt.
web-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
name: web
app:
spec:
containers:
- image: sammy/todo-app
name: myweb
ports:
- containerPort: 3000
Beachten Sie, dass die Definition die Bezeichnungen "+ name" und "+ app" enthält. Ein Dienst verwendet diese Labels, um eingehenden Datenverkehr an die entsprechenden Ports weiterzuleiten.
Führen Sie den folgenden Befehl aus, um den Pod zu erstellen:
kubectl create -f web-pod.yaml
Outputpod "web" created
Überprüfen wir die Erstellung des Pods:
kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
1/1 Running 0 8m
1/1 Running 0 9s
Beachten Sie, dass sowohl die MongoDB-Datenbank als auch die Web-App als Pods ausgeführt werden.
Jetzt werden wir den "+ web +" - Pod für das öffentliche Internet zugänglich machen.
Dienste machen eine Reihe von Pods entweder intern oder extern verfügbar. Definieren wir einen Service, der das "+ web +" - Pod öffentlich verfügbar macht. Wir werden es über einen NodePort verfügbar machen, ein Schema, das den Pod über einen beliebigen Port zugänglich macht, der auf jedem Knoten des Clusters geöffnet ist.
Erstellen Sie eine neue Datei mit dem Namen "+ web-service.yaml +", die diesen Code enthält, der den Service für die App definiert:
apiVersion: v1
kind: Service
metadata:
name: web
labels:
name: web
app:
spec:
selector:
name: web
type: NodePort
ports:
- name: http
port: 3000
targetPort: 3000
protocol: TCP
Der Service erkennt alle Pods im selben Namespace, die dem Label mit dem Namen "+ web +" entsprechen. Der Selektorabschnitt der YAML-Datei definiert diese Zuordnung explizit.
Wir geben an, dass der Service vom Typ "+ NodePort +" ist.
Verwenden Sie "+ kubectl +", um dies an den Cluster zu senden.
kubectl create -f web-service.yml
Diese Ausgabe zeigt an, dass der Service erfolgreich erstellt wurde:
Outputservice "web" created
Lassen Sie uns den Port ermitteln, an dem der Pod verfügbar ist.
kubectl get services
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
db ClusterIP 10.109.114.243 <none> 27017/TCP 12m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 59m
web NodePort 10.107.206.92 <none> 3000: 12s
Anhand dieser Ausgabe sehen wir, dass der Service auf Port + 30770 +
verfügbar ist. Versuchen wir, eine Verbindung zu einem der Worker-Knoten herzustellen.
Beziehen Sie die öffentliche IP-Adresse für einen der Worker-Knoten, die Ihrem Kubernetes-Cluster zugeordnet sind, über die DigitalOcean-Konsole.
image: https://assets.digitalocean.com/articles/webinar_3_kubernetes_stackpoint/w9acP7y.png [DigitalOcean-Konsole mit Arbeiterknoten]
Wenn Sie die IP-Adresse erhalten haben, verwenden Sie den Befehl "+ curl ", um eine HTTP-Anfrage an einen der Knoten an Port " 30770 +" zu senden:
curl http://:30770
Es wird eine Ausgabe ähnlich der folgenden angezeigt:
Output<!DOCTYPE html>
<html>
<head>
<title>Containers Todo Example</title>
<link rel='stylesheet' href='/stylesheets/screen.css' />
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<div id="layout">
<h1 id="page-title">Containers Todo Example</h1>
<div id="list">
<form action="/create" method="post" accept-charset="utf-8">
<div class="item-new">
<input class="input" type="text" name="content" />
</div>
</form>
</div>
<div id="layout-footer"></div>
</div>
<script src="/javascripts/ga.js"></script>
</body>
</html>
Sie haben den Web-Pod und einen Service definiert. Lassen Sie uns nun die Skalierung mit Replikatsätzen betrachten.
Schritt 5 - Skalieren der Webanwendung
Ein Replikatsatz stellt sicher, dass immer eine Mindestanzahl von Pods im Cluster ausgeführt wird. Wenn ein Pod als Replikatsatz verpackt ist, führt Kubernetes immer die in der Spezifikation festgelegte Mindestanzahl von Pods aus.
Löschen Sie den aktuellen Pod und erstellen Sie zwei Pods über das Replikatset neu. Wenn wir den Pod laufen lassen, ist er nicht Teil des Replikatsets. Daher ist es eine gute Idee, Pods über ein Replikatset zu starten, auch wenn die Anzahl nur eins beträgt.
Löschen Sie zunächst den vorhandenen Pod.
kubectl delete pod web
Outputpod "web" deleted
Erstellen Sie nun eine neue Replikatsatzdeklaration. Die Definition des Replikatsatzes ist identisch mit einem Pod. Der Hauptunterschied besteht darin, dass es das Element "+ replica +" enthält, das die Anzahl der auszuführenden Pods definiert. Wie ein Pod enthält er auch Labels als Metadaten, die bei der Serviceerkennung hilfreich sind.
Erstellen Sie die Datei "+ web-rs.yaml +" und fügen Sie den folgenden Code zur Datei hinzu:
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
name: web
labels:
name: web
app: todoapp
spec:
replicas: 2
template:
metadata:
labels:
name: web
spec:
containers:
- name: web
image: sammy/todo-app
ports:
- containerPort: 3000
Speichern und schließen Sie die Datei.
Erstellen Sie nun das Replikatset:
kubectl create -f web-rs.yaml
Outputreplicaset "web" created
Dann überprüfen Sie die Anzahl der Pods:
kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 18m
web-n5l5h 1/1 Running 0 25s
web-wh6nf 1/1 Running 0 25s
Wenn wir über den NodePort auf den Service zugreifen, wird die Anfrage an einen der vom Replikatsatz verwalteten Pods gesendet.
Testen Sie die Funktionalität eines Replikatsets, indem Sie einen der Pods löschen und sehen, was passiert:
kubectl delete pod web-wh6nf
Outputpod "web-wh6nf" deleted
Schauen Sie sich die Pods noch einmal an:
kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 19m
web-n5l5h 1/1 Running 0 1m
web-wh6nf 1/1 Terminating 0 1m
web-ws59m 0/1 ContainerCreating 0 2s
Sobald der Pod gelöscht wird, hat Kubernetes einen neuen erstellt, um sicherzustellen, dass die gewünschte Anzahl beibehalten wird.
Wir können das Replikatset skalieren, um zusätzliche Web-Pods auszuführen.
Führen Sie den folgenden Befehl aus, um die Webanwendung auf 10 Pods zu skalieren.
kubectl scale rs/web --replicas=
Outputreplicaset "web" scaled
Überprüfen Sie die Anzahl der Pods:
kubectl get pods
Sie sehen diese Ausgabe:
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 22m
web-4nh4g 1/1 Running 0 21s
web-7vbb5 1/1 Running 0 21s
web-8zd55 1/1 Running 0 21s
web-f8hvq 0/1 ContainerCreating 0 21s
web-ffrt6 1/1 Running 0 21s
web-k6zv7 0/1 ContainerCreating 0 21s
web-n5l5h 1/1 Running 0 3m
web-qmdxn 1/1 Running 0 21s
web-vc45m 1/1 Running 0 21s
web-ws59m 1/1 Running 0 2m
Kubernetes hat den Prozess der Skalierung des "+ web +" - Pods eingeleitet. Wenn die Anforderung über den NodePort an den Service gesendet wird, wird sie an einen der Pods im Replikatsatz weitergeleitet.
Wenn der Datenverkehr und die Auslastung nachlassen, können wir zur ursprünglichen Konfiguration von zwei Pods zurückkehren.
kubectl scale rs/web --replicas=
Outputreplicaset "web" scaled
Dieser Befehl beendet alle Pods mit Ausnahme von zwei.
kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 24m
web-4nh4g 1/1 Terminating 0 2m
web-7vbb5 1/1 Terminating 0 2m
web-8zd55 1/1 Terminating 0 2m
web-f8hvq 1/1 Terminating 0 2m
web-ffrt6 1/1 Terminating 0 2m
web-k6zv7 1/1 Terminating 0 2m
web-n5l5h 1/1 Running 0 5m
web-qmdxn 1/1 Terminating 0 2m
web-vc45m 1/1 Terminating 0 2m
web-ws59m 1/1 Running 0 4m
Um die Verfügbarkeit des Replikatsets zu überprüfen, löschen Sie einen der Pods und überprüfen Sie die Anzahl.
kubectl delete pod web-ws59m
Outputpod "web-ws59m" deleted
kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 25m
web-n5l5h 1/1 Running 0 7m
web-ws59m 1/1 Terminating 0 5m
web-z6r2g 0/1 ContainerCreating 0 5s
Sobald sich die Anzahl der Pods ändert, passt Kubernetes sie an die in der YAML-Datei definierte Anzahl an. Wenn einer der Web-Pods im Replikatsatz gelöscht wird, wird sofort ein weiterer Pod erstellt, um die gewünschte Anzahl beizubehalten. Dies stellt eine hohe Verfügbarkeit der Anwendung sicher, indem sichergestellt wird, dass die Mindestanzahl von Pods die ganze Zeit ausgeführt wird.
Sie können alle in diesem Lernprogramm erstellten Objekte mit dem folgenden Befehl löschen:
kubectl delete -f db-pod.yaml -f db-service.yaml -f web-rs.yaml -f web-service.yaml
Outputpod "db" deleted
service "db" deleted
replicaset "web" deleted
service "web" deleted
Fazit
In diesem Lernprogramm haben Sie alle in dieser Reihe behandelten Konzepte angewendet, um Microservices-Anwendungen zu packen, bereitzustellen und zu skalieren.
Im nächsten Teil dieser Serie erfahren Sie, wie Sie MongoDB hochverfügbar machen, indem Sie es als StatefulSet ausführen.