Kubernetes ist zum Industriestandard fuer Container-Orchestrierung geworden und betreibt alles von kleinen Startups bis zu den groessten Cloud-nativen Plattformen der Welt. Wenn Sie Container mit Docker oder Docker Compose verwalten und den Punkt erreicht haben, an dem Sie automatische Skalierung, Selbstheilung, Rolling Updates und Multi-Node-Deployments benoetigen, ist Kubernetes der naechste Schritt. Diese Anleitung fuehrt Sie von Null zu einem funktionierenden Kubernetes-Cluster mit kubeadm auf Ubuntu Server und deckt die Architektur, Installation, erstes Deployment, Service-Exponierung und taegliche Verwaltungsbefehle ab.
Voraussetzungen
Bevor Sie beginnen, stellen Sie sicher, dass Sie haben:
- Zwei oder mehr Maschinen mit Ubuntu Server 22.04 oder 24.04 (physisch oder virtuell)
- Jede Maschine mit mindestens 2 GB RAM und 2 CPUs
- Vollstaendige Netzwerkkonnektivitaet zwischen allen Maschinen (privates Netzwerk empfohlen)
- Eindeutigen Hostnamen, MAC-Adresse und product_uuid auf jedem Knoten
- Terminalzugang mit sudo-Rechten auf allen Knoten
- Swap deaktiviert auf allen Knoten
Was ist Kubernetes?
Kubernetes (oft als k8s abgekuerzt) ist eine Open-Source-Container-Orchestrierungsplattform, die urspruenglich von Google entwickelt wurde und jetzt von der Cloud Native Computing Foundation (CNCF) gepflegt wird. Sie automatisiert das Deployment, die Skalierung und die Verwaltung von containerisierten Anwendungen.
Im Kern loest Kubernetes ein fundamentales Problem: Wenn Sie Dutzende oder Hunderte von Containern auf mehreren Servern ausfuehren, benoetigen Sie ein System, das entscheidet, wo jeder Container laeuft, Container neu startet, die ausfallen, sie basierend auf der Nachfrage hoch- oder herunterskaliert und das Netzwerk zwischen ihnen verwaltet. Kubernetes macht all dies deklarativ — Sie beschreiben den gewuenschten Zustand Ihrer Anwendung, und Kubernetes arbeitet kontinuierlich daran, den tatsaechlichen Zustand entsprechend anzupassen.
Schluesselkonzepte:
- Pod — die kleinste deploybare Einheit, die einen oder mehrere Container umschliesst
- Service — ein stabiler Netzwerk-Endpunkt, der Datenverkehr an eine Gruppe von Pods weiterleitet
- Deployment — eine deklarative Art, Pods mit Replikas und Rolling Updates zu verwalten
- Namespace — eine logische Partition zur Isolation von Ressourcen innerhalb eines Clusters
- Node — eine physische oder virtuelle Maschine im Cluster
Kubernetes-Architektur
Ein Kubernetes-Cluster besteht aus zwei Arten von Knoten:
Control Plane (Master-Knoten)
Die Control Plane verwaltet den gesamten Cluster-Zustand und trifft Scheduling-Entscheidungen. Ihre Komponenten umfassen:
- kube-apiserver — das Eingangstor zum Cluster; alle Kommunikation laeuft ueber den API-Server
- etcd — ein verteilter Key-Value-Speicher, der die gesamte Cluster-Konfiguration und den Zustand enthaelt
- kube-scheduler — weist Pods basierend auf Ressourcenanforderungen und Einschraenkungen Knoten zu
- kube-controller-manager — fuehrt Controller aus, die Routineaufgaben wie die Aufrechterhaltung der korrekten Anzahl von Pod-Replikas uebernehmen
- cloud-controller-manager — integriert sich mit Cloud-Provider-APIs (optional, fuer Cloud-Deployments)
Worker-Knoten
Worker-Knoten fuehren Ihre Anwendungscontainer aus. Jeder Worker fuehrt aus:
- kubelet — der Agent, der mit der Control Plane kommuniziert und Pods auf dem Knoten verwaltet
- kube-proxy — verwaltet Netzwerkregeln, damit Pods miteinander und mit externem Datenverkehr kommunizieren koennen
- Container-Runtime — die Software, die Container tatsaechlich ausfuehrt (containerd ist der Standard)
┌─────────────────────────────────────────┐
│ Control-Plane-Knoten │
│ ┌───────────┐ ┌──────────────────┐ │
│ │ API Server│ │ Controller Mgr │ │
│ └───────────┘ └──────────────────┘ │
│ ┌───────────┐ ┌──────────────────┐ │
│ │ etcd │ │ Scheduler │ │
│ └───────────┘ └──────────────────┘ │
└─────────────────────────────────────────┘
│ │
┌────┴────┐ ┌───┴─────┐
│ Worker 1│ │ Worker 2│
│ kubelet │ │ kubelet │
│ kube- │ │ kube- │
│ proxy │ │ proxy │
│ runtime │ │ runtime │
└─────────┘ └─────────┘
Vorbereitung Aller Knoten
Die folgenden Schritte muessen auf jedem Knoten im Cluster durchgefuehrt werden (Control Plane und Workers gleichermassen).
Swap Deaktivieren
Kubernetes erfordert, dass Swap deaktiviert ist. Der kubelet startet nicht, wenn Swap aktiv ist:
# Swap sofort deaktivieren
sudo swapoff -a
# Swap-Eintraege aus fstab entfernen, um ueber Neustarts hinweg zu persistieren
sudo sed -i '/ swap / s/^/#/' /etc/fstab
# Ueberpruefen, dass Swap deaktiviert ist
free -h
Erforderliche Kernel-Module Laden
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
sysctl-Parameter Konfigurieren
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# Ohne Neustart anwenden
sudo sysctl --system
Ueberpruefen Sie, dass die Einstellungen angewendet wurden:
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
Alle drei Werte sollten 1 zurueckgeben.
Installation der Container-Runtime (containerd)
Kubernetes benoetigt eine Container-Runtime, die das Container Runtime Interface (CRI) implementiert. containerd ist der Industriestandard und die empfohlene Wahl:
# containerd installieren
sudo apt update
sudo apt install -y containerd
# Standardkonfiguration generieren
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
# SystemdCgroup aktivieren (erforderlich fuer kubeadm)
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
# containerd neu starten und aktivieren
sudo systemctl restart containerd
sudo systemctl enable containerd
Ueberpruefen Sie, dass containerd laeuft:
sudo systemctl status containerd
Die Ausgabe sollte active (running) anzeigen.
Installation von kubeadm, kubelet und kubectl
Diese drei Tools sind die Grundlage eines kubeadm-basierten Clusters:
- kubeadm — bootstrappt den Cluster
- kubelet — laeuft auf jedem Knoten und verwaltet Pods
- kubectl — das Kommandozeilen-Tool zur Interaktion mit dem Cluster
# Erforderliche Pakete installieren
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gpg
# Signaturschluessel des Kubernetes-APT-Repositorys hinzufuegen
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# Kubernetes-APT-Repository hinzufuegen
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
# Pakete installieren
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
# Automatische Upgrades verhindern (kritisch fuer Cluster-Stabilitaet)
sudo apt-mark hold kubelet kubeadm kubectl
Ueberpruefen Sie die Installation:
kubeadm version
kubectl version --client
Initialisierung der Control Plane
Fuehren Sie den folgenden Befehl nur auf dem Control-Plane-Knoten aus:
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
Das Flag --pod-network-cidr gibt den IP-Bereich fuer Pods an. Der Wert 10.244.0.0/16 ist der Standard fuer Flannel. Wenn Sie Calico verwenden moechten, verwenden Sie stattdessen 192.168.0.0/16.
Nach Abschluss der Initialisierung sehen Sie eine Ausgabe aehnlich wie:
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.1.100:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:abc123...
Speichern Sie den Befehl kubeadm join — Sie benoetigen ihn, um Worker-Knoten hinzuzufuegen.
Konfigurieren Sie kubectl fuer Ihren Benutzer:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Ueberpruefen Sie, dass die Control Plane laeuft:
kubectl get nodes
Die Ausgabe zeigt den Control-Plane-Knoten mit dem Status NotReady — dies ist erwartet, bis Sie ein Pod-Netzwerk-Add-on installieren.
Installation eines Pod-Netzwerk-Add-ons
Pods benoetigen ein Netzwerk-Plugin (CNI — Container Network Interface), um ueber Knoten hinweg miteinander zu kommunizieren. Ohne dieses ist der Cluster nicht funktionsfaehig.
Option A: Flannel Installieren
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
Option B: Calico Installieren
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml
Warten Sie, bis alle System-Pods bereit sind:
kubectl get pods -n kube-system
Nach ein bis zwei Minuten sollten alle Pods den Status Running anzeigen. Ueberpruefen Sie nun den Knotenstatus erneut:
kubectl get nodes
Der Control-Plane-Knoten sollte nun Ready anzeigen.
Worker-Knoten Beitreten Lassen
Fuehren Sie auf jedem Worker-Knoten den Befehl kubeadm join aus, den Sie bei der Initialisierung der Control Plane gespeichert haben:
sudo kubeadm join 192.168.1.100:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:abc123...
Wenn Sie den Join-Befehl verloren haben, koennen Sie ihn auf der Control Plane regenerieren:
kubeadm token create --print-join-command
Nach dem Beitritt ueberpruefen Sie alle Knoten von der Control Plane aus:
kubectl get nodes
Erwartete Ausgabe:
NAME STATUS ROLES AGE VERSION
control-plane Ready control-plane 10m v1.31.0
worker-01 Ready <none> 2m v1.31.0
worker-02 Ready <none> 1m v1.31.0
Um Ihre Worker-Knoten fuer bessere Identifikation zu labeln:
kubectl label node worker-01 node-role.kubernetes.io/worker=worker
kubectl label node worker-02 node-role.kubernetes.io/worker=worker
Ihre Erste Anwendung Deployen
Jetzt, da der Cluster laeuft, deployen wir einen einfachen nginx-Webserver.
Ein Deployment Erstellen
kubectl create deployment nginx --image=nginx:latest --replicas=3
Dies sagt Kubernetes: “Ich moechte 3 Instanzen von nginx jederzeit laufend haben.” Kubernetes wird Pods ueber Ihre Worker-Knoten verteilen.
Ueberpruefen Sie das Deployment:
kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 3/3 3 3 30s
Einzelne Pods anzeigen:
kubectl get pods -o wide
Das Flag -o wide zeigt, auf welchem Knoten jeder Pod laeuft.
Ein YAML-Manifest Verwenden
Fuer Produktions-Workloads sollten Sie Ressourcen in YAML-Dateien definieren. Erstellen Sie eine Datei namens nginx-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
Anwenden:
kubectl apply -f nginx-deployment.yaml
Services Exponieren
Pods sind ephemer und erhalten neue IP-Adressen, wenn sie neu starten. Services bieten einen stabilen Endpunkt, um Ihre Anwendung zu erreichen.
ClusterIP (Nur Intern)
Der Standard-Service-Typ. Nur von innerhalb des Clusters erreichbar:
kubectl expose deployment nginx-deployment --port=80 --target-port=80 --type=ClusterIP
kubectl get services
NodePort (Externer Zugang ueber Knoten-IP)
Exponiert den Service auf einem statischen Port auf der IP jedes Knotens:
kubectl expose deployment nginx-deployment --port=80 --target-port=80 --type=NodePort --name=nginx-nodeport
kubectl get services nginx-nodeport
Sie koennen nun auf die Anwendung unter http://<beliebige-knoten-ip>:31234 zugreifen.
LoadBalancer (Cloud-Umgebungen)
In Cloud-Umgebungen (AWS, GCP, Azure) provisioniert der LoadBalancer-Typ automatisch einen externen Load Balancer:
kubectl expose deployment nginx-deployment --port=80 --target-port=80 --type=LoadBalancer --name=nginx-lb
Fuer Bare-Metal-Cluster koennen Sie MetalLB verwenden, um LoadBalancer-Funktionalitaet bereitzustellen.
Service-YAML-Manifest
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30080
type: NodePort
Skalierung und Rolling Updates
Replikas Skalieren
# Auf 5 Replikas hochskalieren
kubectl scale deployment nginx-deployment --replicas=5
# Auf 2 Replikas herunterskalieren
kubectl scale deployment nginx-deployment --replicas=2
# Ueberpruefen
kubectl get deployment nginx-deployment
Rolling Updates
Container-Image ohne Ausfallzeit aktualisieren:
# Image aktualisieren
kubectl set image deployment/nginx-deployment nginx=nginx:1.27-alpine
# Rollout-Fortschritt beobachten
kubectl rollout status deployment/nginx-deployment
Kubernetes wird alte Pods schrittweise durch neue ersetzen und sicherstellen, dass die Anwendung waehrend des gesamten Updates verfuegbar bleibt.
Rollback
Wenn etwas schiefgeht:
# Rollout-Verlauf anzeigen
kubectl rollout history deployment/nginx-deployment
# Zur vorherigen Version zurueckrollen
kubectl rollout undo deployment/nginx-deployment
# Zu einer bestimmten Revision zurueckrollen
kubectl rollout undo deployment/nginx-deployment --to-revision=2
Inspektion und Debugging von Workloads
Pod-Logs Anzeigen
# Logs eines bestimmten Pods
kubectl logs nginx-deployment-abc123
# Logs in Echtzeit verfolgen
kubectl logs -f nginx-deployment-abc123
# Logs aller Pods in einem Deployment
kubectl logs -l app=nginx
Befehle in einem Pod Ausfuehren
# Eine Shell in einem laufenden Pod oeffnen
kubectl exec -it nginx-deployment-abc123 -- /bin/bash
# Einen einzelnen Befehl ausfuehren
kubectl exec nginx-deployment-abc123 -- cat /etc/nginx/nginx.conf
Ressourcen Beschreiben
# Detaillierte Informationen ueber einen Pod
kubectl describe pod nginx-deployment-abc123
# Detaillierte Informationen ueber einen Knoten
kubectl describe node worker-01
Fehlerbehebung
Pods Stecken im Pending-Zustand
Dies bedeutet typischerweise, dass der Scheduler keinen Knoten mit ausreichenden Ressourcen finden kann:
kubectl describe pod <pod-name>
Schauen Sie sich den Abschnitt Events am Ende an. Haeufige Ursachen:
- Unzureichende CPU oder Speicher auf Worker-Knoten
- Knoten-Taints verhindern das Scheduling
- Pod-Affinitaetsregeln, die nicht erfuellt werden koennen
Pods in CrashLoopBackOff
Der Container startet, beendet sich aber sofort:
# Logs ueberpruefen
kubectl logs <pod-name>
kubectl logs <pod-name> --previous
# Events ueberpruefen
kubectl describe pod <pod-name>
Haeufige Ursachen:
- Anwendungsfehler oder Fehlkonfiguration
- Fehlende Umgebungsvariablen oder ConfigMaps
- Fehlschlagende Readiness- oder Liveness-Probes
Knoten Zeigen NotReady
# Knotenbedingungen ueberpruefen
kubectl describe node <knoten-name>
# Auf dem betroffenen Knoten kubelet-Logs ueberpruefen
sudo journalctl -u kubelet -f
Haeufige Ursachen:
- CNI-Plugin nicht installiert oder abstuerzt
- kubelet kann den API-Server nicht erreichen
- Festplattendruck, Speicherdruck oder PID-Druck
Services Nicht Erreichbar
# Service-Endpoints ueberpruefen
kubectl get endpoints <service-name>
# Konnektivitaet von innerhalb des Clusters testen
kubectl run debug --image=busybox --rm -it -- wget -qO- http://<service-name>
Join-Tokens Regenerieren
Wenn der Join-Token abgelaufen ist (Tokens sind standardmaessig 24 Stunden gueltig):
kubeadm token create --print-join-command
kubectl-Befehlsreferenz
| Befehl | Beschreibung |
|---|---|
kubectl get nodes | Alle Knoten im Cluster auflisten |
kubectl get pods | Pods im aktuellen Namespace auflisten |
kubectl get pods -A | Pods in allen Namespaces auflisten |
kubectl get services | Alle Services auflisten |
kubectl get deployments | Alle Deployments auflisten |
kubectl describe pod <name> | Detaillierte Pod-Informationen anzeigen |
kubectl logs <pod> | Pod-Logs anzeigen |
kubectl exec -it <pod> -- /bin/bash | Shell in einem Pod oeffnen |
kubectl apply -f <datei> | Ein YAML-Manifest anwenden |
kubectl delete -f <datei> | Ressourcen aus einem YAML-Manifest loeschen |
kubectl scale deployment <name> --replicas=N | Ein Deployment skalieren |
kubectl rollout status deployment/<name> | Rollout-Fortschritt ueberpruefen |
kubectl rollout undo deployment/<name> | Ein Deployment zurueckrollen |
kubectl top nodes | Ressourcennutzung der Knoten anzeigen |
kubectl top pods | Ressourcennutzung der Pods anzeigen |
kubectl config get-contexts | Verfuegbare Cluster-Kontexte auflisten |
kubectl cluster-info | Cluster-Endpunkt-Informationen anzeigen |
Zusammenfassung
Sie haben nun einen funktionierenden Kubernetes-Cluster mit kubeadm deployed, komplett mit einer Control Plane, Worker-Knoten, einem CNI-Netzwerk-Plugin und Ihrer ersten Anwendung, die mit exponierten Services laeuft. Dies ist die gleiche grundlegende Architektur, die in Kubernetes-Produktionsumgebungen weltweit verwendet wird.
Wichtige Erkenntnisse:
- Kubernetes orchestriert Container ueber mehrere Knoten mit automatisiertem Scheduling, Skalierung und Selbstheilung
- Die Control Plane (API Server, etcd, Scheduler, Controller Manager) verwaltet den Cluster-Zustand, waehrend Worker-Knoten Ihre Workloads ausfuehren
- kubeadm ist das offizielle Tool zum Bootstrappen von Produktions-Clustern
- Deployments bieten deklarative Verwaltung von Pods mit Rolling Updates und Rollbacks
- Services (ClusterIP, NodePort, LoadBalancer) geben Pods stabile Netzwerk-Endpunkte
- Verwenden Sie immer YAML-Manifeste fuer Produktions-Workloads, um Versionskontrolle und Reproduzierbarkeit zu ermoeglichen
Fuer Container-Grundlagen, die diese Anleitung ergaenzen, lesen Sie unsere Tutorials zu Docker auf Ubuntu Installieren und Docker Compose: Praktischer Leitfaden fuer Systemadministratoren.