Erfreu Dich an Millionen von E-Books, Hörbüchern, Magazinen und mehr

Nur $11.99/Monat nach der Testversion. Jederzeit kündbar.

K8s Applications mit MicroK8S auf Raspberry PI

K8s Applications mit MicroK8S auf Raspberry PI

Vorschau lesen

K8s Applications mit MicroK8S auf Raspberry PI

Länge:
876 Seiten
4 Stunden
Herausgeber:
Freigegeben:
16. Jan. 2022
ISBN:
9783742770134
Format:
Buch

Beschreibung

Beispiele für das Entwickeln und Betreiben von Anwendungen auf einem MicroK8s Kubernetes Cluster auf Raspberry PI Basis. Es werden die folgenden Elemente beschrieben

Infrastrukturservices
◦ Repository
◦ NTP
◦ LDAP
◦ Secretmanagement
Monitoringservices
◦ Prometheus
◦ Grafana
◦ Alert-Agent
Storage und Backup
◦ Longhorn
◦ Externe Storage
Webservice – Stateful
◦ Joomla
◦ PostgresDB
Gitlab
◦ Build-Pipelines
◦ GitRunner
Buildautomatisierung
◦ Eigene einfache Buildpipeline
◦ kpt
◦ kustomize
Servicemesh Linkerd

Alle Services werden als yaml-File beschrieben.
Herausgeber:
Freigegeben:
16. Jan. 2022
ISBN:
9783742770134
Format:
Buch

Über den Autor


Ähnlich wie K8s Applications mit MicroK8S auf Raspberry PI

Ähnliche Bücher

Ähnliche Artikel

Buchvorschau

K8s Applications mit MicroK8S auf Raspberry PI - Alfred Sabitzer

K8s Applications

mit MicroK8S

auf Raspberry PI

Beispiele für das Entwickeln und Betreiben von Anwendungen auf einem MicroK8s Kubernetes Cluster auf Raspberry PI Basis.

Alfred Sabitzer

https://www.linkedin.com/in/alfred-sabitzer-805312183/

https://www.xing.com/profile/Alfred_Sabitzer/cv

Vorwort

Die Idee eine „Cloud zu bauen entstand während der Corona-Zeit. Anstatt „Fernsehen könnte man doch was Sinnvolles ausprobieren. Außerdem ist der vorhandene Raspberry 4 bereits überlastet, und kann schwerlich neue Dienste anbieten. Da wäre doch ein System, das skalierbar ist, beliebig viele Services anbieten kann usw. doch genau das Richtige. Außerdem sind Microservices leichter auf neue Hardware portierbar! Ich erinnere mich noch genau, wie aufwändig der Umstieg vom Raspberry 2 auf den Raspberry 3 und dann auf den Raspberry 4 war. Ich musste jedes mal aufs Neue nachdenken, wie den die Installation genau geht, habe viel Zeit investiert und  erreichte am Ende bestenfalls, dass ich nachher dieselben Dienste nutzen konnte wie vorher:)

Darum: eine Cloud muss her.

Generell: Der Bau einer Cloud ist ein komplexes Unternehmen (am einfachsten ist es, wenn man sich in einer bereits existenten Cloud einmietet – da gibt es genug Anbieter am Markt).

Dieses Buch beschreibt die einzelnen Schritte, die ich durchgeführt habe um mir meine eigene Cloud zu bauen. Hier werden aufbauend auf dem Hardwareaufbau im Buch Bau einer K8s bare-metal-cloud mit RaspberryPI ISBN 978-3-7534-9851-4 unterschiedliche Konzepte und Ideen beschrieben. Der Bau von Microservices, das Einrichten einer CI/CD-Strecke, kpt, kustomize, Servicemesh usw, wird anhand von Beispielen soweit möglich erklärt.

Hier finden sich viele Codefragmente, die eine Idee geben können, wie jemand das bei sich zu Hause selbst tun könnte. Diese Codeteile erheben keinen Anspruch auf Funktionalität oder dergleichen. Die Verwendung erfolgt auf eigenes Risiko.

Generell würde mich der Austausch mit anderen „Cloud"-Bauern interessieren. Ideen, Verbesserungen, Anregungen udglm. sind herzlich willkommen. Der Auto ist erreichbar unter microk8s.raspberry@slainte.at erreichbar.

Die in diesem Buch angeführten Programmteile gibt es online auf https://gitlab.com/Alfred-Sabitzer/k8sapp sowie auf https://gitlab.com/Alfred-Sabitzer/ldap .

Einleitung

Nach dem Aufsetzen des microK8s-Cluster auf RaspberryPI und prinzipiellem Einrichten der Infrastruktur (siehe „Bau einer K8s bare-metal-cloud mit RaspberryPI"), dient diese Beschreibung um die Schritte, Versuche und Fehlversuche zu dokumentieren, die ich beim Entwicklen, Einrichten und Betreiben von Anwendungen im k8s-Cluster unternommen habe. Es werden die folgenden Teile beschrieben

Infrastrukturservices

Repository

NTP

LDAP

Secretmanagement

Monitoringservices

Prometheus

Grafana

Alert-Agent

Storage und Backup

Longhorn

Externe Storage

Webservice – Stateful

Joomla

PostgresDB

Gitlab

Build-Pipelines

GitRunner

Buildautomatisierung

Eigene einfache Buildpipeline

kpt

kustomize

Servicemesh Linkerd

Alle Services werden als yaml-File beschrieben. Die Sourcen befinden sich auf https://gitlab.com/Alfred-Sabitzer/ldap sowie auf https://gitlab.com/Alfred-Sabitzer/k8sapp

Leider ist nicht alles am Raspberry mit arm-Architekture verfügbar. Somit kann ein K8S-Cluster auf Raspberry Basis nicht wirklich mit einem Cluster auf Intel-Basis (oder noch besser in einer wirklichen Cloud wie Google oder Amazon) verglichen werden. Es ist dennoch eine gute und kostengünstige Basis um die Prinzipien kennen zu lernen, und Hands-On einen Cluster vom Scratch aufzubauen.

Der hier beschriebene Cluster baut auf dem Buch

OEBPS/images/image0001.png

Bau einer K8s bare-metal-cloud mit RaspberryPI ISBN 978-3-7534-9851-4 auf.

Gutes Gelingen!

Architektur des Clusters

Inspiration:

https://de.wikipedia.org/wiki/Raspberry_Pi

https://www.picocluster.com/

Das System besteht aus einem RaspberryPI-Cluster mit microk8s. Die Raspberry-Version ist 4 mit 8GB RAM und einer 64GB SDRAM. Der Cluster besteht aus 5 Nodes. Jeder Node hat zusätzlich noch eine externe 110GB USB-SSD-Platte die als Clusterstorage konfiguriert ist.

OEBPS/images/image0002.jpg

Abbildung 1: k8s-Cluster

PC ist die Abkürzung für pico-cluster. Es gibt pc1 bis pc5.

Die SSD-Disken werden mit Longhorn verwaltet. Es steht folgender Speicherplatz für PVC'S (permanent volume claims) zur Verfügung:

OEBPS/images/image0003.jpg

Abbildung 2: Longhorn Clusterstorage

Physikalisch sieht das aus wie folgt:

OEBPS/images/image0004.jpg

Abbildung 3: pico-Cluster von vorne

Man sieht hier den Cluster von vorne mit der Stromversorgung und dem Nway-Switch.

OEBPS/images/image0005.jpg

Abbildung 4: pico-Cluster von der Seite

Hier erkennt man den Cluster mit dem eingebauten Lüfter.

OEBPS/images/image0006.jpg

Abbildung 5: pico-Cluster von hinten

Hier kann man gut die Cluster-Storage erkennen. Aus thermischen Gründen befinden sich die SSD-Platten ausserhalb des Pico-Clusters.

Der Aufbau wird in „Bau einer K8s bare-metal-cloud mit RaspberryPI" beschrieben.

Ein Übersicht gibt folgendes Bild:

OEBPS/images/image0007.jpg

Abbildung 6: MicroK8S Cluster - Gesamtsystem

Namespaces

Inspiration:

https://microk8s.io/docs/registry-built-in

Um den Cluster richtig betreiben zu können, sind auch Namespaces wichtig. Es sind (neben den technischen Namespaces, die mit k8s automatisch angelegt werden) noch die folgenden Namespaces vorhanden.

---

apiVersion: v1

kind: Namespace

metadata:

labels:

kubernetes.io/metadata.name: slainte

name: slainte

spec:

finalizers:

- kubernetes

---

apiVersion: v1

kind: Namespace

metadata:

labels:

kubernetes.io/metadata.name: default

name: default

spec:

finalizers:

- kubernetes

---

apiVersion: v1

kind: Namespace

metadata:

labels:

kubernetes.io/metadata.name: admin

name: admin

spec:

finalizers:

- kubernetes

---

Slainte ist quasi die Produktion (von aussen erreichbar). Default ist ein Test-URL der auch von aussen erreichbar ist. Die Services in admin haben keinen Ingress (sind von aussen nicht erreichbar), werden aber idR. als LoadBalancer-Services bereitgestellt.

IP-Adressen

Inspiration:

https://cloud.google.com/kubernetes-engine/docs/concepts/network-overview

Die im Cluster verfügbaren Bereiche sind:

OEBPS/images/image0008.jpg

Im Konkreten:

k8s.slainte.at                                                87.243.186.29

default.k8s.slainte.at                                87.243.186.29

Aus dem Cluster selbst:

alfred@pc1:~/yaml$ k get svc --all-namespaces | grep -v ''

NAMESPACE  NAME  TYPE  CLUSTER-IP  EXTERNAL-IP  PORT(S)  AGE

ingress  ingress   LoadBalancer  10.152.183.126  192.168.0.210  443:31287/TCP,80:31681/TCP  22h

kube-system  kubernetes-dashboard  LoadBalancer  10.152.183.150  192.168.0.211  443:31449/TCP  22h

longhorn-system  longhorn-frontend  LoadBalancer  10.152.183.199  192.168.0.212  80:31444/TCP  22h

container-registry  registry   LoadBalancer  10.152.183.207  192.168.0.213  5000:32000/TCP  22h

admin  chrony-udp-svc  LoadBalancer  10.152.183.77  192.168.0.240  123:32658/UDP  40m

admin  pgadmin-svc  LoadBalancer  10.152.183.201  192.168.0.241  5432:30954/TCP,80:30675/TCP,443:30676/TCP  19m

Source Repository

Inspiration:

https://microk8s.io/docs/registry-built-in

Eine Software-Registry wird benötigt, wenn man selbst entwickelte Anwendungen lokal speicher und verwenden möchte. Prinzipiell könnte man auch öffentliche Registrys nehmen, aber wir haben ja einen k8s-cluster.

alfred@pc1:~$ microk8s enable registry:size=40Gi

Addon storage is already enabled.

Enabling the private registry

Applying registry manifest

namespace/container-registry created

persistentvolumeclaim/registry-claim created

deployment.apps/registry created

service/registry created

configmap/local-registry-hosting configured

The registry is enabled

The size of the persistent volume is 40Gi

alfred@pc1:~$

Nun ist die Registry vorhanden. Das Cluster-Setup ist wie folgt:

alfred@pc1:~$ microk8s status

microk8s is running

high-availability: yes

datastore master nodes: 192.168.0.202:19001 192.168.0.203:19001 192.168.0.204:19001

datastore standby nodes: 192.168.0.201:19001 192.168.0.205:19001

addons:

enabled:

dashboard  # The Kubernetes dashboard

dns  # CoreDNS

ha-clusalfred@pc1:~$ microk8s status

microk8s is running

high-availability: yes

datastore master nodes: 192.168.0.202:19001 192.168.0.203:19001 192.168.0.204:19001

datastore standby nodes: 192.168.0.201:19001 192.168.0.205:19001

addons:

enabled:

dashboard  # The Kubernetes dashboard

dns  # CoreDNS

ha-cluster  # Configure high availability on the current node

helm3  # Helm 3 - Kubernetes package manager

ingress  # Ingress controller for external access

metallb  # Loadbalancer for your Kubernetes cluster

metrics-server  # K8s Metrics Server for API access to service metrics

prometheus  # Prometheus operator for monitoring and logging

rbac  # Role-Based Access Control for authorisation

registry  # Private image registry exposed on localhost:5000

storage  # Storage class; allocates storage from host directory

disabled:

helm  # Helm 2 - the package manager for Kubernetes

host-access  # Allow Pods connecting to Host services smoothly

linkerd  # Linkerd is a service mesh for Kubernetes and other frameworks

portainer  # Portainer UI for your Kubernetes cluster

traefik  # traefik Ingress controller for external access

alfred@pc1:~$

OEBPS/images/image0009.jpg

Abbildung 7: Registry Clusterdisk

Das Volume wurde als ClusterDisk angelegt. Die Storageclass longhorn ist als default eingerichtet.

Das Skript zum Einrichten der Registry ist wie folgt:

#!/bin/bash

############################################################################################

#  $Date: 2021-11-23 21:37:19 +0100 (Di, 23. Nov 2021) $

#  $Revision: 1285 $

#  $Author: alfred $

#  $HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/k8s/K13_registry.sh $

#  $Id: K13_registry.sh 1285 2021-11-23 20:37:19Z alfred $

#

# Schnell-Installation microk8s - Installation praktischer AddOns

#

############################################################################################

#shopt -o -s errexit  #—Terminates  the shell script  if a command returns an error code.

shopt -o -s xtrace #—Displays each command before it’s executed.

shopt -o -s nounset #-No Variables without definition

# Voraussetzung: Sauber installierte Nodes, Verbundener Cluster

sname=$(basename $0)

app=mikrok8s/install/${sname}

pf=\$Revision:

sf= \$

fr=\$Revision: 1285 $

revision=${fr#*$pf}

revision=${revision%$sf*}

xd=(`date '+%Y-%m-%d'`)

wd=${HOME}/copy/${app}/${xd}/r${revision}

id=/opt/cluster/${app}/${xd}/r${revision}

rm -f -R ${wd}

mkdir -p ${wd}

#

# Zu diesem Zeitpunkt sollte es eine Default-Storage-Class geben, wo das abgelegt wird.

ansible pc1 -m shell -a 'microk8s enable registry:size=40Gi'

ansible pc -m shell -a 'microk8s status --wait-ready'

#

# Adaptieren der Services

#

cat < ${wd}/do_registry.sh

#!/bin/bash

#

#  \$Date: 2021-11-23 21:37:19 +0100 (Di, 23. Nov 2021) $

#  \$Revision: 1285 $

#  \$Author: alfred $

#  \$HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/k8s/K13_registry.sh $

#  \$Id: K13_registry.sh 1285 2021-11-23 20:37:19Z alfred $

#

# Ändern des Services auf Loadbalancer

#

#shopt -o -s errexit  #—Terminates  the shell script  if a command returns an error code.

shopt -o -s xtrace #—Displays each command before it’s executed.

shopt -o -s nounset #-No Variables without definition

# registry - 192.168.0.213

microk8s kubectl -n container-registry get service registry -o yaml > ${id}/registry-svc.yaml

sed 's/NodePort/LoadBalancer/' ${id}/registry-svc.yaml > ${id}/new-registry-svc.yaml

microk8s kubectl apply -f ${id}/new-registry-svc.yaml --validate=false

EOF

#

chmod 755 ${wd}/do_registry.sh

ansible pc1 -m shell -a ${id}'/do_registry.sh ' > ${wd}'/do_registry.log'

#

cat < ${wd}/do_nodes.sh

#!/bin/bash

#

#  \$Date: 2021-11-23 21:37:19 +0100 (Di, 23. Nov 2021) $

#  \$Revision: 1285 $

#  \$Author: alfred $

#  \$HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/k8s/K13_registry.sh $

#  \$Id: K13_registry.sh 1285 2021-11-23 20:37:19Z alfred $

#

# Eintragen der Nodes in die hosts-Datei

#

#shopt -o -s errexit  #—Terminates  the shell script  if a command returns an error code.

shopt -o -s xtrace #—Displays each command before it’s executed.

shopt -o -s nounset #-No Variables without definition

sudo sed --in-place '/docker.registry/d' /etc/hosts

microk8s kubectl -n container-registry get service registry -o yaml > ${id}/nodes-registry-svc.yaml

ip=\$(cat ${id}/nodes-registry-svc.yaml  | grep -i ip: | awk '{print \$3 }')

text=\${ip}  docker.registry

sudo sed -i $ a \${text} /etc/hosts

#

EOF

#

chmod 755 ${wd}/do_nodes.sh

ansible pc -m shell -a ${id}'/do_nodes.sh '

#

# Und jetzt die Repository-Info

#

cat < ${wd}/do_docker.sh

#!/bin/bash

#

#  \$Date: 2021-11-23 21:37:19 +0100 (Di, 23. Nov 2021) $

#  \$Revision: 1285 $

#  \$Author: alfred $

#  \$HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/k8s/K13_registry.sh $

#  \$Id: K13_registry.sh 1285 2021-11-23 20:37:19Z alfred $

#

# Eintragen des Endpoints in die Docker-Registry

#

#shopt -o -s errexit  #—Terminates  the shell script  if a command returns an error code.

#shopt -o -s xtrace #—Displays each command before it’s executed.

shopt -o -s nounset #-No Variables without definition

FILENAME=/var/snap/microk8s/current/args/containerd-template.toml

sudo sed --in-place '/docker.registry:5000/d' \${FILENAME}

text='  [plugins.io.containerd.grpc.v1.cri.registry.mirrors.docker.registry:5000]'

echo  \${text} | tee -a \${FILENAME}

text='  endpoint = [http://docker.registry:5000]'

echo  \${text} | tee -a \${FILENAME}

EOF

#

chmod 755 ${wd}/do_docker.sh

ansible pc -m shell -a ${id}'/do_docker.sh '

#

# Und jetzt für den Docker selbst

#

cat < ${wd}/do_pull.sh

#!/bin/bash

#

#  \$Date: 2021-11-23 21:37:19 +0100 (Di, 23. Nov 2021) $

#  \$Revision: 1285 $

#  \$Author: alfred $

#  \$HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/k8s/K13_registry.sh $

#  \$Id: K13_registry.sh 1285 2021-11-23 20:37:19Z alfred $

#

# Konfiguration damit das docker-pull funktioniert

#

#shopt -o -s errexit  #—Terminates  the shell script  if a command returns an error code.

#shopt -o -s xtrace #—Displays each command before it’s executed.

shopt -o -s nounset #-No Variables without definition

sudo mkdir -p /etc/docker

sudo rm -f /etc/docker/daemon.json

tfile=\$(mktemp /tmp/daemon.XXXXXXXXX)

sudo cat < \${tfile}

{

insecure-registries : [docker.registry:5000]

}

AllOver

sudo cp -f \${tfile} /etc/docker/daemon.json

sudo chmod 666 /etc/docker/daemon.json

#

EOF

#

chmod 755 ${wd}/do_pull.sh

ansible pc -m shell -a ${id}'/do_pull.sh '

##

## Jetzt ist die Docker-Registry online und verfügbar

##

Dieses Skript konfiguriert die Registry als LoadBalancer Service. Damit bekommt die Registry eine fixe IP-Adresse, die von aussen erreichbar ist. Somit können wir den Cluster ansprechen und sind nicht an einen bestimmten Node gebunden. Durch die Verwendung einer Clusterdisk (gesteuert durch Longhorn) ist diese Registry auch ausfallsicher. Der Service sieht dann so aus:

alfred@pc1:~$ k -n container-registry get service

NAME  TYPE  CLUSTER-IP  EXTERNAL-IP  PORT(S)  AGE

registry  LoadBalancer  10.152.183.118  192.168.0.213  5000:5000/TCP  7h32m

alfred@pc1:~$

Das Skript trägt weiters die Registry in die Host-Dateien ein:

alfred@pc1:~$ cat /etc/hosts

192.168.0.201  pc1

192.168.0.202  pc2

192.168.0.203  pc3

192.168.0.204  pc4

192.168.0.205  pc5

192.168.0.2  monitoring

192.168.0.2  ntp

127.0.0.1 localhost pc1

# The following lines are desirable for IPv6 capable hosts

::1 ip6-localhost ip6-loopback

fe00::0 ip6-localnet

ff00::0 ip6-mcastprefix

ff02::1 ip6-allnodes

ff02::2 ip6-allrouters

ff02::3 ip6-allhosts

192.168.0.2 monitoring

192.168.0.213  docker.registry

alfred@pc1:~$

Es wird auch der Eintrag für das unsafe Repository gemacht:

alfred@pc1:~$ tail /var/snap/microk8s/current/args/containerd-template.toml

[plugins.io.containerd.grpc.v1.cri.registry]

# 'plugins.io.containerd.grpc.v1.cri.registry.mirrors' are namespace to mirror mapping for all namespaces.

[plugins.io.containerd.grpc.v1.cri.registry.mirrors]

[plugins.io.containerd.grpc.v1.cri.registry.mirrors.docker.io]

endpoint = [https://registry-1.docker.io, ]

[plugins.io.containerd.grpc.v1.cri.registry.mirrors.localhost:5000]

endpoint = [http://localhost:5000]

[plugins.io.containerd.grpc.v1.cri.registry.mirrors.docker.registry:5000]

endpoint = [http://docker.registry:5000]

alfred@pc1:~$

Somit ist das Repository im Cluster verfügbar.

Verwalten des Sourcerepositorys

Es gibt mehrere Befehle um die Daten im Sourcerepository zu beeinflußen.

docker push ${docker_registry}/${image}:latest

Dieser Befehle fügt ein Image in das Repository ein.

curl ${docker_registry}/v2/${image}/tags/list

Mit diesem Befehl kann man die bereits vorhandene tags-Liste von aussen eingesehen werden.

Wenn man aber die Images die bereits im Kubernetes Cluster sind verwalten möchte, dann wird es ein bisschen schwieriger. Dazu habe ich folgende Skripten:

#!/bin/bash

############################################################################################

#  $Date: 2021-11-25 21:57:57 +0100 (Do, 25. Nov 2021) $

#  $Revision: 1348 $

#  $Author: alfred $

#  $HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/dev/registry_list.sh $

#  $Id: registry_list.sh 1348 2021-11-25 20:57:57Z alfred $

#

# Manipulieren der microk8s.registry

# https://gist.github.com/Kevinrob/4c7f1e5dbf6ce4e94d6ba2bfeff37aeb

############################################################################################

#shopt -o -s errexit  #—Terminates  the shell script  if a command returns an error code.

#shopt -o -s xtrace #—Displays each command before it’s executed.

shopt -o -s nounset #-No Variables without definition

docker_registry=docker.registry:5000

repositories=$(curl -s ${docker_registry}/v2/_catalog)

for repo in $(echo ${repositories} | jq -r '.repositories[]'); do

echo $repo

tags=$(curl -s http://${docker_registry}/v2/${repo}/tags/list | jq -r '.tags[]')

for tag in $tags; do

echo  $repo:$tag

done

done

#

Dieses Skript zeigt alle Images und deren Tags an, die in der Registry vorhanden sind.

#!/bin/bash

############################################################################################

#  $Date: 2021-11-25 21:57:57 +0100 (Do, 25. Nov 2021) $

#  $Revision: 1348 $

#  $Author: alfred $

#  $HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/dev/registry_delete.sh $

#  $Id: registry_delete.sh 1348 2021-11-25 20:57:57Z alfred $

#

# Manipulieren der microk8s.registry

# https://gist.github.com/Kevinrob/4c7f1e5dbf6ce4e94d6ba2bfeff37aeb

#

# webdefault:20211123-1301

#

############################################################################################

#shopt -o -s errexit  #—Terminates  the shell script  if a command returns an error code.

#shopt -o -s xtrace #—Displays each command before it’s executed.

shopt -o -s nounset #-No Variables without definition

docker_registry=docker.registry:5000

# Prüfung ob gesetzt, sonst liefert die Shell hier eine Fehlermeldung

string=${1}

#echo ${string}

prefix=:

suffix=

xrepo=${string%$prefix*}

#echo ${xrepo}

xtag=${string#$xrepo$prefix}

#echo ${xtag}

xtag=${xtag%$suffix*}

#echo ${xtag}

tags=$(curl -sSL http://${docker_registry}/v2/${xrepo}/tags/list | jq -r '.tags[]')

for tag in $tags; do

if [ ${tag} = ${xtag} ] ;

then

echo Lösche  $xrepo:$tag

curl -v -k -X DELETE "http://${docker_registry}/v2/${xrepo}/manifests/$(

curl -k -s -I \

-H Accept: application/vnd.docker.distribution.manifest.v2+json \

http://${docker_registry}/v2/${xrepo}/manifests/${xtag} \

| awk '$1 == Docker-Content-Digest: { print $2 }' \

| tr -d $'\r' \

)"

fi

done

#

Dieses Skript löscht einen angegeben tag, wenn er gefunden wird.

Ein typischer Löschprozess sieht dann so aus:

alfred@bureau:~$ '/home/alfred/svn/trunk/k8s/dev/registry_list.sh'

chrony

chrony:latest

chrony:20211123-1273

chrony:20211123-1275

hello-world

hello-world:20211003

pgmaster

pgmaster:20211125-1327

pgmaster:20211125-1337

pgmaster:20211125-1340

pgmaster:20211125-1339

pgmaster:latest

pgmaster:20211125-1345

pgmaster:20211125-1343

pgmaster:20211125-1334

pgmaster:20211125-1336

pgmaster:20211125-1341

webdefault

webdefault:20211123-1292

webdefault:20211123-1293

webserver

webserver:20211124-1329

webserver:20211124-1321

webserver:20211124-1315

webserver:20211124-1331

webserver:20211124-1305

webserver:20211125-1333

webserver:20211124-1324

webserver:latest

webserver:20211125-1345

webserver:20211124-1306

webserver:20211124-1319

webserver:20211123-1305

webserver:20211124-1328

webserver:20211124-1312

webserver:20211124-1307

webserver:20211124-1327

webserver:20211125-1344

webserver:20211124-1330

webserver:20211124-1314

webserver:20211124-1320

webserver:20211124-1317

webserver:20211124-1332

alfred@bureau:~$ '/home/alfred/svn/trunk/k8s/dev/registry_delete.sh' webdefault:20211123-1293

Lösche  webdefault:20211123-1293

*  Trying 192.168.0.213:5000...

* Connected to docker.registry (192.168.0.213) port 5000 (#0)

> DELETE /v2/webdefault/manifests/sha256:ede78ca033eba1314667d5c6ced6a279833908d162ffe9103d7d1af42d53b6c7 HTTP/1.1

> Host: docker.registry:5000

> User-Agent: curl/7.74.0

> Accept: */*

>

* Mark bundle as not supporting multiuse

< HTTP/1.1 202 Accepted

< Docker-Distribution-Api-Version: registry/2.0

< X-Content-Type-Options: nosniff

< Date: Thu, 25 Nov 2021 20:55:23 GMT

< Content-Length: 0

<

* Connection #0 to host docker.registry left intact

alfred@bureau:~$ '/home/alfred/svn/trunk/k8s/dev/registry_delete.sh' webdefault:20211123-1293

alfred@bureau:~$

Mit diesen beiden Skripts kann man sich die Images anzeigen lassen, und alte Images löschen.

Zertifikate und LetsEncrypt

Inspiration:

https://suda.pl/5-minute-home-server-with/

https://faun.pub/wildcard-k8s-4998173b16c8

https://collabnix.github.io/kubetools/

https://forum.netcup.de/netcup-intern/technik/11841-let-s-encrypt-wildcard-zertifikate-via-certbot/

Um den Cluster vernünftig betreiben zu können braucht es Zertificate.

Darum habe ich den Certificate-Manager installiert.

#!/bin/bash

############################################################################################

#  $Date: 2021-10-21 21:40:29 +0200 (Do, 21. Okt 2021) $

#  $Revision: 659 $

#  $Author: alfred $

#  $HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/k8s/K5_certmanager.sh $

#  $Id: K5_certmanager.sh 659 2021-10-21 19:40:29Z alfred $

#

# cert-manager

#

############################################################################################

#shopt -o -s errexit  #—Terminates  the shell script  if a command returns an error code.

shopt -o -s xtrace #—Displays each command before it’s executed.

shopt -o -s nounset #-No Variables without definition

# Voraussetzung: Scripts in der richtigen Reihenfolge

#

# Definitionen für das Deployment

#

sname=$(basename $0)

app=mikrok8s/install/${sname}

pf=\$Revision:

sf= \$

fr=\$Revision: 659 $

revision=${fr#*$pf}

revision=${revision%$sf*}

xd=(`date '+%Y-%m-%d'`)

wd=${HOME}/copy/${app}/${xd}/r${revision}

id=/opt/cluster/${app}/${xd}/r${revision}

rm -f -R ${wd}

mkdir -p ${wd}

#

cat < ${wd}/install_certmanager.sh

#!/bin/bash

#

#  \$Date: 2021-10-21 21:40:29 +0200 (Do, 21. Okt 2021) $

#  \$Revision: 659 $

#  \$Author: alfred $

#  \$HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/k8s/K5_certmanager.sh $

#  \$Id: K5_certmanager.sh 659 2021-10-21 19:40:29Z alfred $

#

# Installation des cert-managers mit helm

#

#shopt -o -s errexit  #—Terminates  the shell script  if a command returns an error code.

shopt -o -s xtrace #—Displays each command before it’s executed.

shopt -o -s nounset #-No Variables without definition

# Voraussetzung: Scripts in der richtigen Reihenfolge

microk8s kubectl create namespace cert-manager

microk8s helm3 repo add jetstack https://charts.jetstack.io

microk8s helm3 repo update

microk8s helm3 install cert-manager jetstack/cert-manager \

--namespace cert-manager --version v1.5.4 \

--set installCRDs=true \

--set ingressShim.defaultIssuerName=letsencrypt-production \

--set ingressShim.defaultIssuerKind=ClusterIssuer \

--set ingressShim.defaultIssuerGroup=cert-manager.io

#

#wget https://github.com/jetstack/cert-manager/releases/download/v1.5.4/cert-manager.yaml --output-document=${id}/cert-manager.yaml

#wget https://github.com/jetstack/cert-manager/releases/download/v1.5.4/cert-manager.crds.yaml --output-document=${id}/cert-manager.crds.yaml

#microk8s kubectl apply -f ${id}/*.yaml

#

sleep 1m

microk8s kubectl get pods --namespace cert-manager

EOF

chmod 755 ${wd}/install_certmanager.sh

#

ansible pc1 -m shell -a ${id}'/install_certmanager.sh'

#

#!/bin/bash

############################################################################################

#  $Date: 2021-11-28 11:05:45 +0100 (So, 28. Nov 2021) $

#  $Revision: 1404 $apiVersion: networking.k8s.io/v1

#  $Author: alfred $

#  $HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/k8s/K14_webserver.sh $

#  $Id: K14_webserver.sh 1404 2021-11-28 10:05:45Z alfred $

#

# Einspielen der lokalen Konfigurationen - Produktiv ist slainte.

# https://stackoverflow.com/questions/67430592/how-to-setup-letsencrypt-with-kubernetes-microk8s-using-default-ingress

#

############################################################################################

#shopt -o -s errexit  #—Terminates  the shell script  if a command returns an error code.

shopt -o -s xtrace #—Displays each command before it’s executed.

shopt -o -s nounset #-No Variables without definition

#

# Definitionen für das Deployment

#

sname=$(basename $0)

app=mikrok8s/install/${sname}

pf=\$Revision:

sf= \$

fr=\$Revision: 1404 $

revision=${fr#*$pf}

revision=${revision%$sf*}

xd=(`date '+%Y-%m-%d'`)

wd=${HOME}/copy/${app}/${xd}/r${revision}

id=/opt/cluster/${app}/${xd}/r${revision}

rm -f -R ${wd}

mkdir -p ${wd}

#

cat < ${wd}/webserver-depl-svc.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

name: webserver-depl

namespace: slainte

spec:

selector:

matchLabels:

app: webserver-app

template:

metadata:

labels:

app: webserver-app

spec:

containers:

- name: webserver-app

image: nginx:1.20

---

apiVersion: v1

kind: Service

metadata:

name: webserver-svc

namespace: slainte

spec:

selector:

app: webserver-app

ports:

- port: 80

name: http

targetPort: 80

protocol: TCP

- port: 443

name: https

targetPort: 443

protocol: TCP

EOF

ansible pc1 -m shell -a 'microk8s kubectl apply -f '${id}'/webserver-depl-svc.yaml'

cat < ${wd}/letsencrypt-staging.yaml

apiVersion: cert-manager.io/v1

kind: ClusterIssuer

metadata:

name: letsencrypt-staging

spec:

acme:

#change to your email

email: slainte@slainte.at

server: https://acme-staging-v02.api.letsencrypt.org/directory

privateKeySecretRef:

name: letsencrypt-staging

solvers:

- http01:

ingress:

class: public

EOF

ansible pc1 -m shell -a 'microk8s kubectl apply -f '${id}'/letsencrypt-staging.yaml'

cat < ${wd}/letsencrypt-prod.yaml

apiVersion: cert-manager.io/v1

kind: ClusterIssuer

metadata:

name: letsencrypt-prod

spec:

acme:

server: https://acme-v02.api.letsencrypt.org/directory

#change to your email

email: slainte@slainte.at

privateKeySecretRef:

name: letsencrypt-prod

solvers:

- http01:

ingress:

class: public

EOF

ansible pc1 -m shell -a 'microk8s kubectl apply -f '${id}'/letsencrypt-prod.yaml'

cat < ${wd}/ingress-routes-update.yaml

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: webserver-routes

namespace: slainte

annotations:

# Class checken mit kubectl -n ingress describe daemonset.apps/nginx-ingress-microk8s-controller

kubernetes.io/ingress.class: public

# Das ist für das Zertifikat

cert-manager.io/cluster-issuer: letsencrypt-prod

# Das ist für das http -> https forwarding

# See https://kubernetes.github.io/ingress-nginx/examples/rewrite/

nginx.ingress.kubernetes.io/rewrite-target: /\$1

nginx.ingress.kubernetes.io/ssl-redirect: true

nginx.ingress.kubernetes.io/force-ssl-redirect: true

nginx.ingress.kubernetes.io/ssl-temporary-redirect: false

nginx.ingress.kubernetes.io/secure-backends: true

nginx.ingress.kubernetes.io/ssl-proxy-headers: X-Forwarded-Proto: https

nginx.ingress.kubernetes.io/proxy-body-size: 0m

nginx.ingress.kubernetes.io/proxy-buffering: off

#  nginx.ingress.kubernetes.io/ssl-passthrough: true

# https://github.com/nginxinc/kubernetes-ingress/tree/v1.12.0/examples/ssl-services

#  nginx.ingress.kubernetes.io/ssl-services: \${image}-svc

#  nginx.ingress.kubernetes.io/backend-protocol: HTTPS

spec:

tls:

- hosts:

- k8s.slainte.at

secretName: k8s-slainte-at-tls

rules:

- host: k8s.slainte.at

http:

paths:

- path: /(.*)

pathType: Prefix

backend:

service:

name: webserver-svc

port:

number: 80

defaultBackend:

service:

name: webserver-svc

port:

number: 80

EOF

ansible pc1 -m shell -a 'microk8s kubectl apply -f '${id}'/ingress-routes-update.yaml '

# Service PROD

curl -k -v http://k8s.slainte.at

#erreichbar sein.

#Aber auch mit https

curl -k -v https://k8s.slainte.at

#

## Prüfen des Zertifikates

ansible pc1 -m shell -a 'microk8s kubectl get certificate --all-namespaces'

ansible pc1 -m shell -a 'microk8s kubectl describe certificate --all-namespaces'

ansible pc1 -m shell -a 'microk8s kubectl get certificaterequests.cert-manager.io '

ansible pc1 -m shell -a 'microk8s kubectl describe certificaterequests '

ansible pc1 -m shell -a 'microk8s kubectl get certificatesigningrequests.certificates.k8s.io '

ansible pc1 -m shell -a 'microk8s kubectl get Issuer'

ansible pc1 -m shell -a 'microk8s kubectl get ClusterIssuer'

ansible pc1 -m shell -a 'microk8s kubectl describe ClusterIssuer letsencrypt-prod '

ansible pc1 -m shell -a 'microk8s kubectl get challenges.acme.cert-manager.io '

ansible pc1 -m shell -a 'microk8s kubectl describe challenges.acme.cert-manager.io '

##

exit

Die Zertifikate entstehen dann, wenn sie gebraucht werden. Die Definition ist im  Ingress. Derzeit gibt es einen URL pro Namespace, und damit ein Zertifikat.

Die Namespaces werden hier definiert.

#!/bin/bash

############################################################################################

#  $Date: 2021-11-23 18:03:25 +0100 (Di, 23. Nov 2021) $

#  $Revision: 1272 $

#  $Author: alfred $

#  $HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/k8s_app/namespace/slainte_env.sh $

#  $Id: slainte_env.sh 1272 2021-11-23 17:03:25Z alfred $

#

# Bauen und deployen

#

############################################################################################

#shopt -o -s errexit  #—Terminates  the shell script  if a command returns an error code.

shopt -o -s xtrace #—Displays each command before it’s executed.

shopt -o -s nounset #-No Variables without definition

export secretName=k8s-slainte-at-tls

export host=k8s.slainte.at

export namespace_comment=Namespace für die Produktion

export cluster_issuer=letsencrypt-prod

export docker_registry=docker.registry:5000

#

Bzw.

#!/bin/bash

############################################################################################

#  $Date: 2021-11-23 18:03:25 +0100 (Di, 23. Nov 2021) $

#  $Revision: 1272 $

#  $Author: alfred $

#  $HeadURL: https://monitoring.slainte.at/svn/slainte/trunk/k8s/k8s_app/namespace/default_env.sh $

#  $Id: default_env.sh 1272 2021-11-23 17:03:25Z alfred $

#

# Bauen und deployen

#

############################################################################################

#shopt -o -s errexit  #—Terminates  the shell script  if a command returns an error code.

shopt -o -s xtrace #—Displays each command before it’s executed.

shopt -o -s nounset #-No Variables without definition

export secretName=default-k8s-slainte-at-tls

export host=default.k8s.slainte.at

export namespace_comment=Namespace zum Testen

# export cluster_issuer=letsencrypt-staging

# Auch hier die Prod, wegen HTTP Strict Transport Security (HSTS)

export cluster_issuer=letsencrypt-prod

export docker_registry=docker.registry:5000

#

Das sieht dann im Ingress wie folgt aus:

---

# Yaml für ${image}:${tag}

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: ${image}-routes

namespace: ${namespace}

annotations:

kubernetes.io/ingress.class: public

cert-manager.io/cluster-issuer: ${cluster_issuer}

# https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/

nginx.ingress.kubernetes.io/rewrite-target: /$2

nginx.ingress.kubernetes.io/ssl-redirect: true

nginx.ingress.kubernetes.io/ssl-passthrough: true

nginx.ingress.kubernetes.io/force-ssl-redirect: true

nginx.ingress.kubernetes.io/ssl-temporary-redirect: false

nginx.ingress.kubernetes.io/secure-backends: true

nginx.ingress.kubernetes.io/ssl-proxy-headers: X-Forwarded-Proto: https

nginx.ingress.kubernetes.io/proxy-body-size: 0m

nginx.ingress.kubernetes.io/proxy-buffering: off

# https://github.com/nginxinc/kubernetes-ingress/tree/v1.12.0/examples/ssl-services

nginx.ingress.kubernetes.io/ssl-services: ${image}-svc

nginx.ingress.kubernetes.io/backend-protocol: HTTPS

spec:

tls:

- hosts:

- ${host}

secretName: ${secretName}

rules:

- host: ${host}

http:

paths: # https://github.com/google/re2/wiki/Syntax, https://www.regular-expressions.info/refcapture.html

- path: /${image}(/|$)(.*)

pathType: Prefix

backend:

service:

name: ${image}-svc

port:

number: 443

defaultBackend:

service:

name: default-svc

port:

number: 80

---

Man könnte aber auch mit Wildcard-Zertifikaten arbeiten. Ist aber in unserem Falle ein wenig übertrieben. Nachdem es ja eh für jeden Namespace und jeden host  einen Ingress braucht, kann man dafür auch ein eigenes Zertifikat anlegen lassen.

Entwicklungsumgebung

Inspiration:

https://pimylifeup.com/ubuntu-install-docker/

https://brjapon.medium.com/setting-up-ubuntu-20-04-arm-64-under-raspberry-pi-4-970654d12696

https://microk8s.io/docs/registry-built-in

https://microk8s.io/docs/registry-private

https://github.com/docker-library/hello-world

https://www.freecodecamp.org/news/how-to-remove-images-in-docker/

https://gobyexample.com/hello-world

https://linuxconfig.org/how-to-install-go-on-ubuntu-20-04-focal-fossa-linux

https://forums.docker.com/t/docker-private-registry-how-to-list-all-images/21136/2

https://github.com/fraunhoferfokus/deckschrubber

https://collabnix.github.io/kubetools/

Um das Source-Repository nutzen zu können brauchen wir eine Entwicklungsumgebung. Dafür benutzen wir unseren Entwicklungs-Raspbery PI.

OEBPS/images/image0010.jpg

Abbildung 8: Gesamtsystem

Dieser Entwicklungs-Raspberry ist ein Raspberry 4 mit 8GB RAM und einer 120 GB SDRAM Karte. Zusätzlich gibt es noch eine 1TB-USB-Platte für all die Backups.

Auf diesem Rechner ist Docker installiert.

alfred@monitoring:~$ docker version

Client:

Version:  20.10.7

API version:  1.41

Go version:  go1.13.8

Git commit:  20.10.7-0ubuntu1~20.04.1

Built:  Wed Aug  4 22:53:01 2021

OS/Arch:  linux/arm64

Context:  default

Experimental:  true

Server:

Engine:

Version:  20.10.7

API version:  1.41 (minimum version 1.12)

Go version:  go1.13.8

Git

Sie haben das Ende dieser Vorschau erreicht. , um mehr zu lesen!
Seite 1 von 1

Rezensionen

Was die anderen über K8s Applications mit MicroK8S auf Raspberry PI denken

0
0 Bewertungen / 0 Rezensionen
Wie hat es Ihnen gefallen?
Bewertung: 0 von 5 Sternen

Leser-Rezensionen