Kubernetes via Ansible auf dem Raspberry Cluster
Unser Raspberry Cluster ist erwachsen geworden. In einem vorherigen Blogpost wurde bereits gezeigt wie ein k3s Cluster erfolgreich aufgesetzt und verwendet wurde. Dieser Cluster wurde nun durch einen vollwertiges k8s Kluster ersetzt. Wichtiger Bestandteil dabei war es, die Installation und das Konfigurieren möglichst einfach zu halten. Hier kommt Ansible ins Spiel, auf das im folgendem Blogbeitrag näher eingegangen wird.
Cluster Aufbau
Die Grundlage besteht weiterhin aus drei Raspberry 4 (4GB). Der Cluster selbst wird mit kubeadm aufgesetzt und konfiguriert. Für das cluster networking wird calico verwendet. Um auch persistenten Speicher in einem Pod zur Verfügung zu stellen wird OpenEBS verwendet. Um Services auch von außerhalb des Clusters (im Büro Netzwerk) erreichen zu können wird metallb verwendet.
Ansible
Ansible ermöglicht es Konfigurationen und Aufgaben in so genannten Playbooks mittels Tasks via YAML zu definieren. Das alles kann somit in einem Git Repository abgelegt werden und dient auch gleichzeitig der Dokumentation. Die Playbooks werden dann noch in „Roles“ aufgeteilt um eine bessere Übersicht zu behalten und um Teile davon auch wiederverwenden zu können. Beispielsweise gibt es eine Role „general“ für das Vorbereiten des Host Betriebssystems und eine Role „k8s“ für das installieren des Clusters. Die Role „general“ wird nicht nur für die Raspberries sondern auch bei jedem anderen Server verwendet um zum Beispiel den Time-Server zu setzen, root ssh login auszuschalten, Hostnamen zu setzen etc.
Vorteile
- Einfache Herstellung eines gewünschten Zustands: Der größte Vorteil von Ansible ist die einfache Ausführung und Wiederherstellung eines gewünschten Zustandes. Sollte einmal etwas schief gehen beim Testen und Ausprobieren dauert es nur wenige Minuten bis der Cluster vollständig wieder neu erstellt und im ursprünglichen Zustand ist.
- Zeitersparnis: Das automatische Ausrollen ist im Vergleich zum manuellen Aufsetzen und Konfigurieren eine enorme Zeitersparnis.
- Konfiguration in Git: Auch die Zusammenarbeit bei der Konfiguration und Weiterentwicklung der Infrastruktur und Services ist durch die Verwendung von Git einfach und in einem gewohnten Umfeld für Software Entwickler.
- Parallele Ausführung: Ansible ermöglicht es im Vergleich zu bash Scripten Aufgaben auf einer Vielzahl von Host-Systemen gleichzeitig auszuführen.
Nachteile
- Initialer Aufwand: Der initiale Aufwand zur Erstellung des Playbooks ist etwas größer, allerdings ist dies zu vernachlässigen da auf lange Sicht wieder einiges an Zeit gespart wird.
- Lernkurve: Ein gewisses Ansible Know-How sollte vorhanden sein um komplexe Aufgaben abbilden zu können.
Task Beispiele:
- Erstellt ein Verzeichnis im angegeben Pfad
- name: Create general backup directory
file:
path: "/data/backup"
state: directory
- Führt einen Befehl aus um die Zeitzone zu setzen.
{{ general_timezone }}
ist eine Variable die in einem separatem File konfiguriert werden kann.
- name: Set timezone
command: "timedatectl set-timezone {{ general_timezone }}"
become: true
- Installiert alle notwendig Kubernetes Pakete via
apt
- name: Install Kubernetes binaries
apt:
name: "{{ packages }}"
state: present
update_cache: yes
vars:
packages:
- kubelet
- kubeadm
- kubectl
become: true
- Initialisiert Kubernetes control plane auf dem Raspberry Master Knoten
- name: Initialize the Kubernetes cluster using kubeadm
command:
cmd: >
kubeadm init --apiserver-advertise-address="{{ k8s_node_ip }}"
--apiserver-cert-extra-sans="{{ k8s_node_ip }}"
--node-name {{ general_hostname }}
--pod-network-cidr={{ k8s_network_pod_cidr }}
creates: /etc/kubernetes/admin.conf
become: true
when: k8s_node_type == "master"
Anwendungsbereich
Der Cluster wird dazu verwendet um sich näher mit Kubernetes auseinander zu setzen. Weiters werden Deployments von verschiedenen Anwendungen getestet und auch als Test-Umgebung für die eigene Software verwendet.
Beispiel Deployment
Hier gibt es noch ein kleines Beispiel eines Nginx Webservers der auf dem Raspberry Cluster deployed werden kann.
Es werden 2 Pods erstellt, auf die die Anfragen aufgeteilt werden. Der Metallb Loadbalancer weist dem Service eine externe IP zu um sie aus dem lokalen Büronetz aus erreichen zu können.
apiVersion: v1
kind: Service
metadata:
name: test-app
labels:
app.kubernetes.io/name: test-app
app.kubernetes.io/component: webserver
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app.kubernetes.io/name: test-app
app.kubernetes.io/component: webserver
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-app
labels:
app.kubernetes.io/name: test-app
app.kubernetes.io/component: webserver
spec:
selector:
matchLabels:
app.kubernetes.io/name: test-app
app.kubernetes.io/component: webserver
replicas: 2
template:
metadata:
labels:
app.kubernetes.io/name: test-app
app.kubernetes.io/component: webserver
spec:
containers:
- name: test-app
image: nginx:latest
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 80
Die folgenden Screenshots zeigen den laufenden Nginx im Cluster.

Auflistung der pods die durch das deployment erstellt wurden.

Externe (Büro Netzwerk) IP Adresse um auf das Service zugreifen zu können

Default Testseite von nginx
So weit, so gut. Die nächsten Schritte:
- Externe SSDs für die Raspberries um etwas mehr Funktionen von OpenEBS nutzen zu können
- external-dns installieren um anstatt der IP Adressen auch automatisch via Domains auf Services zugreifen zu können