Webinar-Reihe: Bereitstellen und Skalieren von Mikrodiensten in Kubernetes

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:

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.

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.