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 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.