Kubernetes-Workshop Teil 6: Die erste Applikation

Im fünften Teil haben wir unseren Kubernetes-Cluster eingerichtet. Heute wollen wir die erste Applikation installieren. Wir verwenden für die Demo einfach das kleine webbasierte Spiel game2048. Dieses gibt es praktischerweise schon fertig als Docker-Container.

Im ersten Schritt erstellen wir einen Namespace:

kubectl create namespace game2048

Dann erzeugen wir eine deployment.yaml mit folgendem Inhalt:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: game2048
spec:  
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: game2048      
  template: 
    metadata:
      labels:
        app.kubernetes.io/name: game2048        
    spec:      
      containers:
        - name: game2048
          securityContext:
            {}
          image: "ponsfrilus/2048nginx:latest"
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 80
              protocol: TCP

und deployen diese mit:

kubectl -n game2048 create -f deployment.yaml

Mit folgendem Kommando kann man sich das Ergebnis anschauen:

kubectl -n game2048 get deployments

Wir sollten folgendes Ergebnis erhalten:

NAME       READY   UP-TO-DATE   AVAILABLE   AGE
game2048   1/1     1            1           16s

Damit wir auf den installierten Server zugreifen können, benötigen wir einen Service, den wir in der Datei service.yaml definieren:

apiVersion: v1
kind: Service
metadata:
  name: game2048
  labels:    
    app.kubernetes.io/name: game2048    
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app.kubernetes.io/name: game2048

Auch diesen Service installieren wir mit:

kubectl -n game2048 create -f service.yaml

Nun definieren wir eine Ingress-Route und erstellen eine Datei ingress.yaml. Das Entscheidende ist die Angabe der Domain unter „host:“. Unter dieser Adresse wollen wir die Anwendung aufrufen.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: game2048
  labels:    
    app.kubernetes.io/name: game2048
spec:  
  rules:
    - host: "2048.ronnywalter.de"
      http:
        paths:
          - path: /
            backend:
              serviceName: game2048
              servicePort: 80

Auch diese installieren wir mit:

kubectl -n game2048 create -f ingress.yaml

Damit haben wir folgende Komponenten deployed:

kubectl -n game2048 get all
NAME                            READY   STATUS    RESTARTS   AGE
pod/game2048-5fb4546466-266hv   1/1     Running   0          7m10s

NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/game2048   ClusterIP   10.43.114.142   <none>        80/TCP    3m45s

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/game2048   1/1     1            1           7m10s

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/game2048-5fb4546466   1         1         1       7m10s

Natürlich kann man sich das Ganze auch in der Rancher-Oberfläche ansehen. Der soeben erzeugte Namespace ist standardmäßig noch keinem Rancher-Projekt zugeordnet. Das liegt daran, dass der Projekt-Begriff eine Rancher-Eigenschaft ist, und kein Kubernetes-Objekt. Wir haben soeben nur mit Kubernetes-Mitteln gearbeitet. Man kann den Namespace über die Oberfläche in ein Projekt (wie z.B. Default) verschieben:

Rancher: Namespace verschieben

Es gibt auch die Möglichkeit, an den Namespace sogenannte Labels anzubringen und damit die Zuordnung zu Projekten zu realisieren, doch dazu später mehr.

Im Projekt Default sieht man nun die installierte Anwendung:

Rancher-Resources-Workloads.

Oder die installierten Ingress-Routen (unter „Load Balancing“):

Rancher-Ingress-Route

Nun wollen wir endlich die Applikation auch aufrufen und können das unter der URL, die wir in der Ingress-Definition angegeben haben, auch tun. Im obigen Beispiel haben wir http://2048.ronnywalter.de verwendet.

In Teil 2 haben wir die Server mit der Firewall ufw eingerichtet. Es ist natürlich notwendig, den http-Port zuzulassen, damit wir auf den Server zugreifen können. Das machen wir in dem Beispiel auf den 3 Nodes, auf denen wir Kubernetes installiert haben. Den https-Port öffnen wir gleich mit, da wir den später noch brauchen.

ufw allow http
ufw allow https

Nun können wir die Seite aufrufen.

Der Browser zeigt nun noch an, dass die Seite „Nicht Sicher“ ist. Heutzutage betreibt man keine Seiten mehr ohne https und ein gültiges Zertifikat. Daher wollen wir uns im nächsten Teil ein eben solches via LetsEncrypt besorgen.

Kubernetes-Workshop Teil 5: Kubernetes

Nachdem nun endlich unsere Rancher-Installation läuft, gehts heute endlich mal an die Einrichtung eines Kubernetes-Clusters. Dazu loggen wir uns in Rancher ein und gehen auf „Global“ und wählen „Add Cluster“ aus. Wir wollen heute noch keinen Cluster in der Cloud anlegen. Das machen wir später einmal. Heute erstellen wir einen „Custom“ Cluster auf unseren Nodes.

Man wählt zunächst einen Namen, wie zum Beispiel „k8s“. Im unteren Bereich hat man die Möglichkeit, noch diverse Einstellungen, wie z.B. die Kubernetes-Version festzulegen. Ich belasse es zunächst bei der Standardvorgabe. Allerdings möchte ich, dass die Kubernetes-Komponenten über das wireguard-Interface miteinander reden, das wir bereits eingerichtet haben. Einen Einstieg dazu gibt es hier.

Wir gehen auf „Edit as YAML“ und passen den Teil „network“ an:

  network:
    mtu: 0
    options:
      canal_iface: wg0
      flannel_backend_type: vxlan
    plugin: canal

Entscheidend ist der Eintrag „canal_iface“. In der Rancher-Dokumentation gibt’s noch mehr Details. Wir klicken auf Next und schon existiert unser Cluster. Dieser braucht natürlich noch Nodes. Hier nochmal der Plan:

NameCoresRAMIPZweck
defiant48 GB10.0.0.1Rancher-Installation
discovery616 GB10.0.0.2Master, Worker
reliant830 GB10.0.0.3Worker
yorktown616 GB10.0.0.4Worker

Wir erstellen nun als erstes den Master Node. Ich selektiere hier alle Rollen und trage in den Advanced Options die zu nutzenden IPs ein. Bei der public-IP gibt man die „ganz normale“ öffentliche IP des Servers an. Bei der internen IP geben wir die Wireguard IP-Adresse an. Als Beispiel für „discovery“:

Das erzeugte Kommando kopieren wir uns, und führen es auf dem Server „discovery“ aus. Ich klicke dann auf Done und warte, bis der Cluster „Ready“ ist. Man kann vermutlich auch alle 3 Nodes in einem Rutsch hinzufügen, ich habe das aber immer nacheinander gemacht. Den zweiten Node fügen wir hinzu, in dem wir auf „Edit“ klicken und dann im unteren Bereich genau so den nächsten Node hinzufügen. Wir wählen dabei aber immer nur die Role „Worker“ aus. Wie gesagt, dieses Setup hat nicht den Anspruch einer Produktionsumgebung mit hoher Verfügbarkeit. Im echten Leben würde man sicherlich auf den Mastern keine Workload haben wollen und natürlich mehrere Master installieren.

Wenn alle 3 Nodes hinzugefügt sind, sollte die Übersicht unter „Nodes“ so ähnlich aussehen:

Perfekt, der Cluster läuft!

Wenn man lokal mit kubectl auf den Cluster zugreifen möchte, holt man sich noch die Kubeconfig unter „Cluster“ und speichert den Inhalt lokal in der Datei ˜/.kube/config. Natürlich muss man sich lokal vorher noch den kubectl-client installieren. Auf dem Mac geht das wunderbar mit Homebrew:

brew install kubectl

Danach kann man mit kubectl schon mit seinem Cluster arbeiten und die erste Workload deployen oder sich z.B. die nodes anzeigen lassen:

~ » kubectl get nodes                                                                                                                
NAME        STATUS   ROLES                      AGE   VERSION
discovery   Ready    controlplane,etcd,worker   23d   v1.17.4
reliant     Ready    worker                     23d   v1.17.4
yorktown    Ready    worker                     23d   v1.17.4

Beim nächsten Mal deployen wir die erste Applikation auf dem Cluster.

Kubernetes Workshop Teil 4: Docker und Rancher

Heute ist es soweit, wir wollen Rancher in Betrieb nehmen. In Teil 2 haben wir uns 4 Server eingerichtet. In meinem Fall sieht das geplante Setup so aus:

NameCoresRAMIPZweck
defiant48 GB10.0.0.1Rancher-Installation
discovery616 GB10.0.0.2Master, Worker
reliant830 GB10.0.0.3Worker
yorktown616 GB10.0.0.4Worker

Auf allen Maschinen benötigen wir Docker. Ich verwende nicht die Docker-Pakete aus Ubuntu 18.04 sondern die aktuellen Dockerversionen gemäß der Anleitung bei Docker:

apt-get remove docker docker-engine docker.io containerd runc

apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

apt-get update
apt-get install docker-ce docker-ce-cli containerd.io

Wenn man die ufw-Firewall in Verbindung mit Docker einsetzt, kann es sein, dass Ports geöffnet werden, die ich in der Firewall gar nicht erlaube. Das liegt daran, dass docker Kommandos mit iptables ausführt. Dazu gibt es im Internet einige Artikel. Eine Möglichkeit, das Verhalten zu deaktivieren, ist das Setzen der Option iptables=false. Ich habe das in der /etc/docker/daemon.json getan:

cat /etc/docker/daemon.json 
{
    "iptables": false
}

Ob das irgendwann zu Problemen führt, weiß ich noch nicht. Bisher haben alle Anwendungen, die ich dann deployed habe, funktioniert. Im nächsten Schritt muss docker noch aktiviert und gestartet werden:

systemctl enable docker
systemctl start docker

Mit docker info kann man prüfen, ob der Daemon läuft:

docker info

Super, sobald Docker läuft, können wir endlich Rancher installieren. Wie bereits gesagt, reicht mir für meine Experimente eine single node installation. Es soll auch automatisch ein entsprechendes SSL-Zertifikat per LetsEncrypt erstellt werden. Das erreicht man mit der Angabe der Option –acme-domain. Dazu „ruft“ LetsEncrypt die angegebene Domain auf und muss den Server auf dem http-Port erreichen können. Also öffnen wir in der Firewall auf defiant noch den Port. Wir wollen per https zugreifen, also machen wir den auch auf:

ufw allow http
ufw allow https

Ich nehme die aktuelle Version und verwende rancher 2.4.2. Ein einfacher docker-Befehl auf dem ersten Server defiant reicht aus:

docker run -d --restart=unless-stopped -p 8080:80 -p 8443:443 rancher/rancher:v2.4.2 --acme-domain rancher.ronnywalter.de

Nun sollte ein Container laufen:

docker ps
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS                                      NAMES
cd325b199817        rancher/rancher:v2.4.2   "entrypoint.sh --acm…"   3 weeks ago         Up 15 hours         0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   tender_sammet

Nun sollten wir mit dem Browser die entsprechende URL aufrufen können und haben dabei wie von Wunderhand ein gültiges Zertifikat, also in meinem Fall https://rancher.ronnywalter.de

Rancher begrüßt euch mit der Bitte, ein neues Admin-Passwort festzulegen:

Anschließen bestätigt man noch die Domain und hat dann eine lauffähige Rancher-Installation, allerdings noch ohne einen Kubernetes-Cluster. Ich lege mir immer unter Security/Users einen persönlichen (Admin-)User an, logge mich mit diesem ein und sperre dann den Admin-Account.

Im nächsten Teil werden wir einen Kubernetes-Cluster anlegen.

Kubernetes Workshop Teil 3: Wireguard

Nachdem wir in Teil 2 die Server vorbereitet haben, wollen wir nun Wireguard installieren und konfigurieren.

Wie gesagt, sollen die Server und die Kubernetes-Komponenten verschlüsselt über wireguard miteinander kommunizieren. Eine schöne Anleitung dazu gibt es z.B. hier:

https://vitobotta.com/2019/07/17/kubernetes-wireguard-vpn-rancheros/

Im ersten Schritt installieren wir Wireguard. Vorher machen wir uns natürlich zum root.

sudo -s
add-apt-repository ppa:wireguard/wireguard
apt update
apt install wireguard

Es gibt diverse Anleitungen, wie man unter Ubuntu ein Wireguard-Setup aufbauen kann, wie z.B.

https://www.thomas-krenn.com/de/wiki/Ubuntu_18.04_als_WireGuard_VPN_Client_konfigurieren

Die Schritte sind im Prinzip für jeden Server das Gleiche. Wir erzeugen auf jedem Server jeweils einen privaten, einen öffentlichen Schlüssel und einen sogenannten preshared-key. Hier als Beispiel für meinen ersten Server defiant:

sudo -s
cd /etc/wireguard
umask 077
wg genkey > private-key
wg pubkey > public-key < private-key
wg genpsk > defiant.psk

Im Verzeichnis sollten nun die jeweiligen Dateien liegen. Insbesondere auf den privaten Key sollte man gut aufpassen, daher lohnt sich noch ein:

chmod 600 /etc/wireguard/privatekey

Im nächsten Schritt legen wir für jeden Server eine Konfigurationsdatei unter /etc/wireguard/wg0.conf an. Hier ist das Beispiel für den ersten Server defiant. Dieser soll mit allen anderen 3 Servern und meinem Raspberry-Pi reden können. Daher tragen wir die 4 Kommunikationspartner mit in die Datei ein. Das gleiche gilt dann jeweils für die anderen 3 Server auch, nur dass dort der jeweilige private Schlüssel und eine andere IP vergeben werden müssen.

In meinem Setup vergebe ich folgende IPs:

defiant10.0.0.1
discovery10.0.0.2
reliant10.0.0.3
yorktown10.0.0.4
pi10.0.0.10
IP-Addressen der Server

Der Rest der Datei ist selbsterklärend:

[Interface]
ListenPort = 51871
PrivateKey = <privater Schlüssel Server defiant>
Address = 10.0.0.1/32

PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
# pi 
PublicKey = <öffentlicher Schlüssel raspberrypi>
PresharedKey = <preshared key raspberrypi>
AllowedIPs = 10.0.0.10/32, 192.168.0.0/24

[Peer]
# Discovery 
PublicKey = <öffentlicher Schlüssel discovery>
PresharedKey = <preshared key discovery>
AllowedIPs = 10.0.0.2/32
Endpoint = <öffentliche IP discovery>:51871

[Peer]
# reliant 
PublicKey = <öffentlicher Schlüssel reliant>
PresharedKey = <preshared key reliant>
AllowedIPs = 10.0.0.3/32
Endpoint = <öffentliche IP reliant>:51871

[Peer]
#yorktown 
PublicKey = <öffentlicher Schlüssel yorktown>
PresharedKey = <preshared key yorktown>
AllowedIPs = 10.0.0.4/32
Endpoint = <öffentliche IP yorktown>:51871

Zur Erklärung:

  • ListenPort: Port (UDP) auf dem Wireguard hört
  • PrivateKey: privater Schlüssel
  • Adress: Die IP-Adresse des Servers für das wireguard-Interface
  • PostUp: mit den Befehlen aktiviert man das packet-forwarding auf dem wireguard interface
  • PostDown: Damit deaktiviert man es wieder

Für jeden Peer trägt man folgende Dinge ein:

  • PublicKey: Der öffentliche Schlüssel des Peers
  • PresharedKey: der preshared-key, den ihr für den jeweiligen Server erzeugt habt.
  • AllowedIPs: Das ist die IP des Partners
  • Endpoint: Die öffentliche IP-Adresse des Servers, auf der dann wireguard erreichbar ist.

Eine Besonderheit gibt es bei dem Eintrag für den RaspberryPI. Dort lasse ich neben der IP-Adresse 10.0.0.10 auch das Netz 192.168.0.0/24 zu. Dabei handelt es sich um mein Heimnetzwerk. Damit kann ich nachher die Geräte in meinem Heimnetz erreichen und vom Heimnetz aus die Server über Wireguard ansprechen.

Anschließend erlauben wir noch in der ufw-Firewall auf den Servern die Kommunikation über den UDP-Port 51871:

ufw allow 51871/udp

Mit dem Befehl wg-quick kann man wireguard starten.

wg-quick up wg0

Mit wg show sollten nun die Daten zum wireguard-Netzwerk aufgezeigt werden. Ebenfalls kann man mit ping die jeweiligen peers erreichen:

wg show

ping 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=3.59 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.729 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=1.34 ms
64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.787 ms

Wenn das alles zur Zufriedenheit funktioniert, sollte man den Dienst noch aktivieren, damit wireguard auch nach dem nächsten Serverneustart gestartet wird:

# aktivieren
systemctl enable wg-quick@wg0
# ggf. starten
systemctl start wg-quick@wg0

Ich erlaube in der Firewall noch alles, was über das Interface wg0 reinkommt, also alles aus meinem VPN:

ufw allow in on wg0

Wenn ihr euch sicher seid, dass ihr eure Server von eurem Client aus per SSH durch den wireguard-tunnel erreichen könnt, könnt ihr auch die OpenSSH-Regel aus der Firewall entfernen. Der Port muss ja nicht für das ganze Internet geöffnet sein. Wir prüfen das lokal mit:

ssh ronny@10.0.0.1

und entfernen dann die „alte“ OpenSSH Regel:

ufw delete allow OpenSSH

Nachdem nun die Kommunikation zwischen den Servern funktioniert, wollen wir im nächsten Teil Docker und Rancher installieren.

Kubernetes Workshop Teil 2: Einrichtung der Server

Wie bereits im ersten Teil angekündigt, geht es heute um die Einrichtung der Server. Wie gesagt, habe ich 4 kleine virtuelle Server bei Contabo bestellt. Die Server habe ich mit Ubuntu 18.04 LTS aufgesetzt. Die Server sollen unter meiner Domain erreichbar sein. Dazu muss ich im ersten Schritt die IP-Adressen der Server bei meinem Domain-Anbieter hinterlegen. Ich hoste meine Domains bei united-domains und lege nun DNS-Records sowohl für IPv4 als auch für IPv6 an. Die IPs könnt ihr bei Contabo im Kundenportal nachschlagen. Das sieht dann beispielsweise so aus:

Weiterhin lege ich einen CNAME-Eintrag an, der alle Sub-Domains auf einen der Server zeigen lässt:

Damit kann ich später alle Applikationen mit eigenen Sub-Domains app1.ronnywalter.de, app2.ronnywalter.de usw. versehen und muss nicht jede Sub-Domain einzeln pflegen. Um das Routing im Cluster kümmert sich Kubernetes.

Für den Aufruf der Rancher-Oberfläche konfiguriere ich noch einen CNAME-Eintrag, der auf den „kleinen“ Server (VPS-S) zeigt:

Nun loggen wir uns auf den Servern ein und konfigurieren sie ein wenig. Ich verwende auf dem Mac das kleine Tool csshX. Damit kann ich mich gleichzeitig auf allen Servern einloggen. Die eingegebenen Kommandos werden zeitgleich an alle Server geschickt. Sehr praktisch! Im ersten Schritt wird auf allen Servern das root-passwort geändert, dass euch Contabo geschickt hat. Ebenso lege ich einen User an.

csshx root@defiant.ronnywalter.de root@discovery.ronnywalter.de root@reliant.ronnywalter.de root@yorktown.ronnywalter.de
#Passwort für root ändern
passwd

#User "ronny" anlegen
useradd -m -g users -s /bin/bash ronny

#Passwort vergeben
passwd ronny

#IPv6 anktivieren (auf contabo Servern)
enable_ipv6

#Den User ronny in die sudo-group aufnehmen
gpasswd -a ronny sudo

Ich aktiviere auf gleich noch die ufw-firewall unter ubuntu und aktiviere SSH, da wir uns ja weiterhin per SSH verbinden wollen:

systemctl enable ufw
systemctl start ufw
ufw enable
ufw allow SSH

Dann setze ich auf jedem Server den gewünschten hostnamen, trage also den Namen in die /etc/hostname ein. Beispiel für den ersten Server:

echo "defiant" > /etc/hostname

Ich starte nun die Server neu.

reboot

In Zukunft möchte ich mich nur noch mit SSH-Key einloggen und will die Passwortauthentifizierung deaktivieren. Logins als root möchte ich komplett verbieten und bei der Gelegenheit den root-Account deaktivieren. Ich kann später ja alles per sudo erledigen.

Dazu erstellt man sich lokal einen SSH-Key mit ssh-keygen und kopiert den anschliessend auf alle Server.

# key erzeugen
ssh-keygen -t ed25519

# key auf den Server defiant kopieren
ssh-copy-id defiant.ronnywalter.de

# die anderen server
ssh-copy-id reliant.ronnywalter.de
ssh-copy-id discovery.ronnywalter.de
ssh-copy-id yorktown.ronnywalter.de

Jetzt testen wir mal die Verbindung per SSH und sollten uns ohne Passwort einloggen können. Anschließend testen wir, ob wir uns mit sudo zum root machen können.

csshx ronny@defiant.ronnywalter.de ronny@discovery.ronnywalter.de ronny@reliant.ronnywalter.de ronny@yorktown.ronnywalter.de
sudo -s

Wenn das alles klappt, schalten wir die Logins per Passwort und als Root ab. Dazu muss die Datei /etc/ssh/sshd_config editiert werden. Dort werden folgende Einträge geändert:

PermitRootLogin no
PasswordAuthentication no

Danach starten wir den SSH-Server neu und deaktivieren root

systemctl restart sshd
passwd -l root

Danach dürfte man sich nicht mehr als root einloggen können. Es gibt im Netz diverse Anleitungen, um Ubuntu-Server abzusichern. Dazu einfach mal nach „ubuntu hardening guide“ suchen. Ich werd sicher mal noch fail2ban installieren. Jetzt belass ich erstmal dabei.

Ich möchte unter Ubuntu 18.04 einen aktuellen Kernel betreiben. Dazu kann man den sogenannten HWE-Kernel installieren. Eine Beschreibung gibts hier. Wir installieren bei der Gelegenheit gleich mal noch ein paar Softwareupdates, falls verfügbar.

apt-get update
apt-get upgrade
apt-get install --install-recommends linux-generic-hwe-18.04
reboot

Im nächsten Teil wollen wir wireguard konfigurieren und die Kommunikation mit dem Heimnetzwerk einrichten.

Kubernetes Workshop Teil 1: Vorüberlegungen

Ich möchte mir einen kleinen Kubernetescluster aufbauen, um dort verschiedenste Applikationen zu deployen, die ich mehr oder weniger im Alltag nutzen möchte. Weiterhin möchte ich diverse Anwendungen aus dem Bereich der Softwareentwicklung installieren, um verschiedene Aspekte insbesondere aus dem Bereich CI/CD ausprobieren zu können. Anfangs denke ich hierbei an folgende Applikationen:

Weiterhin möchte ich CI/CD-Buildstrecken mit eben dieser Infrastruktur aufsetzen. Das werde ich mit kleinen Java-Beispielen ausprobieren.

Ziel soll sein, dass alle Applikationen mit Kubernetes-Mitteln bzw. Helm installiert werden können. Ich hoffe, dabei viel zu lernen.

Um den Kubernetes-Cluster aufzusetzen, möchte ich Rancher einsetzen. Ich möchte ebenfalls einen zentrales Logging (ElasticStack) und ein Monitoring installieren, vor allem um zu lernen, wie das geht.

Es gibt ja die Möglichkeit, sich mit Tools wie minikube einen eigenen kleinen Cluster für Experimente zu erzeugen. Ich wollte mir das Ganze aber auf „richigen“ Servern im Internet installieren. Dabei muss ich dann auch einige Sachen wie Firewall-Einstellungen berücksichtigen. Ebenso soll die Kommunikation zwischen den Servern und von meinem PC aus verschlüsselt erfolgen. Dazu habe ich mich etwas mit Wireguard beschäftigt.

In meinem Heimnetz steht eine Synology Diskstation. Diese hat die wunderbare Eigenschaft, dass man darauf auch Docker-Container starten kann. Das möchte ich nutzen, um dort u.a. einen kleinen Git-Server (gitea) und ein S3-Storage (minio) zu betreiben. In dieses S3-Storage soll mein Kubernetes Cluster z.B. Backups ablegen. Weiterhin habe ich einen Raspberry PI, den ich dazu nutzen möchte, eine VPN-Verbindung zwischen meinem lokalen Netz und den Servern herzustellen.

Das Ganze soll dann schematisch so aussehen:

Für mein Experiment nutze ich virtuelle Server von contabo (VPS), da diese relativ günstig sind. Experimente in der Cloud mit AWS EKS oder GKE werde ich später machen. Ich habe mir insgesamt 4 Maschinen bestellt:

  1. VPS S – Rancher Installation
  2. VPS L – Kubernetes Node 1 (Worker, etcd, controllpane)
  3. VPS M – Kubernetes Node 2 (Worker)
  4. VPS M – Kubernetes Node 3 (Worker)

Warum ausgerechnet 4 Server? Auf dem ersten kleinen Server soll die Rancher-Installation laufen. In Rancher wiederum soll ein Kubernetes-Cluster auf den anderen 3 Nodes angelegt werden. Damit habe ich auf dem Cluster genug RAM (ca. 60GB) und auch etwas CPU-Power (20 Cores) um einige Applikationen laufen lassen zu können. Das Ganze kostet mich im Monat ca. 38€. Das bin ich aktuell bereit auszugeben. 🙂

Wie das geübte Auge sieht, ist das kein Hochverfügbarkeits-Setup. Dafür bräuchte man einige Nodes mehr. Rancher selbst soll auch „nur“ als Single-Node installiert werden. Für meine Experimente reicht das soweit aber aus.

Im nächsten Teil wollen wir die 4 Server einrichten.