Kubernetes (auch bekannt als k8s) ist ein Open-Source-Orchestrierungssystem. Es ermöglicht Benutzern das Bereitstellen, Skalieren und Verwalten von containerisierten Anwendungen mit minimaler Ausfallzeit. In diesem Tutorial lernen Sie, wie Sie eine PHP-Anwendung auf einem Kubernetes-Cluster bereitstellen.
Nginx fungiert als Proxy für PHP-FPM, während eine PHP-Anwendung ausgeführt wird. Die Verwaltung dieser beiden Dienste in einem einzigen Container ist ein schwieriger Prozess. Kubernetes hilft uns, sie in zwei verschiedenen Containern zu verwalten, und reduziert den Aufwand. Es ermöglicht Benutzern außerdem, die Container wiederzuverwenden und sich keine Gedanken über das Erstellen ihres Container-Images für jede neue Version von PHP/Nginx machen zu müssen.
Sie werden Ihre Anwendung und Ihren Proxy-Dienst in zwei separaten Containern ausführen. Das Tutorial bietet außerdem Einblicke in die Verwendung von lokalem Speicher zum Erstellen eines Persistent Volume (PV) und Persistent Volume Claim (PVC). Sie werden diesen PVC dann verwenden, um Ihre Konfigurationsdateien und Ihren Code außerhalb der Container-Images aufzubewahren. Nach Abschluss dieses Tutorials können Sie Ihr Nginx-Image für andere Anwendungen wiederverwenden, die einen Proxy-Server erfordern. Dies können Sie erreichen, indem Sie eine Konfiguration übergeben, anstatt das Image dafür neu zu erstellen.
Voraussetzungen
- Ein grundlegendes Verständnis von Kubernetes (k8s) und seinen Objekten. In diesem Leitfaden finden Sie eine detaillierte Übersicht über das Kubernetes-Ökosystem.
- Ein Kubernetes-Cluster, das auf Ubuntu 18.04 läuft. Folgen Sie diesem Tutorial, um Ihr Kubernetes-Cluster mit kubeadm zu erstellen.
- Zusätzlich müssen Sie Ihren Anwendungscode auf einer öffentlichen URL hosten, zum Beispiel GitHub.
Schritt 1: PHP-FPM- und Nginx-Dienste erstellen
Dieser Schritt hilft Ihnen beim Erstellen von PHP-FPM- und Nginx-Diensten. Jeder Dienst bietet Zugriff auf eine Reihe von Pods innerhalb eines Clusters. Alle in einem Cluster vorhandenen Dienste können über ihre Namen miteinander kommunizieren, ohne IP-Adressen. Der PHP-FPM-Dienst und der Nginx-Dienst bieten Zugriff auf PHP-FPM- bzw. Nginx-Pods.
Sie müssen dem PHP-FPM-Dienst mitteilen, wie er die Nginx-Pods findet, da er als Proxy für die PHP-FPM-Pods fungiert. Hierzu nutzen Sie die automatische Dienstermittlung von Kubernetes’ und verwenden lesbare Namen, um die Anfrage an den jeweiligen Dienst weiterzuleiten.
Um einen Dienst zu erstellen, müssen Sie eine YAML-Datei erstellen, die die Objektdefinition enthält. Diese YAML-Datei hat mindestens die folgenden Tags:
apiVersion: Die Kubernetes-API-Version, zu der die Definition gehört.kind: Die Art des Kubernetes-Objekts, das diese YAML-Datei erstellt. Zum Beispiel: einservice, einjob, oder einpod.metadata: Der Name des Objekts und die verschiedenenlabels, die der Benutzer auf dieses Objekt anwenden möchte, sind unter diesem Tag definiert.spec: Dieses Tag enthält die Objektspezifikation Ihres Objekts, wie z. B. ENVs, das zu verwendende Container-Image und die Ports, über die der Container-Dienst zugänglich sein wird.
Erstellen des PHP-FPM-Dienstes
Erstellen Sie zunächst ein Verzeichnis, um Ihre Kubernetes-Objektdefinition aufzubewahren. Melden Sie sich an Ihrem Master-Node an und erstellen Sie ein Verzeichnis namens “definitions:”
|
1 |
mkdir definitions |
Wechseln Sie in das Verzeichnis definitions:
|
1 |
cd definitions |
Erstellen Sie als Nächstes Ihre PHP-FPM-Dienstdatei als php_service.yaml-Datei:
|
1 |
nano php_fpm_service.yaml |
Legen Sie danach apiVersion und kind in der php_fpm_service.yaml-Datei fest:
|
1 2 |
apiVersion: v1 kind: Service |
Benennen Sie Ihren Dienst als php oder php-fpm, da er Zugriff auf Ihre PHP-FPM-Anwendung bietet:
|
1 2 3 |
… Metadata: name: php |
Versehen Sie Ihren php-Dienst mit dem Label tier: backend, da die PHP-Anwendung hinter diesem Dienst ausgeführt wird:
|
1 2 3 |
… labels: tier: backend |
Ein Dienst verwendet die selector-Labels, um zu bestimmen, auf welche Pods zugegriffen werden soll. Jeder Pod, der mit diesen Labels übereinstimmt, wird bedient, unabhängig davon, wann der Pod erstellt wurde. Sie werden später in diesem Tutorial lernen, wie Sie Ihren Pods Labels hinzufügen.
Fügen Sie das Label tier: backend hinzu, das Ihren Pod der Backend-Ebene zuweist, zusammen mit dem Label app: php-fpm , um anzugeben, dass der Pod eine PHP-FPM-Anwendung ausführt. Sie müssen diese Labels nach dem Abschnitt metadata hinzufügen:
|
1 2 3 4 5 |
… spec: selector: app: php-fpm tier: backend |
Als Nächstes müssen Sie den Port deklarieren, um auf diesen php-fpm-Dienst unter spec zuzugreifen. Sie können einen beliebigen Port Ihrer Wahl hinzufügen, aber wir werden in diesem Tutorial den Port 9000 verwenden:
|
1 2 3 4 |
... ports: - protocol: TCP port: 9000 |
Sobald Sie die obigen Schritte ausgeführt haben, sieht Ihre Datei php_fpm_service.yaml wie folgt aus:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
apiVersion: v1 kind: Service metadata: name: php labels: tier: backend spec: selector: app: php tier: backend ports: - protocol: TCP port: 9000 |
Drücken Sie Strg + O zum Speichern der Datei, und drücken Sie dann Strg + X zum Beenden von nano.
Anwenden des kubectl-Befehls zum Erstellen des PHP-Dienstes
Sobald die Objektdefinition für Ihren Dienst erstellt ist, führen Sie den Befehl kubectl apply mit dem Argument -f aus, indem Sie Ihre Datei php_fpm_service.yaml angeben:
|
1 |
kubectl apply -f php_fpm_service.yaml |
Die Ausgabe des obigen Befehls sollte wie folgt aussehen:
|
1 |
service/php created |
Führen Sie den folgenden Befehl aus, um zu überprüfen, ob Ihr php-fpm-Dienst ausgeführt wird:
|
1 |
$ kubectl get svc |
Sie können sehen, dass der php-fpm-Dienst aktiv ist und ausgeführt wird:
|
1 2 3 |
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10m php ClusterIP 10.100.59.238 <none> 9000/TCP 5m |
Erstellen des Nginx-Dienstes
Da Ihr PHP-FPM-Dienst nun bereit ist, ist es an der Zeit, auch Ihren Nginx-Dienst zu erstellen. Erstellen und öffnen Sie eine neue YAML-Datei für diesen Dienst namens nginx_service.yaml im Editor:
|
1 |
$ nano nginx_service.yaml |
Benennen Sie diesen Dienst als nginx, da er auf die Nginx-Pods abzielt. Dieser Dienst gehört ebenfalls zum Backend, daher sollten Sie ihm ein Label tier: backend hinzufügen:
|
1 2 3 4 5 6 |
apiVersion: v1 kind: Service metadata: name: nginx labels: tier: backend |
Fügen Sie wie beim php-fpm-Dienst die Selektor-Labels app: nginx und tier: backend hinzu, um die Pods als Ziel festzulegen. Fügen Sie den Standard-HTTP-Port 80 hinzu, um auf diesen Dienst zuzugreifen:
|
1 2 3 4 5 6 7 8 |
... spec: selector: app: nginx tier: backend ports: - protocol: TCP port: 80 |
Der Nginx-Dienst kann über die öffentliche IP-Adresse öffentlich im Internet zugänglich sein. Sie können die IP Ihres Worker-Nodes als your_public_ip hinzufügen. Fügen Sie die folgenden Zeilen unter spec.externalIPs:
|
1 2 3 4 5 |
... spec: externalIPs: - your_public_ip |
Ihre Datei nginx_service.yaml sollte wie folgt aussehen, sobald Sie alle oben genannten Schritte abgeschlossen haben:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
apiVersion: v1 kind: Service metadata: name: nginx labels: tier: backend spec: selector: app: nginx tier: backend ports: - protocol: TCP port: 80 externalIPs: - your_public_ip |
Speichern und schließen Sie die Datei, nachdem Sie alle oben erforderlichen Parameter hinzugefügt haben.
Anwenden des kubectl-Befehls zum Erstellen des Nginx-Dienstes
|
1 |
kubectl apply -f nginx_service.yaml |
|
1 |
service/nginx created |
|
1 |
$ kubectl get svc |
|
1 2 3 4 |
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13m nginx ClusterIP 10.102.160.47 ihre_oeffentliche_ip 80/TCP 50s php ClusterIP 10.100.59.238 <none> 9000/TCP 8m |
|
1 |
$ kubectl delete svc/service_name |
Step 2: Lokalen Speicher und Persistent Volume erstellen
Kubernetes bietet verschiedene Speicher-Plug-ins, mit denen Sie Speicherplatz für Ihre Umgebung erstellen können. Dieser Schritt führt Sie durch die Erstellung eines lokalen StorageClass und wie diese StorageClass weiter zur Erstellung eines Persistent Volume verwendet werden kann.
Erstellen eines lokalen Speichers
Erstellen Sie eine Datei, zum Beispiel storageClass.yaml, in Ihrem Editor:
|
1 |
$nano storageClass.yaml |
Fügen Sie kind als "storageClass" und apiVersion als "storage.k8s.io/v1" wie folgt hinzu:
|
1 2 |
kind: StorageClass apiVersion: storage.k8s.io/v1 |
Benennen Sie diese StorageClass als "my-local-storage" und fügen Sie provisioner und volumeBindingMode wie folgt hinzu:
|
1 2 3 4 5 |
… metadata: name: my-local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: Immediate |
Speichern und schließen Sie die Datei. Ihre endgültige storageClass.yaml-Datei sollte wie folgt aussehen:
|
1 2 3 4 5 6 |
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: my-local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer |
Erstellen Sie nun die StorageClass, indem Sie den Befehl kubectl create wie folgt ausführen:
|
1 |
$ kubectl create -f storageClass.yaml |
Nach Ausführung des obigen Befehls sollten Sie die folgende Ausgabe erhalten:
|
1 |
storageclass.storage.k8s.io/my-local-storage created |
Lokales Persistent Volume erstellen
Nachdem Sie den lokalen Speicher erstellt haben, können Sie Ihr lokales Persistent Volume erstellen. Ein Persistent Volume, auch bekannt als PV, ist ein Blockspeicher mit einer bestimmten Größe, der unabhängig vom Lebenszyklus eines Pods ist. Ein lokales Persistent Volume ist nichts anderes als eine lokale Festplatte oder ein Verzeichnis, das auf einem Kubernetes-Cluster-Knoten verfügbar ist. Dieses lokale Persistent Volume ermöglicht es Benutzern, auf sehr einfache und dennoch portable Weise über einen lokalen Persistent Volume Claim auf den lokalen Speicher zuzugreifen. Sie können dieses lokale Persistent Volume mithilfe der soeben erstellten StorageClass erstellen. Öffnen Sie eine Datei, zum Beispiel persistentVolume.yaml, in Ihrem Editor:
|
1 |
$ nano persistentVolume.yaml |
Geben Sie diesem Persistent Volume einen Namen, zum Beispiel "my-local-pv":
|
1 2 3 4 |
apiVersion: v1 kind: PersistentVolume metadata: name: my-local-pv |
Sie können beim Erstellen eines lokalen Persistent Volume die Speicherkapazität je nach Bedarf hinzufügen. In diesem Tutorial verwenden wir 5 Gi für den Speicher:
|
1 2 3 4 |
… spec: capacity: storage: 5Gi |
Fügen Sie die accessModes und die persistentVolumeReclaimPolicy hinzu und geben Sie denselben storageClassName an, der in storageClass.yaml verwendet wurde:
|
1 2 3 4 5 |
… accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: my-local-storage |
Fügen Sie local.path für Ihr Persistent Volume wie unten beschrieben hinzu:
|
1 2 3 |
… local: path: /mnt/disk/vol |
Nach dem Hinzufügen aller erforderlichen Felder sollte Ihre persistentVolume.yaml-Datei wie folgt aussehen:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
apiVersion: v1 kind: PersistentVolume metadata: name: my-local-pv spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: my-local-storage local: path: /mnt/disk/vol nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - worker |
Lokales Volume vorbereiten
Jetzt müssen wir ein lokales Volume auf dem “worker”-Knoten vorbereiten, wie wir es in der persistentVolume.yaml-Datei hinzugefügt haben. Führen Sie die folgenden Befehle auf dem Knoten aus, den Sie in persistentVolume konfiguriert haben. In diesem Fall ist es der “worker”-Knoten:
|
1 2 3 |
$ DIRNAME="vol" $ mkdir -p /mnt/disk/$DIRNAME $ chmod 777 /mnt/disk/$DIRNAME |
Führen Sie den folgenden Befehl auf dem Master-Knoten aus, auf dem sich Ihre persistentVolume.yaml-Datei befindet:
|
1 |
kubectl create -f persistentVolume.yaml |
Sie sollten die folgende Ausgabe erhalten:
|
1 |
persistentvolume/my-local-pv created |
Da Sie Ihren lokalen Speicher und Ihr Persistent Volume erfolgreich erstellt haben, können Sie nun fortfahren und einen Persistent Volume Claim erstellen, um Ihren Anwendungscode und Ihre Konfigurationsdateien aufzunehmen.
Step 3: Erstellen Sie das Persistent Volume
Ihr Anwendungscode muss sicher aufbewahrt werden, während Sie Ihre Pods verwalten oder aktualisieren. Hierfür verwenden Sie das im vorherigen Schritt erstellte Persistent Volume, auf das über einen PersistentVolumeClaim (oder PVC) zugegriffen wird. Dieser PVC bindet das PV am erforderlichen Pfad ein.
Öffnen Sie eine Datei, beispielsweise code_volume.yaml, in Ihrem Editor:
|
1 |
$ nano code_volume.yaml |
Benennen Sie Ihren PVC als code, indem Sie die folgenden Parameter und Werte zu Ihrer Datei hinzufügen:
|
1 2 3 4 |
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: code |
Der spec-Bereich eines PVC enthält die folgenden Elemente:
- accessModes: Für dieses Feld gibt es verschiedene mögliche Werte wie folgt:
- ReadWriteOnce – Bindet das Volume für einen einzelnen Knoten mit Lese- und Schreibberechtigungen ein.
- ReadOnlyMany – Bindet das Volume für viele Knoten mit reiner Leseberechtigung ein.
- ReadWriteMany – Bindet das Volume für viele Knoten mit Lese- und Schreibberechtigungen ein.
- resources: Definiert den erforderlichen Speicherplatz.
Da der lokale Speicher nur an einen einzelnen Node gemountet ist, müssen Sie den accessMode auf ReadWriteOnce festlegen. In diesem Tutorial fügen Sie nur ein kleines Stück Anwendungscode hinzu, weshalb 1 GB Speicherplatz hier ausreicht. Wenn Sie jedoch eine größere Menge an Daten oder Code speichern möchten, können Sie den Parameter storage entsprechend Ihren Anforderungen anpassen. Beachten Sie, dass Sie die Speichergröße nach der Erstellung des Volumes zwar erhöhen können, eine Verringerung jedoch nicht unterstützt wird:
|
1 2 3 4 5 6 7 |
... spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi |
Deklarieren Sie nun die Storage-Klasse, die der Kubernetes-Cluster für die Zuweisung zu den Volumes verwenden soll. Verwenden Sie hier die im vorherigen Schritt erstellte Storage-Klasse my-local-storage für Ihren storageClassName:
|
1 2 |
... storageClassName: my-local-storage |
Nach Abschluss der obigen Schritte sollte Ihre code_volume.yaml-Datei wie folgt aussehen:
|
1 2 3 4 5 6 7 8 9 10 11 |
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: code spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: my-local-storage |
Speichern und schließen Sie nun die Datei.
PVC erstellen
Erstellen Sie den Code-PVC, indem Sie den Befehl kubectl apply ausführen:
|
1 |
$ kubectl apply -f code_volume.yaml |
Sie sollten die folgende Ausgabe erhalten, die anzeigt, dass das Objekt erfolgreich erstellt wurde und bereit ist, Ihren 1-GB-PVC als Volume zu mounten:
|
1 |
persistentvolumeclaim/code created |
Sie können den folgenden Befehl ausführen, um das verfügbare Persistent Volume (PV) zu überprüfen:
|
1 |
$ kubectl get pv |
Die Ausgabe des obigen Befehls sollte wie folgt aussehen:
|
1 2 |
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-ca4df10f-ab8c-11e8-b89d-12331aa95b13 1Gi RWO Delete Bound default/code do-block-storage 2m |
Alle oben genannten Felder, mit Ausnahme von Reclaim Policy und Status, sind eine Übersicht über Ihre Konfigurationsdatei. Die Reclaim Policy definiert, was mit dem PV geschieht, sobald der darauf zugreifende PVC gelöscht wird. Der Wert Delete entfernt das PV sowohl aus dem Kubernetes-Cluster als auch aus der Speicherinfrastruktur. Sie können sich auf die Kubernetes-PV-Dokumentation beziehen, um ein klares Verständnis von Reclaim Policy und Status zu erhalten.
Sie können nun Ihre Pods mithilfe eines Deployments erstellen, da Sie Ihr Persistent Volume erfolgreich unter Verwendung des lokalen Speichers erstellt haben.
Step 4: Create Deployment for your PHP-FPM Application
Dieser Schritt hilft Ihnen bei der Erstellung Ihres PHP-FPM-Pods mithilfe eines Deployments. Ein Deployment verwendet ReplicaSets, um eine stabile Methode zum Erstellen, Aktualisieren und Verwalten Ihrer Pods bereitzustellen. Ein Deployment setzt seine Pods automatisch auf ein vorheriges Image zurück.
Der spec.selector-Schlüssel im Deployment listet alle Labels der von ihm verwalteten Pods auf. Er verwendet auch den template-Schlüssel, um die erforderlichen Pods zu erstellen.
In diesem Schritt führen wir auch die Anwendung von Init-Containern ein. Die Init-Container führen einige Befehle vor den regulären Containern aus, die unter dem Template des Pods angegeben sind. Hier verwendet der Init-Container GitHub Gist (https://gist.github.com/), um eine Beispiel-index.php-Datei abzurufen. Der Inhalt der Beispieldatei ist:
|
1 2 |
<?php echo phpinfo(); |
PHP-Deployment erstellen
Öffnen Sie eine neue Datei namens php_deployment.yaml in Ihrem Editor, um Ihr Deployment zu erstellen:
|
1 |
$ nano php_deployment.yaml |
Benennen Sie nun das Deployment-Objekt PHP, da dieses Deployment Ihre PHP-FPM-Pods verwalten wird. Fügen Sie das Label tier: backend hinzu, da der Pod zur Backend-Ebene gehören wird:
|
1 2 3 4 5 6 |
apiVersion: apps/v1 kind: Deployment metadata: name: php labels: tier: backend |
Geben Sie mithilfe des Parameters replica die Anzahl der Kopien dieses Pods an, die erstellt werden sollen. Die Anzahl der Replikate kann je nach Ihren Anforderungen und den verfügbaren Ressourcen variieren. In diesem Tutorial erstellen Sie nur ein Replikat Ihres Pods:
|
1 2 3 4 |
... spec: replicas: 1 |
Fügen Sie app: php und tier:backend-Labels unter dem Schlüssel selector hinzu, der angibt, dass dieses Deployment Pods verwalten wird, die mit diesen beiden Labels übereinstimmen:
|
1 2 3 4 5 |
... selector: matchLabels: app: php tier: backend |
Nun benötigt die Objektdefinition Ihres Pods ein Template unter Ihrer Deployment-Spezifikation (spec). Dieses Template definiert die Spezifikation, die zur Erstellung Ihres Pods erforderlich ist. Fügen Sie zunächst die Labels hinzu, die für den php-Service-Selector und die matchLabels des Deployments angegeben wurden. Fügen Sie dann app:php und tier:backend unter template.metadata.labels:
|
1 2 3 4 5 6 7 |
... template: metadata: labels: app: php tier: backend |
First, you need to specify all the volumes that your containers will access. Name this volume code as you had created a PVC named code to hold your application code:
|
1 2 3 4 5 6 |
... spec: volumes: - name: code persistentVolumeClaim: claimName: code |
Geben Sie als Nächstes den Containernamen zusammen mit dem Image an, das Sie in Ihrem Pod ausführen möchten. Im Docker Store (https://hub.docker.com/explore/) stehen verschiedene Images zur Verfügung, aber in diesem Tutorial verwenden wir das php:7-fpm-Image:
|
1 2 3 4 |
... containers: - name: php image: php:7-fpm |
Binden Sie nun die Volumes ein, auf die der Container Zugriff benötigt. Da dieser Container Ihren PHP-Code ausführen wird, benötigt er Zugriff auf das im vorherigen Schritt erstellte Volume code. In diesem Schritt erfahren Sie auch, wie Sie Ihren Anwendungscode mithilfe eines Init-Containers kopieren.
To download the code, this tutorial will guide you on how to use a single Init Container with busybox. Busybox is a small container with wget utility that you will use to achieve this.
Fügen Sie zuerst Ihren initContainer unter spec.template.spec hinzu und geben Sie das busybox-Image an:
|
1 2 3 4 |
... initContainers: - name: install image: busybox |
Damit der Code in das Volume code heruntergeladen werden kann, benötigt Ihr Init-Container Zugriff darauf. Binden Sie das Volume code am Pfad /code unter spec.template.spec.initContainers:
|
1 2 3 4 |
... volumeMounts: - name: code mountPath: /code |
Jeder Init-Container muss einen Befehl ausführen. Dieser Init-Container verwendet wget, um den code von Github in das Verzeichnis /code herunterzuladen. Sie können die Option -O übergeben, um dieser heruntergeladenen Datei einen Namen zu geben, und Sie können diese Datei index.php.
Fügen Sie außerdem die folgenden Zeilen unter dem install-Container in spec.template.spec.initContainers:
|
1 2 3 4 5 6 |
... command: - wget - "-O" - "/code/index.php" - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php |
Nachdem Sie alle diese Schritte abgeschlossen haben, sollte Ihre php_deployment.yaml-Datei wie folgt aussehen:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
apiVersion: apps/v1 kind: Deployment metadata: name: php labels: tier: backend spec: replicas: 1 selector: matchLabels: app: php tier: backend template: metadata: labels: app: php tier: backend spec: volumes: - name: code persistentVolumeClaim: claimName: code containers: - name: php image: php:7-fpm volumeMounts: - name: code mountPath: /code initContainers: - name: install image: busybox volumeMounts: - name: code mountPath: /code command: - wget - "-O" - "/code/index.php" - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php |
Sie können die Datei nun speichern und schließen. Erstellen Sie als Nächstes Ihr PHP-FPM-Deployment mit dem Befehl kubectl apply:
|
1 |
$ kubectl apply -f php_deployment.yaml |
Die erfolgreiche Erstellung des Deployments sollte die folgende Ausgabe liefern:
|
1 |
deployment.apps/php created |
Dieses Deployment beginnt mit dem Herunterladen der angegebenen Images, fordert dann das PersistentVolume von Ihrem PersistentVolumeClaim an und führt anschließend Ihre initContainers aus. Sobald dieser Schritt abgeschlossen ist, werden die Container ausgeführt und die Volumes am angegebenen Mount-Pfad gemountet. Nach Abschluss all dieser Schritte ist Ihr Pod betriebsbereit.
Sie können den folgenden Befehl ausführen, um Ihr Deployment anzuzeigen:
|
1 |
$ kubectl get deployments |
Nach Ausführung des obigen Befehls sollten Sie die folgende Ausgabe erhalten:
|
1 2 |
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE php 1 1 1 0 19s |
Anhand dieser Ausgabe können Sie den aktuellen Zustand des Deployments nachvollziehen. Ein Deployment ist ein Controller, der den gewünschten Zustand aufrechterhält. Das Feld DESIRED gibt an, dass es 1 Replikat des Pods namens php gibt. Das Feld CURRENT gibt an, wie viele Replikate des DESIRED-Zustands derzeit ausgeführt werden. Bei einem fehlerfreien Pod sollte dies mit dem DESIRED-Zustand übereinstimmen. Weitere Informationen zu den übrigen Feldern finden Sie in der Kubernetes-Deployments-Dokumentation.
Um danach den Status Ihres laufenden Pods zu überprüfen, können Sie den folgenden Befehl ausführen:
|
1 |
$ kubectl get pods |
Die Ausgabe dieses Befehls kann variieren, je nachdem, wie viel Zeit seit der Erstellung Ihres Deployments vergangen ist. Wenn er kurz nach der Erstellung des Deployments ausgeführt wird, ähnelt die Ausgabe der folgenden:
|
1 2 |
NAME READY STATUS RESTARTS AGE php-5d8f6bbf7f-56df2 0/1 Init:0/1 0 9s |
Erklärung:
Diese Spalten stellen die folgenden Informationen dar:
- Ready: Die Anzahl der aktuellen/gewünschten Replikate, die diesen Pod ausführen.
- Status: Der Status Ihres Pods. Init:0/1 zeigt an, dass die Init-Container ausgeführt werden und 0 von 1 Init-Containern die Ausführung beendet haben.
- Restarts: Dies gibt an, wie oft dieser Prozess neu gestartet wurde, um den Pod zu starten.
Es kann einige Minuten dauern, bis sich der Status Ihres Pods ändert in podInitializing abhängig von der Komplexität Ihrer Startup-Skripte:
|
1 2 |
NAME READY STATUS RESTARTS AGE php-5d8f6bbf7f-56df2 0/1 podInitializing 0 39s |
Dies zeigt an, dass die Init-Container erfolgreich ausgeführt wurden und die Container nun initialisiert werden:
|
1 2 |
NAME READY STATUS RESTARTS AGE php-5d8f6bbf7f-56df2 1/1 Running 0 4m10s |
Wie Sie sehen können, ist Ihr Pod nun betriebsbereit. Falls Ihr Pod jedoch nicht startet, können Sie die folgenden Befehle zu Debugging-Zwecken ausführen:
1. Um detaillierte Informationen zum Pod anzuzeigen:
|
1 |
$ kubectl describe pods pod-name |
2. Um die Logs des Pods anzuzeigen:
|
1 |
$ kubectl logs pod-name |
3. Um die Logs eines bestimmten Containers im Pod anzuzeigen:
|
1 |
$ kubectl logs pod-name container-name |
Herzlichen Glückwunsch! Sie haben den Anwendungscode erfolgreich gemountet und der PHP-FPM-Dienst ist bereit, Verbindungen zu verarbeiten. Auf ähnliche Weise können Sie Ihr Nginx-Deployment erstellen.
Schritt 5: Erstellen Sie Ihr Nginx-Deployment
Dieser Schritt führt Sie durch die Konfiguration von Nginx mithilfe einer ConfigMap. Eine ConfigMap speichert alle Ihre erforderlichen Konfigurationen in einem Schlüssel-Wert-Format, das in anderen Kubernetes-Objektdefinitionen verwendet wird. Mit diesem Ansatz haben Sie die Flexibilität, das Nginx-Image bei Bedarf wiederzuverwenden oder durch eine andere Version zu ersetzen. Sie können die ConfigMap aktualisieren, und diese Änderungen werden automatisch auf alle Pods repliziert, die diese ConfigMap.
Öffnen Sie zu Beginn eine nginx_configmap.yaml-Datei in Ihrem Editor:
|
1 |
$ nano nginx_configMap.yaml |
Nennen Sie diese ConfigMap nun nginx-config und fügen Sie sie dem Microservice tier: backend hinzu:
|
1 2 3 4 5 6 |
apiVersion: v1 kind: ConfigMap metadata: name: nginx-config labels: tier: backend |
Zusätzlich können Sie die Daten zur ConfigMap hinzufügen. Fügen Sie einen Schlüssel namens config hinzu und tragen Sie den gesamten Inhalt der Nginx-Konfigurationsdatei als Wert ein.
Da Kubernetes Anfragen an die jeweiligen Hosts für einen Dienst weiterleiten kann, können Sie den Namen Ihres PHP-FPM-Dienstes unter dem Parameter fastcgi_pass anstelle seiner IP-Adresse eingeben. Fügen Sie die folgenden Codezeilen zu Ihrer nginx_configMap.yaml-Datei hinzu:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
... data: config : | server { index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /code; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } } |
Nach Abschluss sieht Ihre nginx_configMap.yaml-Datei wie folgt aus:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
apiVersion: v1 kind: ConfigMap metadata: name: nginx-config labels: tier: backend data: config : | server { index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /code; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } } |
Sie können den Editor nun speichern und beenden. Führen Sie nun den kubectl apply-Befehl aus, um die ConfigMap:
|
1 |
$ kubectl apply -f nginx_configMap.yaml |
Danach sollten Sie die folgende Ausgabe auf Ihrem Bildschirm sehen:
|
1 |
configmap/nginx-config erstellt |
Sie haben Ihre Nginx-Configmap erfolgreich erstellt. Jetzt können Sie Ihr Nginx-Deployment erstellen.
Nginx-Deployment erstellen
Erstellen Sie zunächst eine neue Datei namens nginx_deployment.yaml im Editor:
|
1 |
$ nano nginx_deployment.yaml |
Nennen Sie dieses Deployment nginx und fügen Sie das Label tier: backend hinzu:
|
1 2 3 4 5 6 7 |
apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: tier: backend |
Geben Sie danach die Anzahl der Replikate an, indem Sie das Feld replica in der Deployment-Spezifikation hinzufügen, und fügen Sie die Labels app: nginx und tier: backend hinzu:
|
1 2 3 4 5 6 7 |
... spec: replicas: 1 selector: matchLabels: app: nginx tier: backend |
Fügen Sie auf ähnliche Weise das Pod-Template hinzu. Stellen Sie sicher, dass Sie dieselben Labels hinzufügen, die Sie im selector.matchLabels des Deployments hinzugefügt haben. Sie können Folgendes hinzufügen:
|
1 2 3 4 5 6 |
... template: metadata: labels: app: nginx tier: backend |
Geben Sie Nginx Zugriff auf den zuvor erstellten Code-PVC, indem Sie die folgenden Parameter unter spec.template.spec.volumes:
|
1 2 3 4 5 6 |
... spec: volumes: - name: code persistentVolumeClaim: claimName: code |
|
1 2 3 4 5 6 7 |
... - name: config configMap: name: nginx-config items: - key: config path: site.conf |
Warnung: Der Inhalt des Schlüssels ersetzt den mountPath des Volumes, wenn keine Datei angegeben ist. Mit anderen Worten: Sie verlieren alle Inhalte im Zielordner, wenn kein Pfad explizit angegeben wird.
Geben Sie nun den Namen, das Image und den Port an, den Sie in Ihrem Pod verwenden möchten. Hier verwenden wir das Image nginx:1.7.9 und den Port 80. Fügen Sie diese unter spec.template.spec-Abschnitt:
|
1 2 3 4 5 6 |
... containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 |
Binden Sie außerdem das Code-Volume unter /code ein, da sowohl Nginx als auch PHP-FPM auf die Datei unter demselben Pfad zugreifen müssen:
|
1 2 3 4 |
... volumeMounts: - name: code mountPath: /code |
Das nginx-1.7.9-Image lädt automatisch jede Konfigurationsdatei im Ordner /etc/nginx/conf.d. Wenn wir nun das Config-Volume in diesem Verzeichnis einbinden, wird /etc/nginx/conf.d/site.conf erstellt. Fügen Sie Folgendes unter dem volumeMount-Abschnitt hinzu:
|
1 2 3 |
... - name: config mountPath: /etc/nginx/conf.d |
Nachdem Sie alle oben genannten Schritte ausgeführt haben, sollte Ihre nginx_deployment.yaml-Datei wie folgt aussehen:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: tier: backend spec: replicas: 1 selector: matchLabels: app: nginx tier: backend template: metadata: labels: app: nginx tier: backend spec: volumes: - name: code persistentVolumeClaim: claimName: code - name: config configMap: name: nginx-config items: - key: config path: site.conf containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 volumeMounts: - name: code mountPath: /code - name: config mountPath: /etc/nginx/conf.d |
Sie können die Datei nun speichern und schließen und das Nginx-Deployment erstellen, indem Sie den folgenden Befehl ausführen:
|
1 |
$ kubectl apply -f nginx_deployment.yaml |
Nach erfolgreicher Ausführung des Befehls sollten Sie die folgende Ausgabe sehen:
|
1 |
deployment.apps/nginx created |
Sie können alle Ihre Deployments auflisten, indem Sie die folgenden Befehle ausführen:
|
1 |
$ kubectl get deployments |
Sie sollten nun sowohl das Nginx- als auch das PHP-FPM-Deployment sehen:
Darüber hinaus können Sie den folgenden Befehl ausführen, um die Pods aufzulisten, die von den beiden oben aufgeführten Deployments verwaltet werden:
|
1 |
$ kubectl get pods |
Sie werden sehen, dass beide Pods wie folgt aktiv sind und ausgeführt werden:
Da alle Ihre Kubernetes-Objekte zu diesem Zeitpunkt aktiv sind, können Sie nun über Ihren Browser auf den Nginx-Dienst zugreifen.
Führen Sie den folgenden Befehl aus, um die Dienste aufzulisten:
|
1 |
$ kubectl get services -o wide |
Notieren Sie sich die External IP Ihres Nginx-Dienstes:
Mit dieser External IP des Nginx-Dienstes können Sie nun Ihren Server besuchen, indem Sie http://your_public_ip in Ihren Browser eingeben. Sie sollten die Ausgabe von php_info() sehen, die bestätigt, dass Ihre Kubernetes-Dienste aktiv sind und ausgeführt werden.
Fazit
In diesem Tutorial haben Sie Ihre PHP-FPM- und Nginx-Dienste containerisiert, um sie unabhängig voneinander zu verwalten. Dadurch verbessern Sie nicht nur die Skalierbarkeit Ihres Projekts, sondern nutzen auch Ihre Ressourcen effizienter. Sie haben außerdem gelernt, wie Sie lokalen Speicher und ein Persistent Volume erstellen, um Ihren Anwendungscode auf einem Volume zu speichern und Ihre Dienste in Zukunft problemlos aktualisieren zu können. Auf diese Weise haben Sie die Benutzerfreundlichkeit und Wartbarkeit Ihres Codes verbessert.
Werfen Sie außerdem einen Blick auf unsere anderen Tutorials zu Docker und Kubernetes, die Sie auf unserem Blog:
- Kubernetes kennenlernen
- So erstellen Sie einen Kubernetes-Cluster mit Kubeadm auf Ubuntu 18.04
- Docker-Ressourcen bereinigen – Images, Container und Volumes
- Bereitstellung von Laravel, Nginx und MySQL mit Docker Compose
- So installieren & betreiben Sie Docker auf Ubuntu in der Public Cloud
Viel Spaß beim Computing!


Kommentare
Noch keine Kommentare. Schreiben Sie den ersten.