Webinar-Reihe: Bausteine ​​für das Ausführen von CI / CD mit Kubernetes

[.Hinweis]##

Webinar-Reihe

Dieser Artikel ergänzt awebinar series on doing CI/CD with Kubernetes. In dieser Reihe wird erläutert, wie Sie mit Cloud Native Anwendungen erstellen, testen und bereitstellen. Dabei werden die Themen Release-Management, Cloud Native-Tools, Service Meshes und CI / CD-Tools behandelt, die mit Kubernetes verwendet werden können. Es soll Entwicklern und Unternehmen helfen, die CI / CD-Best Practices mit Kubernetes in ihre Workflows integrieren möchten.

Dieses Tutorial enthält die Konzepte und Befehle aus der ersten Sitzung der Serie, Bausteine ​​für das Ausführen von CI / CD mit Kubernetes.

Einführung

Wenn Sie mitcontainers beginnen, möchten Sie wahrscheinlich wissen, wie das Erstellen, Testen und Bereitstellen automatisiert wird. Indem Sie einenCloud Native-Ansatz für diese Prozesse verwenden, können Sie die richtigen Infrastruktur-APIs nutzen, um Anwendungen auf automatisierte Weise zu verpacken und bereitzustellen.

Zwei Bausteine ​​für die Automatisierung sindcontainer images undcontainer orchestrators. In den letzten Jahren wurdeKubernetes zur Standardauswahl für die Container-Orchestrierung. In diesem ersten Artikel derCI/CD with Kubernetes-Serie werden Sie:

  • Erstellen Sie Containerbilder mitDocker,Buildah undKaniko.

  • Richten Sie einen Kubernetes-Cluster mitTerraform ein und erstellen SieDeployments undServices.

  • Erweitern Sie die Funktionalität eines Kubernetes-Clusters mitCustom Resources.

Am Ende dieses Lernprogramms werden Container-Images mit Docker, Buildah und Kaniko sowie ein Kubernetes-Cluster mit Bereitstellungen, Diensten und benutzerdefinierten Ressourcen erstellt.

Zukünftige Artikel in der Reihe werden verwandte Themen behandeln: Paketverwaltung für Kubernetes, CI / CD-Tools wieJenkins X undSpinnaker, Services Meshes und GitOps.

Voraussetzungen

[[Schritt-1 - Erstellen von Container-Images mit Docker und Buildah]] == Schritt 1 - Erstellen von Container-Images mit Docker und Buildah

Ein Container-Image ist eine eigenständige Entität mit eigenem Anwendungscode, eigener Laufzeit und eigenen Abhängigkeiten, mit denen Sie Container erstellen und ausführen können. Sie können verschiedene Tools verwenden, um Container-Images zu erstellen. In diesem Schritt erstellen Sie Container mit zwei davon: Docker und Buildah.

Erstellen von Containerbildern mit Dockerdateien

Docker erstellt Ihre Container-Images automatisch, indem Anweisungen aus einer Docker-Datei gelesen werden, einer Textdatei, die die zum Zusammenstellen eines Container-Images erforderlichen Befehle enthält. Mit dem Befehldocker image build können Sie einen automatisierten Build erstellen, der die in der Docker-Datei bereitgestellten Befehlszeilenanweisungen ausführt. Wenn Sie das Image erstellen, übergeben Sie auch diebuild context mit der Docker-Datei, die die Dateien enthält, die zum Erstellen einer Umgebung und zum Ausführen einer Anwendung im Container-Image erforderlich sind.

In der Regel erstellen Sie einen Projektordner für Ihre Docker-Datei und erstellen den Kontext. Erstellen Sie zunächst einen Ordner mit dem Namendemo:

mkdir demo
cd demo

Erstellen Sie als Nächstes eine Docker-Datei im Ordnerdemo:

nano Dockerfile

Fügen Sie der Datei den folgenden Inhalt hinzu:

~/demo/Dockerfile

FROM ubuntu:16.04

LABEL MAINTAINER [email protected]

RUN apt-get update \
    && apt-get install -y nginx \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
    && echo "daemon off;" >> /etc/nginx/nginx.conf

EXPOSE 80
CMD ["nginx"]

Diese Docker-Datei besteht aus einer Reihe von Anweisungen, mit denen ein Image zum Ausführen von Nginx erstellt wird. Während des Erstellungsprozesses fungiertubuntu:16.04 als Basis-Image und das Paketnginx wird installiert. Mit der AnweisungCMD haben Sie auchnginx als Standardbefehl konfiguriert, wenn der Container gestartet wird.

Als Nächstes erstellen Sie das Container-Image mit dem Befehldocker image build, wobei Sie das aktuelle Verzeichnis (.) Als Erstellungskontext verwenden. Wenn Sie die Option-t an diesen Befehl übergeben, wird das Bildnkhare/nginx:latest benannt:

sudo docker image build -t nkhare/nginx:latest .

Sie werden die folgende Ausgabe sehen:

OutputSending build context to Docker daemon  49.25MB
Step 1/5 : FROM ubuntu:16.04
 ---> 7aa3602ab41e
Step 2/5 : MAINTAINER [email protected]
 ---> Using cache
 ---> 552b90c2ff8d
Step 3/5 : RUN apt-get update     && apt-get install -y nginx     && apt-get clean     && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*     && echo "daemon off;" >> /etc/nginx/nginx.conf
 ---> Using cache
 ---> 6bea966278d8
Step 4/5 : EXPOSE 80
 ---> Using cache
 ---> 8f1c4281309e
Step 5/5 : CMD ["nginx"]
 ---> Using cache
 ---> f545da818f47
Successfully built f545da818f47
Successfully tagged nginx:latest

Ihr Image ist jetzt erstellt. Sie können Ihre Docker-Bilder mit dem folgenden Befehl auflisten:

docker image ls
OutputREPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nkhare/nginx        latest              4073540cbcec        3 seconds ago       171MB
ubuntu              16.04               7aa3602ab41e        11 days ago

Sie können jetzt das Bildnkhare/nginx:latestverwenden, um Container zu erstellen.

Erstellen von Containerbildern mit Project Atomic-Buildah

Buildah ist ein vonProject Atomic entwickeltes CLI-Tool zum schnellen Erstellen vonOpen Container Initiative (OCI)-kompatiblen Bildern. OCI bietet Spezifikationen für Containerlaufzeiten und -bilder, um Best Practices der Branche zu standardisieren.

Buildah kann ein Image entweder aus einem Arbeitscontainer oder aus einer Docker-Datei erstellen. Es kann Bilder vollständig im Benutzerbereich ohne den Docker-Dämon erstellen und Bildoperationen wiebuild,list,push undtag ausführen. In diesem Schritt kompilieren Sie Buildah aus dem Quellcode und erstellen daraus ein Container-Image.

Zur Installation von Buildah benötigen Sie die erforderlichen Abhängigkeiten, einschließlich Tools, mit denen Sie unter anderem Pakete und die Paketsicherheit verwalten können. Führen Sie die folgenden Befehle aus, um diese Pakete zu installieren:

 cd
 sudo apt-get install software-properties-common
 sudo add-apt-repository ppa:alexlarsson/flatpak
 sudo add-apt-repository ppa:gophers/archive
 sudo apt-add-repository ppa:projectatomic/ppa
 sudo apt-get update
 sudo apt-get install bats btrfs-tools git libapparmor-dev libdevmapper-dev libglib2.0-dev libgpgme11-dev libostree-dev libseccomp-dev libselinux1-dev skopeo-containers go-md2man

Da Sie den Quellcode vonbuildahkompilieren, um das Paket zu erstellen, müssen Sie auchGo installieren:

sudo apt-get update
sudo curl -O https://storage.googleapis.com/golang/go1.8.linux-amd64.tar.gz
sudo tar -xvf go1.8.linux-amd64.tar.gz
sudo mv go /usr/local
sudo echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile
source ~/.profile
go version

Sie werden die folgende Ausgabe sehen, die eine erfolgreiche Installation anzeigt:

Outputgo version go1.8 linux/amd64

Sie können jetzt den Quellcode vonbuildahabrufen, um das Paket zusammen mit der Binärdatei vonrunczu erstellen. runc ist die Implementierung der Container-LaufzeitOCI, mit der Sie Ihre Buildah-Container ausführen.

Führen Sie die folgenden Befehle aus, umrunc undbuildah zu installieren:

mkdir ~/buildah
cd ~/buildah
export GOPATH=`pwd`
git clone https://github.com/containers/buildah ./src/github.com/containers/buildah
cd ./src/github.com/containers/buildah
make runc all TAGS="apparmor seccomp"
sudo cp ~/buildah/src/github.com/opencontainers/runc/runc /usr/bin/.
sudo apt install buildah

Erstellen Sie als Nächstes die Datei/etc/containers/registries.conf, um Ihre Containerregistrierungen zu konfigurieren:

sudo nano /etc/containers/registries.conf

Fügen Sie der Datei den folgenden Inhalt hinzu, um Ihre Registries anzugeben:

/etc/containers/registries.conf

# This is a system-wide configuration file used to
# keep track of registries for various container backends.
# It adheres to TOML format and does not support recursive
# lists of registries.

# The default location for this configuration file is /etc/containers/registries.conf.

# The only valid categories are: 'registries.search', 'registries.insecure',
# and 'registries.block'.

[registries.search]
registries = ['docker.io', 'registry.fedoraproject.org', 'quay.io', 'registry.access.redhat.com', 'registry.centos.org']

# If you need to access insecure registries, add the registry's fully-qualified name.
# An insecure registry is one that does not have a valid SSL certificate or only does HTTP.
[registries.insecure]
registries = []

# If you need to block pull access from a registry, uncomment the section below
# and add the registries fully-qualified name.
#
# Docker only
[registries.block]
registries = []

Die Konfigurationsdatei vonregistries.confgibt an, welche Registrierungen konsultiert werden sollen, wenn Bildnamen vervollständigt werden, die keine Registrierung oder keinen Domain-Teil enthalten.

Führen Sie nun den folgenden Befehl aus, um ein Image zu erstellen, wobei Sie das Repository vonhttps://github.com/do-community/rsvpapp-webinar1als Erstellungskontext verwenden. Dieses Repository enthält auch die relevante Docker-Datei:

sudo buildah build-using-dockerfile -t rsvpapp:buildah github.com/do-community/rsvpapp-webinar1

Dieser Befehl erstellt ein Image mit dem Namenrsvpapp:buildah aus der Dockerfille, die im Repository vonhttps://github.com/do-community/rsvpapp-webinar1verfügbar ist.

Verwenden Sie den folgenden Befehl, um die Bilder aufzulisten:

sudo buildah images

Sie werden die folgende Ausgabe sehen:

OutputIMAGE ID             IMAGE NAME                                               CREATED AT             SIZE
b0c552b8cf64         docker.io/teamcloudyuga/python:alpine                    Sep 30, 2016 04:39     95.3 MB
22121fd251df         localhost/rsvpapp:buildah                                Sep 11, 2018 14:34     114 MB

Eines dieser Bilder istlocalhost/rsvpapp:buildah, das Sie gerade erstellt haben. Das andere,docker.io/teamcloudyuga/python:alpine, ist das Basis-Image aus der Docker-Datei.

Sobald Sie das Image erstellt haben, können Sie es in Docker Hub übertragen. Auf diese Weise können Sie es für eine spätere Verwendung aufbewahren. Sie müssen sich zuerst über die Befehlszeile bei Ihrem Docker Hub-Konto anmelden:

docker login -u your-dockerhub-username -p your-dockerhub-password

Sobald die Anmeldung erfolgreich war, erhalten Sie eine Datei~/.docker/config.json, die Ihre Docker Hub-Anmeldeinformationen enthält. Sie können diese Datei dann mitbuildah verwenden, um Bilder an Docker Hub zu senden.

Wenn Sie beispielsweise das gerade erstellte Bild verschieben möchten, können Sie den folgenden Befehl ausführen und dabei dieauthfile und das zu übertragende Bild angeben:

sudo buildah push --authfile ~/.docker/config.json rsvpapp:buildah docker://your-dockerhub-username/rsvpapp:buildah

Sie können das resultierende Image auch mit dem folgenden Befehl an den lokalen Docker-Daemon senden:

sudo buildah push rsvpapp:buildah docker-daemon:rsvpapp:buildah

Schauen Sie sich zum Schluss die von Ihnen erstellten Docker-Images an:

sudo docker image ls
OutputREPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
rsvpapp             buildah             22121fd251df        4 minutes ago       108MB
nkhare/nginx        latest              01f0982d91b8        17 minutes ago      172MB
ubuntu              16.04               b9e15a5d1e1a        5 days ago          115MB

Wie erwartet sollte jetzt ein neues Bildrsvpapp:buildah angezeigt werden, das mitbuildah exportiert wurde.

Sie haben jetzt Erfahrung mit dem Erstellen von Container-Images mit zwei verschiedenen Tools, Docker und Buildah. Lassen Sie uns nun erläutern, wie Sie mit Kubernetes einen Container-Cluster einrichten.

[[Schritt-2 - Einrichten eines Kubernetes-Clusters auf Digitalocean mit Kubeadm und Terraform]] == Schritt 2 - Einrichten eines Kubernetes-Clusters auf DigitalOcean mit Kubeadm und Terraform

Es gibt verschiedene Möglichkeiten, Kubernetes auf DigitalOcean einzurichten. Weitere Informationen zum Einrichten von Kubernetes mitkubeadm finden Sie beispielsweise unterHow To Create a Kubernetes Cluster Using Kubeadm on Ubuntu 18.04.

Da in dieser Lernserie ein Cloud Native-Ansatz für die Anwendungsentwicklung erläutert wird, wenden wir diese Methode beim Einrichten unseres Clusters an. Insbesondere werden wir die Clustererstellung mit kubeadm undTerraform automatisieren, einem Tool, das das Erstellen und Ändern der Infrastruktur vereinfacht.

Mit Ihrem persönlichen Zugriffstoken stellen Sie mit Terraform eine Verbindung zu DigitalOcean her, um 3 Server bereitzustellen. Sie führen diekubeadm-Befehle in diesen VMs aus, um einen Kubernetes-Cluster mit drei Knoten zu erstellen, der einen Masterknoten und zwei Worker enthält.

Erstellen Sie auf Ihrem Ubuntu-Server ein PaarSSH keys, mit denen Sie sich ohne Kennwort bei Ihren VMs anmelden können:

ssh-keygen -t rsa

Sie werden die folgende Ausgabe sehen:

OutputGenerating public/private rsa key pair.
Enter file in which to save the key (~/.ssh/id_rsa):

Drücken SieENTER, um das Schlüsselpaar im Verzeichnis~/.ssh in Ihrem Ausgangsverzeichnis zu speichern, oder geben Sie ein anderes Ziel ein.

Als Nächstes wird die folgende Eingabeaufforderung angezeigt:

OutputEnter passphrase (empty for no passphrase):

Drücken Sie in diesem FallENTER ohne Kennwort, um kennwortlose Anmeldungen an Ihren Knoten zu aktivieren.

Sie erhalten eine Bestätigung, dass Ihr Schlüsselpaar erstellt wurde:

OutputYour identification has been saved in ~/.ssh/id_rsa.
Your public key has been saved in ~/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:lCVaexVBIwHo++NlIxccMW5b6QAJa+ZEr9ogAElUFyY root@3b9a273f18b5
The key's randomart image is:
+---[RSA 2048]----+
|++.E ++o=o*o*o   |
|o   +..=.B = o   |
|.    .* = * o    |
| .   =.o + *     |
|  . . o.S + .    |
|   . +.    .     |
|    . ... =      |
|        o= .     |
|       ...       |
+----[SHA256]-----+

Holen Sie sich Ihren öffentlichen Schlüssel, indem Sie den folgenden Befehl ausführen, der ihn in Ihrem Terminal anzeigt:

cat ~/.ssh/id_rsa.pub

Fügen Sie diesen Schlüssel Ihrem DigitalOcean-Konto hinzu, indem Siethese directions folgen.

Als nächstes installieren Sie Terraform:

sudo apt-get update
sudo apt-get install unzip
wget https://releases.hashicorp.com/terraform/0.11.7/terraform_0.11.7_linux_amd64.zip
unzip terraform_0.11.7_linux_amd64.zip
sudo mv terraform /usr/bin/.
terraform version

Sie sehen die Ausgabe, die Ihre Terraform-Installation bestätigt:

OutputTerraform v0.11.7

Führen Sie als Nächstes die folgenden Befehle aus, umkubectl, ein CLI-Tool, das mit Ihrem Kubernetes-Cluster kommuniziert, zu installieren und ein~/.kube-Verzeichnis im Basisverzeichnis Ihres Benutzers zu erstellen:

sudo apt-get install apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo touch /etc/apt/sources.list.d/kubernetes.list
echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install kubectl
mkdir -p ~/.kube

Durch Erstellen des Verzeichnisses~/.kube können Sie die Konfigurationsdatei an diesen Speicherort kopieren. Sie werden dies tun, sobald Sie das Kubernetes-Setup-Skript später in diesem Abschnitt ausführen. Standardmäßig sucht die CLI vonkubectlnach der Konfigurationsdatei im Verzeichnis~/.kube, um auf den Cluster zuzugreifen.

Klonen Sie als Nächstes das Beispielprojekt-Repository für dieses Lernprogramm, das die Terraform-Skripts zum Einrichten der Infrastruktur enthält:

git clone https://github.com/do-community/k8s-cicd-webinars.git

Wechseln Sie in das Terraform-Skriptverzeichnis:

cd k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/

Holen Sie sich einen Fingerabdruck Ihres öffentlichen SSH-Schlüssels:

ssh-keygen -E md5 -lf ~/.ssh/id_rsa.pub | awk '{print $2}'

Sie sehen die Ausgabe wie folgt, wobei der hervorgehobene Teil Ihren Schlüssel darstellt:

OutputMD5:dd:d1:b7:0f:6d:30:c0:be:ed:ae:c7:b9:b8:4a:df:5e

Beachten Sie, dass sich Ihr Schlüssel von den hier gezeigten unterscheidet.

Speichern Sie den Fingerabdruck in einer Umgebungsvariablen, damit Terraform ihn verwenden kann:

export FINGERPRINT=dd:d1:b7:0f:6d:30:c0:be:ed:ae:c7:b9:b8:4a:df:5e

Exportieren Sie anschließend Ihr persönliches DO-Zugriffstoken:

export TOKEN=your-do-access-token

Schauen Sie sich nun das Projektverzeichnis von~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/an:

ls
Outputcluster.tf  destroy.sh  files outputs.tf  provider.tf  script.sh

Dieser Ordner enthält die erforderlichen Skripts und Konfigurationsdateien für die Bereitstellung Ihres Kubernetes-Clusters mit Terraform.

Führen Sie das Skriptscript.shaus, um das Kubernetes-Cluster-Setup auszulösen:

./script.sh

Wenn die Skriptausführung abgeschlossen ist, wirdkubectl so konfiguriert, dass der von Ihnen erstellte Kubernetes-Cluster verwendet wird.

Listen Sie die Clusterknoten mitkubectl get nodes auf:

kubectl get nodes
OutputNAME                STATUS    ROLES     AGE       VERSION
k8s-master-node     Ready     master    2m        v1.10.0
k8s-worker-node-1   Ready         1m        v1.10.0
k8s-worker-node-2   Ready         57s       v1.10.0

Sie haben jetzt einen Master- und zwei Worker-Knoten im StatusReady.

Wenn ein Kubernetes-Cluster eingerichtet ist, können Sie jetzt eine andere Option zum Erstellen von Container-Images untersuchen:Kaniko from Google.

[[Schritt 3 - Erstellen von Container-Bildern mit Kaniko]] == Schritt 3 - Erstellen von Container-Bildern mit Kaniko

Zu Beginn dieses Tutorials haben Sie Container-Images mit Dockerfiles und Buildah erstellt. Aber was wäre, wenn Sie Container-Images direkt auf Kubernetes erstellen könnten? Es gibt Möglichkeiten, den Befehldocker image buildin Kubernetes auszuführen, dies ist jedoch kein natives Kubernetes-Tool. Sie müssten sich auf den Docker-Dämon verlassen, um Images zu erstellen, und er müsste auf einem derPods im Cluster ausgeführt werden.

Mit einem Tool namens Kaniko können Sie Container-Images mit einer Docker-Datei auf einem vorhandenen Kubernetes-Cluster erstellen. In diesem Schritt erstellen Sie mit Kaniko ein Container-Image mit einer Docker-Datei. Sie werden dieses Image dann an Docker Hub senden.

Um Ihr Image an Docker Hub zu übertragen, müssen Sie Ihre Docker Hub-Anmeldeinformationen an Kaniko übergeben. Im vorherigen Schritt haben Sie sich bei Docker Hub angemeldet und eine~/.docker/config.json-Datei mit Ihren Anmeldeinformationen erstellt. Verwenden Sie diese Konfigurationsdatei, um ein KubernetesConfigMap-Objekt zum Speichern der Anmeldeinformationen im Kubernetes-Cluster zu erstellen. Das ConfigMap-Objekt wird zum Speichern von Konfigurationsparametern verwendet, um sie von Ihrer Anwendung zu entkoppeln.

Führen Sie den folgenden Befehl aus, um eine ConfigMap mit dem Namendocker-config unter Verwendung der Datei~/.docker/config.json zu erstellen:

sudo kubectl create configmap docker-config --from-file=$HOME/.docker/config.json

Als Nächstes können Sie eine Pod-Definitionsdatei mit dem Namenpod-kaniko.yml im Verzeichnis~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/ erstellen (obwohl sie überall hingehen kann).

Stellen Sie zunächst sicher, dass Sie sich im Verzeichnis~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/befinden:

cd ~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/

Erstellen Sie die Dateipod-kaniko.yml:

nano pod-kaniko.yml

Fügen Sie der Datei den folgenden Inhalt hinzu, um anzugeben, was beim Bereitstellen des Pod geschehen soll. Stellen Sie sicher, dass Sieyour-dockerhub-username im Feldargsdes Pods durch Ihren eigenen Docker Hub-Benutzernamen ersetzen:

~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/pod-kaniko.yaml

apiVersion: v1
kind: Pod
metadata:
  name: kaniko
spec:
  containers:
  - name: kaniko
    image: gcr.io/kaniko-project/executor:latest
    args: ["--dockerfile=./Dockerfile",
            "--context=/tmp/rsvpapp/",
            "--destination=docker.io/your-dockerhub-username/rsvpapp:kaniko",
            "--force" ]
    volumeMounts:
      - name: docker-config
        mountPath: /root/.docker/
      - name: demo
        mountPath: /tmp/rsvpapp
  restartPolicy: Never
  initContainers:
    - image: python
      name: demo
      command: ["/bin/sh"]
      args: ["-c", "git clone https://github.com/do-community/rsvpapp-webinar1.git /tmp/rsvpapp"]
      volumeMounts:
      - name: demo
        mountPath: /tmp/rsvpapp
  restartPolicy: Never
  volumes:
    - name: docker-config
      configMap:
        name: docker-config
    - name: demo
      emptyDir: {}

Diese Konfigurationsdatei beschreibt, was passiert, wenn Ihr Pod bereitgestellt wird. Zuerst klonen dieInit container das Git-Repository mit der Docker-Dateihttps://github.com/do-community/rsvpapp-webinar1.git in ein gemeinsam genutztes Volume namensdemo. Init-Container werden vor Anwendungscontainern ausgeführt und können zum Ausführen von Dienstprogrammen oder anderen Aufgaben verwendet werden, die nicht von Ihren Anwendungscontainern ausgeführt werden sollen. Ihr Anwendungscontainerkaniko erstellt dann das Image mithilfe der Docker-Datei und überträgt das resultierende Image mithilfe der Anmeldeinformationen, die Sie an das ConfigMap-Volumedocker-config übergeben haben, an Docker Hub.

Führen Sie den folgenden Befehl aus, um den Podkaniko bereitzustellen:

kubectl apply -f pod-kaniko.yml

Sie sehen folgende Bestätigung:

Outputpod/kaniko created

Holen Sie sich die Liste der Hülsen:

kubectl get pods

Sie sehen die folgende Liste:

OutputNAME      READY     STATUS     RESTARTS   AGE
kaniko    0/1       Init:0/1   0          47s

Warten Sie einige Sekunden und führen Sie dannkubectl get pods erneut aus, um eine Statusaktualisierung durchzuführen:

kubectl get pods

Sie werden folgendes sehen:

OutputNAME      READY     STATUS    RESTARTS   AGE
kaniko    1/1       Running   0          1m

Führen Sie abschließendkubectl get pods erneut aus, um eine endgültige Statusaktualisierung durchzuführen:

kubectl get pods
OutputNAME      READY     STATUS      RESTARTS   AGE
kaniko    0/1       Completed   0          2m

Diese Ausgabesequenz zeigt an, dass der Init-Container ausgeführt wurde und das GitHub-Repository innerhalb des Volumes vondemogeklont hat. Danach wurde der Kaniko-Build-Prozess ausgeführt und schließlich beendet.

Überprüfen Sie die Protokolle des Pods:

kubectl logs kaniko

Sie werden die folgende Ausgabe sehen:

Outputtime="2018-08-02T05:01:24Z" level=info msg="appending to multi args docker.io/your-dockerhub-username/rsvpapp:kaniko"
time="2018-08-02T05:01:24Z" level=info msg="Downloading base image nkhare/python:alpine"
.
.
.
ime="2018-08-02T05:01:46Z" level=info msg="Taking snapshot of full filesystem..."
time="2018-08-02T05:01:48Z" level=info msg="cmd: CMD"
time="2018-08-02T05:01:48Z" level=info msg="Replacing CMD in config with [/bin/sh -c python rsvp.py]"
time="2018-08-02T05:01:48Z" level=info msg="Taking snapshot of full filesystem..."
time="2018-08-02T05:01:49Z" level=info msg="No files were changed, appending empty layer to config."
2018/08/02 05:01:51 mounted blob: sha256:bc4d09b6c77b25d6d3891095ef3b0f87fbe90621bff2a333f9b7f242299e0cfd
2018/08/02 05:01:51 mounted blob: sha256:809f49334738c14d17682456fd3629207124c4fad3c28f04618cc154d22e845b
2018/08/02 05:01:51 mounted blob: sha256:c0cb142e43453ebb1f82b905aa472e6e66017efd43872135bc5372e4fac04031
2018/08/02 05:01:51 mounted blob: sha256:606abda6711f8f4b91bbb139f8f0da67866c33378a6dcac958b2ddc54f0befd2
2018/08/02 05:01:52 pushed blob sha256:16d1686835faa5f81d67c0e87eb76eab316e1e9cd85167b292b9fa9434ad56bf
2018/08/02 05:01:53 pushed blob sha256:358d117a9400cee075514a286575d7d6ed86d118621e8b446cbb39cc5a07303b
2018/08/02 05:01:55 pushed blob sha256:5d171e492a9b691a49820bebfc25b29e53f5972ff7f14637975de9b385145e04
2018/08/02 05:01:56 index.docker.io/your-dockerhub-username/rsvpapp:kaniko: digest: sha256:831b214cdb7f8231e55afbba40914402b6c915ef4a0a2b6cbfe9efb223522988 size: 1243

Aus den Protokollen können Sie ersehen, dass der Containerkanikodas Image aus der Docker-Datei erstellt und in Ihr Docker Hub-Konto übertragen hat.

Sie können jetzt das Docker-Image ziehen. Stellen Sie sicher, dass Sieyour-dockerhub-username erneut durch Ihren Docker Hub-Benutzernamen ersetzen:

docker pull your-dockerhub-username/rsvpapp:kaniko

Sie sehen eine Bestätigung des Pulls:

Outputkaniko: Pulling from your-dockerhub-username/rsvpapp
c0cb142e4345: Pull complete
bc4d09b6c77b: Pull complete
606abda6711f: Pull complete
809f49334738: Pull complete
358d117a9400: Pull complete
5d171e492a9b: Pull complete
Digest: sha256:831b214cdb7f8231e55afbba40914402b6c915ef4a0a2b6cbfe9efb223522988
Status: Downloaded newer image for your-dockerhub-username/rsvpapp:kaniko

Sie haben jetzt erfolgreich einen Kubernetes-Cluster erstellt und neue Images innerhalb des Clusters erstellt. Fahren wir mit der Erörterung vonDeployments undServices fort.

[[Schritt 4 - Erstellen von Kubernetes-Bereitstellungen und -Diensten]] == Schritt 4 - Erstellen von Kubernetes-Bereitstellungen und -Diensten

Mit KubernetesDeployments können Sie Ihre Anwendungen ausführen. Bereitstellungen geben den gewünschten Status für Ihre Pods an und gewährleisten so die Konsistenz über Ihre Rollouts hinweg. In diesem Schritt erstellen Sie eineNginx-Bereitstellungsdatei mit dem Namendeployment.yml im Verzeichnis~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/, um eine Nginx-Bereitstellung zu erstellen.

Öffnen Sie zuerst die Datei:

nano deployment.yml

Fügen Sie der Datei die folgende Konfiguration hinzu, um Ihre Nginx-Bereitstellung zu definieren:

~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terraform/deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

Diese Datei definiert eine Bereitstellung mit dem Namennginx-deployment, die drei Pods erstellt, in denen jeweils einnginx-Container auf Port80 ausgeführt wird.

Führen Sie zum Bereitstellen der Bereitstellung den folgenden Befehl aus:

kubectl apply -f deployment.yml

Sie sehen eine Bestätigung, dass die Bereitstellung erstellt wurde:

Outputdeployment.apps/nginx-deployment created

Listen Sie Ihre Bereitstellungen auf:

kubectl get deployments
OutputNAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           29s

Sie können sehen, dass die Bereitstellung vonnginx-deployment erstellt wurde und die gewünschte und aktuelle Anzahl der Pods gleich ist:3.

Führen Sie den folgenden Befehl aus, um die von der Bereitstellung erstellten Pods aufzulisten:

kubectl get pods
OutputNAME                                READY     STATUS      RESTARTS   AGE
kaniko                              0/1       Completed   0          9m
nginx-deployment-75675f5897-nhwsp   1/1       Running     0          1m
nginx-deployment-75675f5897-pxpl9   1/1       Running     0          1m
nginx-deployment-75675f5897-xvf4f   1/1       Running     0          1m

An dieser Ausgabe können Sie erkennen, dass die gewünschte Anzahl von Pods ausgeführt wird.

Um eine Anwendungsbereitstellung intern und extern verfügbar zu machen, müssen Sie ein Kubernetes-Objekt mit dem NamenService erstellen. Jeder Dienst gibt einServiceType an, das definiert, wie der Dienst verfügbar gemacht wird. In diesem Beispiel verwenden wir einen ServiceType vonNodePort, der den Service an einem statischen Port auf jedem Knoten verfügbar macht.

Erstellen Sie dazu eine Dateiservice.yml im Verzeichnis~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terrafrom/:

nano service.yml

Fügen Sie den folgenden Inhalt hinzu, um Ihren Service zu definieren:

~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terrafrom/service.yml

kind: Service
apiVersion: v1
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30111

Diese Einstellungen definieren den Dienstnginx-service und geben an, dass er auf Port80 auf Ihrem Pod abzielt. nodePort definiert den Port, an dem die Anwendung externen Datenverkehr akzeptiert.

Führen Sie den folgenden Befehl aus, um den Dienst bereitzustellen:

kubectl apply -f service.yml

Sie sehen eine Bestätigung:

Outputservice/nginx-service created

Listen Sie die Services auf:

kubectl get service

Sie sehen die folgende Liste:

OutputNAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.96.0.1               443/TCP        5h
nginx-service   NodePort    10.100.98.213           80:30111/TCP   7s

Ihr Dienstnginx-service ist auf Port30111 verfügbar und Sie können jetzt über eine der öffentlichen IP-Adressen des Knotens darauf zugreifen. Wenn Sie beispielsweise zuhttp://node_1_ip:30111 oderhttp://node_2_ip:30111 navigieren, gelangen Sie zur Standard-Begrüßungsseite von Nginx.

Nachdem Sie die Bereitstellung getestet haben, können Sie sowohl die Bereitstellung als auch den Dienst bereinigen:

kubectl delete deployment nginx-deployment
kubectl delete service nginx-service

Diese Befehle löschen die von Ihnen erstellte Bereitstellung und den Dienst.

Nachdem Sie mit Bereitstellungen und Diensten gearbeitet haben, können Sie nun benutzerdefinierte Ressourcen erstellen.

[[Schritt 5 - Erstellen von benutzerdefinierten Ressourcen in Kubernetes]] == Schritt 5 - Erstellen von benutzerdefinierten Ressourcen in Kubernetes

Kubernetes bietet begrenzte, aber produktionsreife Funktionen und Merkmale. Es ist jedoch möglich, das Angebot von Kubernetes mithilfe derCustom Resources-Funktion zu erweitern. In Kubernetes ist einresource ein Endpunkt in der Kubernetes-API, der eine Sammlung von APIobjects speichert. Eine Pod-Ressource enthält beispielsweise eine Sammlung von Pod-Objekten. Mit benutzerdefinierten Ressourcen können Sie benutzerdefinierte Angebote für Netzwerke, Speicher und mehr hinzufügen. Diese Ergänzungen können jederzeit erstellt oder entfernt werden.

Sie können nicht nur benutzerdefinierte Objekte erstellen, sondern auch Subcontroller der Komponente KubernetesControllerin der Steuerebene verwenden, um sicherzustellen, dass der aktuelle Status Ihrer Objekte dem gewünschten Status entspricht. Der Kubernetes Controller verfügt über Sub-Controller für bestimmte Objekte. Beispielsweise istReplicaSet ein Subcontroller, der sicherstellt, dass die gewünschte Pod-Anzahl konsistent bleibt. Wenn Sie eine benutzerdefinierte Ressource mit einem Controller kombinieren, erhalten Sie ein echtesdeclarative API, mit dem Sie den gewünschten Status Ihrer Ressourcen angeben können.

In diesem Schritt erstellen Sie eine benutzerdefinierte Ressource und zugehörige Objekte.

Um eine benutzerdefinierte Ressource zu erstellen, erstellen Sie zunächst eine Datei mit dem Namencrd.yml im Verzeichnis~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terrafrom/:

nano crd.yml

Fügen Sie die folgende benutzerdefinierte Ressourcendefinition (Custom Resource Definition, CRD) hinzu:

~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terrafrom/crd.yml

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: webinars.digitalocean.com
spec:
  group: digitalocean.com
  version: v1
  scope: Namespaced
  names:
    plural: webinars
    singular: webinar
    kind: Webinar
    shortNames:
    - wb

Führen Sie den folgenden Befehl aus, um die incrd.yml definierte CRD bereitzustellen:

kubectl create -f crd.yml

Sie sehen eine Bestätigung, dass die Ressource erstellt wurde:

Outputcustomresourcedefinition.apiextensions.k8s.io/webinars.digitalocean.com created

Die Dateicrd.yml hat einen neuen RESTful-Ressourcenpfad erstellt:/apis/digtialocean.com/v1/namespaces/*/webinars. Sie können jetzt mitwebinars,webinar,Webinar undwb auf Ihre Objekte verweisen, wie Sie sie im Abschnittnames vonCustomResourceDefinitionaufgelistet haben ) s. Sie können die RESTful-Ressource mit dem folgenden Befehl überprüfen:

kubectl proxy & curl 127.0.0.1:8001/apis/digitalocean.com

[.Hinweis]##

Note: Wenn Sie die Anleitung zur Einrichtung des ersten Servers in den Voraussetzungen befolgt haben, müssen Sie den Datenverkehr zu Port8001 zulassen, damit dieser Test funktioniert. Aktivieren Sie den Datenverkehr zu diesem Port mit dem folgenden Befehl:

sudo ufw allow 8001

Sie werden die folgende Ausgabe sehen:

OutputHTTP/1.1 200 OK
Content-Length: 238
Content-Type: application/json
Date: Fri, 03 Aug 2018 06:10:12 GMT

{
    "apiVersion": "v1",
    "kind": "APIGroup",
    "name": "digitalocean.com",
    "preferredVersion": {
        "groupVersion": "digitalocean.com/v1",
        "version": "v1"
    },
    "serverAddressByClientCIDRs": null,
    "versions": [
        {
            "groupVersion": "digitalocean.com/v1",
            "version": "v1"
        }
    ]
}

Erstellen Sie als Nächstes das Objekt für die Verwendung neuer benutzerdefinierter Ressourcen, indem Sie eine Datei mit dem Namenwebinar.yml öffnen:

nano webinar.yml

Fügen Sie den folgenden Inhalt hinzu, um das Objekt zu erstellen:

~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terrafrom/webinar.yml

apiVersion: "digitalocean.com/v1"
kind: Webinar
metadata:
  name: webinar1
spec:
  name: webinar
  image: nginx

Führen Sie den folgenden Befehl aus, um diese Änderungen in den Cluster zu übertragen:

kubectl apply -f webinar.yml

Sie werden die folgende Ausgabe sehen:

Outputwebinar.digitalocean.com/webinar1 created

Sie können jetzt Ihrewebinar-Objekte mitkubectl verwalten. Zum Beispiel:

kubectl get webinar
OutputNAME       CREATED AT
webinar1   21s

Sie haben jetzt ein Objekt namenswebinar1. Wenn es einen Controller gegeben hätte, hätte er die Objekterstellung abgefangen und alle definierten Operationen ausgeführt.

Löschen einer benutzerdefinierten Ressourcendefinition

Verwenden Sie den folgenden Befehl, um alle Objekte für Ihre benutzerdefinierte Ressource zu löschen:

kubectl delete webinar --all

Du wirst sehen:

Outputwebinar.digitalocean.com "webinar1" deleted

Entfernen Sie die benutzerdefinierte Ressource selbst:

kubectl delete crd webinars.digitalocean.com

Sie sehen eine Bestätigung, dass es gelöscht wurde:

Outputcustomresourcedefinition.apiextensions.k8s.io "webinars.digitalocean.com" deleted

Nach dem Löschen haben Sie keinen Zugriff auf den API-Endpunkt, den Sie zuvor mit dem Befehlcurl getestet haben.

Diese Sequenz ist eine Einführung, wie Sie die Kubernetes-Funktionen erweitern können, ohne Ihren Kubernetes-Code zu ändern.

[[Schritt-6 - Löschen des Kubernetes-Clusters]] == Schritt 6 - Löschen des Kubernetes-Clusters

Um den Kubernetes-Cluster selbst zu zerstören, können Sie das Skriptdestroy.shaus dem Ordner~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terrafromverwenden. Stellen Sie sicher, dass Sie sich in diesem Verzeichnis befinden:

cd ~/k8s-cicd-webinars/webinar1/2-kubernetes/1-Terrafrom

Führen Sie das Skript aus:

./destroy.sh

Wenn Sie dieses Skript ausführen, können Sie Terraform die Kommunikation mit der DigitalOcean-API ermöglichen und die Server in Ihrem Cluster löschen.

Fazit

In diesem Lernprogramm haben Sie verschiedene Tools zum Erstellen von Containerbildern verwendet. Mit diesen Bildern können Sie Container in jeder Umgebung erstellen. Sie haben auch einen Kubernetes-Cluster mit Terraform eingerichtet und Deployment- und Service-Objekte erstellt, um Ihre Anwendung bereitzustellen und verfügbar zu machen. Darüber hinaus haben Sie die Funktionalität von Kubernetes erweitert, indem Sie eine benutzerdefinierte Ressource definiert haben.

Sie haben jetzt eine solide Grundlage für den Aufbau einer CI / CD-Umgebung auf Kubernetes, die wir in zukünftigen Artikeln untersuchen werden.