Vollwertiges Kubernetes von Grund auf auf Raspberry Pi.

Vollwertiges Kubernetes von Grund auf auf Raspberry Pi.

Vor kurzem hat ein bekanntes Unternehmen angekündigt, dass es seine Laptop-Reihe auf die ARM-Architektur umstellt. Als ich von dieser Nachricht hörte, erinnerte ich mich, dass ich bei der erneuten Durchsicht der EC2-Preise in AWS auf die Graviton-Prozessoren gestoßen bin, die zu einem sehr attraktiven Preis angeboten werden. Der Haken, so viel war klar, lag darin, dass es sich um ARM handelt. Damals kam mir nicht in den Sinn, dass ARM eine ernstzunehmende Angelegenheit ist…

Für mich war diese Architektur bisher das Revier von mobilen Geräten und verschiedenen IoT-Gadgets. „Echte“ Server auf ARM erscheinen mir eher unüblich, ja fast bizarr… Doch dieser Gedanke ließ mich nicht los, und so beschloss ich an einem der Wochenenden, herauszufinden, was man heutzutage überhaupt auf ARM starten kann. Ich wollte dabei mit etwas Vertrautem und Naheliegendem beginnen – einem Kubernetes-Cluster. Und zwar nicht irgendein beliebiges „Cluster“, sondern ganz professionell, damit es so nah wie möglich an dem ist, was ich aus der Produktion gewohnt bin.

Nach meiner Vorstellung sollte der Cluster aus dem Internet zugänglich sein, dort sollte eine Webanwendung laufen und mindestens Monitoring vorhanden sein. Für die Umsetzung dieser Idee benötigt man ein paar (oder mehr) Raspberry Pi mindestens der Modellreihe 3B+. Als Experimentierplattform käme auch AWS in Frage, aber ich war besonders an den "Malis" interessiert (die ohnehin nur herumstanden). Also werden wir darauf einen Kubernetes-Cluster mit Ingress, Prometheus und Grafana aufsetzen.

Vorbereitung der "Malis"

Installation des Betriebssystems und SSH

Bei der Wahl des Betriebssystems habe ich mir nicht allzu viele Gedanken gemacht: Ich habe einfach die frischeste Raspberry Pi OS Lite Version von der offiziellen Webseite. Dort ist auch die Installationsdokumentation, deren Schritte an allen Knoten des zukünftigen Clusters ausgeführt werden müssen. Anschließend sind folgende Schritte (ebenfalls an allen Knoten) erforderlich.

Nachdem ich Monitor und Tastatur angeschlossen habe, muss ich zunächst das Netzwerk und SSH einrichten:

  1. Für den Betrieb des Clusters muss auf dem Master unbedingt eine statische IP-Adresse vorhanden sein, während dies auf den Worker-Knoten nach Ermessen geschehen kann. Ich bevorzuge überall statische Adressen aus praktischen Gründen.
  2. Eine statische Adresse kann im Betriebssystem konfiguriert werden (in der Datei /etc/dhcpcd.conf entweder durch ein passendes Beispiel oder durch das Festlegen einer Lease auf dem verwendeten DHCP-Server (in meinem Fall dem Heimrouter).
  3. Der SSH-Server wird einfach in raspi-config aktiviert (Schnittstellenoptionen → SSH).

Danach können Sie sich per SSH anmelden (Standardbenutzername ist pi, und das Passwort ist raspberry oder das, welches Sie geändert haben) und die Einstellungen fortsetzen.

Weitere Einstellungen

  1. Legen wir den Hostnamen fest. In meinem Beispiel werden verwendet: pi-control und pi-worker.
  2. Überprüfen Sie, ob das Dateisystem auf die gesamte Festplatte erweitert wurde (df -h /). Bei Bedarf kann es über raspi-config erweitert werden.
  3. Ändern Sie das Standardbenutzerpasswort in raspi-config.
  4. Deaktivieren Sie die Swap-Datei (dies ist eine Anforderung von Kubernetes; wenn Sie weitere Informationen zu diesem Thema wünschen, siehe Issue #53533):
    dphys-swapfile swapoff
    systemctl disable dphys-swapfile
  5. Aktualisieren Sie die Pakete auf die neuesten Versionen:
    apt-get update && apt-get dist-upgrade -y
  6. Installieren Sie Docker und zusätzliche Pakete:
    apt-get install -y docker docker.io apt-transport-https curl bridge-utils iptables-persistent

    Bei der Installation von iptables-persistent müssen die iptables-Einstellungen für ipv4 gespeichert werden, und in der Datei /etc/iptables/rules.v4 fügen Sie Regeln zur Kette FORWARDhinzu, so:

    # Generated by xtables-save v1.8.2 on Sun Jul 19 00:27:43 2020
    *filter
    :INPUT ACCEPT [0:0]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [0:0]
    -A FORWARD -s 10.1.0.0/16  -j ACCEPT
    -A FORWARD -d 10.1.0.0/16  -j ACCEPT
    COMMIT
  7. Jetzt bleibt nur noch, neu zu starten.

Jetzt ist alles bereit für die Installation des Kubernetes-Clusters.

Installation von Kubernetes

An dieser Stelle habe ich absichtlich alle unsere internen Entwicklungen zur Automatisierung der Installation und Konfiguration eines K8s-Clusters beiseite gelegt. Stattdessen nutzen wir die offizielle Dokumentation von kubernetes.io (leicht ergänzt mit Kommentaren und Kürzungen).

Fügen wir das Kubernetes-Repository hinzu:

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get update

Weiterhin wird in der Dokumentation empfohlen, die CRI (Container Runtime Interface) zu installieren. Da Docker bereits installiert ist, machen wir mit der Installation der Hauptkomponenten weiter:

sudo apt-get install -y kubelet kubeadm kubectl kubernetes-cni

Beim Schritt zur Installation der Hauptkomponenten habe ich sofort kubernetes-cni, hinzugefügt, das für den Betrieb des Clusters erforderlich ist. Hier gibt es einen wichtigen Punkt: Das Paket kubernetes-cni erstellt aus irgendwelchen Gründen nicht standardmäßig ein Verzeichnis für die CNI-Interface-Konfigurationen, weshalb ich es manuell erstellen musste:

mkdir -p /etc/cni/net.d

Für den Betrieb des Netzwerk-Backends, über das wir später sprechen werden, muss ein Plugin für CNI nachinstalliert werden. Ich habe das mir vertraute und verständliche Plugin portmap gewählt (eine vollständige Liste finden Sie in Dokumentation.):

curl -sL https://github.com/containernetworking/plugins/releases/download/v0.7.5/cni-plugins-arm-v0.7.5.tgz | tar zxvf - -C /opt/cni/bin/ ./portmap

Kubernetes-Konfiguration

Knoten mit dem Control Plane

Die Installation des Clusters ist recht einfach. Um diesen Prozess zu beschleunigen und zu überprüfen, ob die Kubernetes-Images verfügbar sind, können Sie folgendes im Voraus ausführen:

kubeadm config images pull

Jetzt führen wir die eigentliche Installation durch – initialisieren wir die Control Plane des Clusters:

kubeadm init --pod-network-cidr=10.1.0.0/16 --service-cidr=10.2.0.0/16 --upload-certs

Bitte beachten Sie, dass die Subnetze für Dienste und Pods nicht miteinander und nicht mit bestehenden Netzwerken überlappen dürfen.

Am Ende erhalten wir eine Nachricht, dass alles gut gelaufen ist, und gleichzeitig werden Hinweise gegeben, wie man Arbeitsknoten an die Control Plane anschließt:

Ihr Kubernetes-Steuerungsknoten wurde erfolgreich initialisiert!
Um Ihren Cluster zu verwenden, müssen Sie Folgendes als regulärer Benutzer ausführen:
 mkdir -p $HOME/.kube
 sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
 sudo chown $(id -u):$(id -g) $HOME/.kube/config
Jetzt sollten Sie ein Pod-Netzwerk im Cluster bereitstellen.
Führen Sie "kubectl apply -f [podnetwork].yaml" aus, wobei Sie eine der Optionen nutzen, die unter:
 https://kubernetes.io/docs/concepts/cluster-administration/addons/
 aufgeführt sind.
Sie können jetzt beliebig viele Steuerungsknoten verbinden, indem Sie folgenden Befehl auf jedem als Root ausführen:
 kubeadm join 192.168.88.30:6443 --token a485vl.xjgvzzr2g0xbtbs4 
   --discovery-token-ca-cert-hash sha256:9da6b05aaa5364a9ec59adcc67b3988b9c1b94c15e81300560220acb1779b050 
   --contrl-plane --certificate-key 72a3c0a14c627d6d7fdade1f4c8d7a41b0fac31b1faf0d8fdf9678d74d7d2403
Bitte beachten Sie, dass der Zertifikatsschlüssel Zugriff auf sensible Daten des Clusters gewährt. Halten Sie ihn geheim!
Zur Sicherheit werden hochgeladene Zertifikate in zwei Stunden gelöscht; falls erforderlich, können Sie
"kubeadm init phase upload-certs --upload-certs" verwenden, um die Zertifikate anschließend erneut hochzuladen.
Dann können Sie auch beliebig viele Worker-Knoten verbinden, indem Sie folgenden Befehl auf jedem als Root ausführen:
kubeadm join 192.168.88.30:6443 --token a485vl.xjgvzzr2g0xbtbs4 
   --discovery-token-ca-cert-hash sha256:9da6b05aaa5364a9ec59adcc67b3988b9c1b94c15e81300560220acb1779b050

Lassen Sie uns die Empfehlungen zur Hinzufügung der Konfiguration für den Benutzer befolgen. Ich empfehle außerdem, sofort die Autovervollständigung für kubectl hinzuzufügen:

 kubectl completion bash > ~ /.kube/completion.bash.inc
 printf "
 # Kubectl Shell-Vervollständigung
 source '$HOME/.kube/completion.bash.inc'
 " >> $HOME/.bash_profile
 source $HOME/.bash_profile

Zu diesem Zeitpunkt kann bereits der erste Knoten im Cluster gesehen werden (auch wenn er noch nicht bereit ist):

root@pi-control:~# kubectl get no
NAME         STATUS     ROLES    AGE   VERSION
pi-control   NotReady   master   29s   v1.18.6

Netzwerkkonfiguration

Wie im Installationshinweis angegeben, muss als Nächstes das Netzwerk im Cluster eingerichtet werden. In der Dokumentation werden die Optionen Calico, Cilium, contiv-vpp, Kube-router und Weave Net vorgeschlagen… Ich habe hier von der offiziellen Anleitung abgewichen und die Variante gewählt, die mir bekannter und verständlicher ist: flannel im host-gw Modus (weitere Informationen zu verfügbaren Backends finden Sie in der in der Projektdokumentation.).

Die Installation in den Cluster ist ziemlich einfach. Zunächst laden wir die Manifeste herunter:

wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

Dann ändern wir in den Einstellungen den Typ von vxlan findet man host-gw:

sed -i 's/vxlan/host-gw/' kube-flannel.yml

… und das Subnetz der Pods — von dem Standardwert auf den, der bei der Initialisierung des Clusters angegeben wurde:

sed -i 's#10.244.0.0/16#10.1.0.0/16#' kube-flannel.yml

Nach diesem Schritt erstellen wir die Ressourcen:

kubectl create -f kube-flannel.yml

Fertig! Nach einiger Zeit wechselt der erste K8s-Knoten in den Status Bereit:

NAME         STATUS   ROLES    AGE   VERSION
pi-control   Ready    master   2m    v1.18.6

Hinzufügen eines Arbeitsknotens

Jetzt können wir einen Worker hinzufügen. Dazu muss auf diesem, nachdem Kubernetes gemäß dem oben beschriebenen Szenario installiert wurde, einfach der zuvor erhaltene Befehl ausgeführt werden:

kubeadm join 192.168.88.30:6443 --token a485vl.xjgvzzr2g0xbtbs4 
    --discovery-token-ca-cert-hash sha256:9da6b05aaa5364a9ec59adcc67b3988b9c1b94c15e81300560220acb1779b050

Damit können wir davon ausgehen, dass das Cluster bereit ist:

root@pi-control:~# kubectl get no
NAME         STATUS   ROLES    AGE    VERSION
pi-control   Ready    master   28m    v1.18.6
pi-worker    Ready       2m8s   v1.18.6

Ich hatte nur zwei Raspberry Pi zur Verfügung, also wollte ich nicht eine davon nur für den Control Plane verwenden. Daher habe ich die automatisch gesetzte Taint vom Knoten pi-control entfernt, indem ich folgendes ausgeführt habe:

root@pi-control:~# kubectl edit node pi-control

… und habe diese Zeilen entfernt:

 - effect: NoSchedule
   key: node-role.kubernetes.io/master

Ausstattung des Clusters mit dem notwendigen Minimum

Zunächst benötigen wir Helm. Natürlich kann man alles auch ohne machen, aber Helm ermöglicht es, einige Komponenten ganz ohne Dateibearbeitung nach eigenen Wünschen zu konfigurieren. Und im Grunde ist es nur eine Binärdatei, die "keine Vergünstigungen verlangt."

Also gehen wir auf helm.sh in den Bereich docs/installation und führen den Befehl von dort aus aus:

curl -s https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash

Danach fügen wir das Chart-Repository hinzu:

helm repo add stable https://kubernetes-charts.storage.googleapis.com/

Jetzt installieren wir die Infrastrukturkomponenten gemäß der Planung:

  • Ingress-Controller;
  • Prometheus;
  • Grafana;
  • cert-manager.

Ingress-Controller

Die erste Komponente — Ingress-Controller — ist recht einfach einzurichten und sofort einsatzbereit. Dazu muss man lediglich auf den Bereich bare-metal auf der Webseite gehen und von dort aus den Installationsbefehl ausführen:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/baremetal/deploy.yaml

Allerdings begann in diesem Moment die "Himbeere" zu überlasten und bei den Disk-IOPS an ihre Grenzen zu stoßen. Das liegt daran, dass zusammen mit dem Ingress-Controller eine große Anzahl an Ressourcen installiert wird, viele API-Anfragen ausgeführt werden und folglich viele Daten in etcd geschrieben werden. Insgesamt entweder ist die Klasse 10 Speicherkarte nicht sehr leistungsfähig, oder es fehlt grundsätzlich an SD-Karten für diese Last. Trotzdem lief nach etwa 5 Minuten alles.

Ein Namespace wurde erstellt, und darin erschien der Controller sowie alles, was er benötigte:

root@pi-control:~# kubectl -n ingress-nginx get pod
NAME                                        READY   STATUS      RESTARTS   AGE
 ingress-nginx-admission-create-2hwdx        0/1     Completed   0          31s
 ingress-nginx-admission-patch-cp55c         0/1     Completed   0          31s
 ingress-nginx-controller-7fd7d8df56-68qp5   1/1     Running     0          48s

Prometheus

Die folgenden zwei Komponenten lassen sich ziemlich einfach über Helm aus dem Chart-Repository installieren.

Suchen nach Prometheus, erstellen wir einen Namespace und installieren darin:

helm search repo stable | grep prometheus
kubectl create ns monitoring
helm install prometheus --namespace monitoring stable/prometheus --set server.ingress.enabled=True --set server.ingress.hosts={"prometheus.home.pi"}

Standardmäßig fordert Prometheus 2 Festplatten an: eine für die Daten von Prometheus selbst und eine für die Daten des AlertManagers. Da in dem Cluster keine Storage Class erstellt wurde, werden die Festplatten nicht angefordert und die Pods werden nicht gestartet. Für bare metal-Installationen von Kubernetes verwenden wir normalerweise Ceph rbd, jedoch ist das bei Raspberry Pi übertrieben.

Daher erstellen wir einen einfachen lokalen Speicher auf dem Hostpfad. Die Manifeste für PV (Persistent Volume) für den prometheus-server und den prometheus-alertmanager sind in der Datei zusammengeführt. prometheus-pv.yaml in Git-Repositories mit Beispielen für den Artikel. Das Verzeichnis für das PV muss vorab auf der Festplatte des Knotens erstellt werden, an den wir Prometheus binden möchten: im Beispiel ist nodeAffinity nach Hostname pi-worker und die Verzeichnisse sind dort erstellt /data/localstorage/prometheus-server und /data/localstorage/prometheus-alertmanager.

Laden Sie das Manifest herunter (klonen) und fügen Sie es in Kubernetes hinzu:

kubectl create -f prometheus-pv.yaml

In diesem Schritt stieß ich zum ersten Mal auf das Problem der ARM-Architektur. Kube-state-metrics, das standardmäßig im Prometheus-Chart installiert wird, weigerte sich zu starten. Es gab einen Fehler aus:

root@pi-control:~# kubectl -n monitoring logs prometheus-kube-state-metrics-c65b87574-l66d8
standard_init_linux.go:207: exec user process caused "exec format error"

Der Punkt ist, dass für kube-state-metrics ein Bild des CoreOS-Projekts verwendet wird, das nicht für ARM gebaut wird:

kubectl -n monitoring get deployments.apps prometheus-kube-state-metrics -o=jsonpath={.spec.template.spec.containers[].image}
quay.io/coreos/kube-state-metrics:v1.9.7

Ich musste ein wenig googeln und fand beispielsweise dieses Image. Um es zu nutzen, обновим wir das Release und geben an, welches Image für kube-state-metrics verwendet werden soll:

helm upgrade prometheus --namespace monitoring stable/prometheus --set server.ingress.enabled=True --set server.ingress.hosts={"prometheus.home.pi"} --set kube-state-metrics.image.repository=carlosedp/kube-state-metrics --set kube-state-metrics.image.tag=v1.9.6

Wir prüfen, ob alles läuft:

root@pi-control:~# kubectl -n monitoring get po
NAME                                             READY   STATUS              RESTARTS   AGE
prometheus-alertmanager-df65d99d4-6d27g          2/2     Running             0          5m56s
prometheus-kube-state-metrics-5dc5fd89c6-ztmqr   1/1     Running             0          5m56s
prometheus-node-exporter-49zll                   1/1     Running             0          5m51s
prometheus-node-exporter-vwl44                   1/1     Running             0          4m20s
prometheus-pushgateway-c547cfc87-k28qx           1/1     Running             0          5m56s
prometheus-server-85666fd794-z9qnc               2/2     Running             0          4m52s

Grafana und cert-manager

Für Diagramme und Dashboards installieren wir Grafana:

helm install grafana --namespace monitoring stable/grafana  --set ingress.enabled=true --set ingress.hosts={"grafana.home.pi"}

Am Ende der Ausgabe wird uns gezeigt, wie wir das Passwort für den Zugang erhalten:

kubectl get secret --namespace monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo

Um Zertifikate zu bestellen, installieren wir cert-manager. Für die Installation wenden wir uns an Dokumentation., die entsprechende Befehle für Helm anbietet:

helm repo add jetstack https://charts.jetstack.io

helm install 
  cert-manager jetstack/cert-manager 
  --namespace cert-manager 
  --version v0.16.0 
  --set installCRDs=true

Für selbstsignierte Zertifikate im privaten Gebrauch ist das völlig ausreichend. Wenn jedoch das gleiche Let’s Encrypt, benötigt man zusätzlich noch einen Cluster-Issuer. Details dazu finden Sie in unserem Artikel „SSL-Zertifikate von Let’s Encrypt mit cert-manager in Kubernetes».

Ich habe mich für die Variante aus dem Beispiel in der Dokumentation entschieden, da ich dachte, dass die Staging-Version von LE ausreichend sein wird. Wir ändern die E-Mail-Adresse im Beispiel, speichern sie in einer Datei und fügen sie zum Cluster hinzu (cert-manager-cluster-issuer.yaml):

kubectl create -f cert-manager-cluster-issuer.yaml

Jetzt können wir ein Zertifikat bestellen, zum Beispiel für Grafana. Dazu benötigen wir eine Domain und externen Zugriff auf den Cluster. Ich habe eine Domain, und der Traffic wird über Port-80- und Port-443-Umleitungen auf meinem Heimrouter entsprechend dem erstellten Ingress-Controller-Service eingerichtet:

kubectl -n ingress-nginx get svc
NAME                                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.2.206.61            80:31303/TCP,443:30498/TCP   23d

Der Port 80 wird in diesem Fall auf 31303 und der Port 443 auf 30498 übersetzt. (Die Ports werden zufällig generiert, daher unterscheiden sie sich bei Ihnen.)

Hier ist ein Beispielzertifikat (cert-manager-grafana-certificate.yaml):

apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
  name: grafana
  namespace: monitoring
spec:
  dnsNames:
    - grafana.home.pi
  secretName: grafana-tls
  issuerRef:
    kind: ClusterIssuer
    name: letsencrypt-staging

Fügen Sie es zum Cluster hinzu:

kubectl create -f cert-manager-grafana-certificate.yaml

Danach wird eine Ingress-Ressource erstellt, die die Validierung durch Let’s Encrypt ermöglicht:

root@pi-control:~# kubectl -n monitoring get ing
NAME                        CLASS    HOSTS                        ADDRESS         PORTS   AGE
cm-acme-http-solver-rkf8l      grafana.home.pi      192.168.88.31   80      72s
grafana                        grafana.home.pi      192.168.88.31   80      6d17h
prometheus-server              prometheus.home.pi   192.168.88.31   80      8d

Sobald die Validierung abgeschlossen ist, sehen wir, dass das Resource certificate bereit ist und im oben genannten Geheimnis grafana-tls — das Zertifikat und den Schlüssel. Sie können sofort überprüfen, wer das Zertifikat ausgestellt hat:

root@pi-control:~# kubectl -n monitoring get certificate
NAME      READY   SECRET        AGE
grafana   True    grafana-tls   13m

root@pi-control:~# kubectl -n monitoring get secrets grafana-tls -ojsonpath="{.data['tls.crt']}" | base64 -d | openssl x509 -issuer -noout
issuer=CN = Fake LE Intermediate X1

Kehren wir zu Grafana zurück. Wir müssen die Helm-Release etwas anpassen, um die Einstellungen für TLS entsprechend dem erstellten Zertifikat zu ändern.

Dafür laden wir das Chart herunter, ändern es und aktualisieren aus dem lokalen Verzeichnis:

helm pull --untar stable/grafana

Wir bearbeiten die Datei grafana/values.yaml die TLS-Parameter:

  tls:
    - secretName: grafana-tls
      hosts:
        - grafana.home.pi

Hier können wir auch sofort Prometheus als Datenquelle:

datasources:
  datasources.yaml:
    apiVersion: 1
    datasources:
    - name: Prometheus
      type: prometheus
      url: http://prometheus-server:80
      access: proxy
      isDefault: true

Jetzt aktualisieren wir das Grafana-Chart aus dem lokalen Verzeichnis:

helm upgrade grafana --namespace monitoring ./grafana  --set ingress.enabled=true --set ingress.hosts={"grafana.home.pi"}

Wir überprüfen, ob im Ingress grafana der Port 443 hinzugefügt wurde und der Zugriff über HTTPS besteht:

root@pi-control:~# kubectl -n monitoring get ing grafana
NAME      CLASS    HOSTS                     ADDRESS         PORTS     AGE
grafana   <none>   grafana.home.pi           192.168.88.31   80, 443   63m

root@pi-control:~# curl -kI https://grafana.home.pi
HTTP/2 302
server: nginx/1.19.1
date: Tue, 28 Jul 2020 19:01:31 GMT
content-type: text/html; charset=utf-8
cache-control: no-cache
expires: -1
location: /login
pragma: no-cache
set-cookie: redirect_to=%2F; Path=/; HttpOnly; SameSite=Lax
x-frame-options: deny
strict-transport-security: max-age=15724800; includeSubDomains

Um Grafana in Aktion zu demonstrieren, können Sie herunterladen und hinzufügen ein Dashboard für kube-state-metrics. So sieht es aus:

Vollwertiges Kubernetes von Grund auf auf Raspberry Pi.

Ich empfehle außerdem, ein Dashboard für den Node Exporter hinzuzufügen: Es zeigt detailliert, was mit den „Raspberry Pis“ passiert (CPU-Last, Speicherauslastung, Netzwerk, Festplatte usw.).

Danach halte ich es für den Cluster bereit, Anwendungen zu empfangen und auszuführen!

Hinweis zur Erstellung

Für die Erstellung von Anwendungen für die ARM-Architektur gibt es mindestens zwei Optionen. Erstens kann man auf einem ARM-Gerät bauen. Allerdings habe ich bei der aktuellen Auslastung von zwei Raspberry Pis festgestellt, dass sie nicht einmal das Builden verkraften werden. Daher habe ich mir einen neuen Raspberry Pi 4 bestellt (der ist leistungsstärker und hat sogar 4 GB RAM) – ich plane, darauf zu bauen.

Die zweite Option ist der Bau eines multiarchitektur Docker-Images auf einer leistungsstärkeren Maschine. Dafür gibt es das Docker Buildx-Plugin.. Wenn die Anwendung in einer kompilierbaren Sprache vorliegt, ist eine Cross-Kompilation für ARM erforderlich. Ich werde die gesamten Einstellungen für diesen Ansatz nicht beschreiben, da das den Rahmen eines eigenen Artikels sprengen würde. Mit dieser Methode können "universelle" Images erreicht werden: Docker, das auf einer ARM-Maschine läuft, lädt automatisch das entsprechend Architektur-optimierte Image herunter.

Fazit

Das durchgeführte Experiment übertraf all meine Erwartungen: [mindestens] ein "vanilla" Kubernetes mit der erforderlichen Basis läuft recht gut auf ARM, und bei der Konfiguration traten nur ein paar kleine Probleme auf.

Die Raspberry Pi 3B+ halten die CPU-Last aus, jedoch stellen ihre SD-Karten ein deutliches Flaschenhalten dar. Kollegen haben mir erzählt, dass es in bestimmten Versionen möglich ist, von USB zu booten, wo man ein SSD anschließen kann: dann wird die Situation wahrscheinlich besser sein.

Hier ist ein Beispiel für die CPU-Auslastung bei der Installation von Grafana:

Vollwertiges Kubernetes von Grund auf auf Raspberry Pi.

Für Experimente und "zum Ausprobieren" vermittelt meines Erachtens ein Kubernetes-Cluster auf den "Raspberry Pis" viel bessere Erfahrungen bei der Nutzung als derselbe Minikube, da alle Clusterkomponenten professionell installiert und betrieben werden.

In der Zukunft gibt es die Idee, den gesamten CI/CD-Zyklus vollständig auf Raspberry Pi in das Cluster einzufügen. Ich freue mich auch, wenn jemand seine Erfahrungen mit der Einrichtung von K8s auf AWS Graviton teilen kann.

P.S. Ja, „Produktion“ könnte näher sein, als ich dachte:

Vollwertiges Kubernetes von Grund auf auf Raspberry Pi.

P.P.S.

Lesen Sie auch in unserem Blog:

Quelle: habr.com

Купить надежный хостинг для сайтов с защитой от DDoS, VPS VDS серверы 🔥 Купить надежный хостинг для сайтов с защитой от DDoS, VPS VDS серверы | ProHoster