Eine übersichtliche Referenz der Architekturmuster, die in der CKA-Prüfung getestet werden. Von oben nach unten lesen oder zu einem Abschnitt springen.
Cluster-Architektur, Installation & Konfiguration
Anforderung zur Durchführung eines Disaster-Recovery-Backups des Cluster-Zustands.
Verwenden Sie `etcdctl snapshot save` mit den entsprechenden TLS-Zertifikaten (`--cacert`, `--cert`, `--key`) und dem Endpunkt.
Warum: etcd speichert den gesamten Cluster-Zustand. Direkte Snapshots sind die kanonische Methode zur Sicherung. In einem kubeadm-Cluster ist TLS aktiviert, daher sind Zertifikate für die Authentifizierung von `etcdctl` zwingend erforderlich.
Wiederherstellung eines Clusters aus einem Disaster-Recovery-Backup.
Verwenden Sie `etcdctl snapshot restore` in ein neues Datenverzeichnis. Aktualisieren Sie dann das statische Pod-Manifest `etcd.yaml`, um seinen `--data-dir`-Volume-Mount auf den neuen Speicherort zu verweisen und den kubelet neu zu starten.
Warum: Die Wiederherstellung erstellt ein neues Datenverzeichnis. Das statische Pod-Manifest muss aktualisiert werden, um diese neuen Daten zu verwenden, da etcd sonst mit dem alten (oder leeren) Datenverzeichnis gestartet wird.
Durchführung eines Versions-Upgrades für einen kubeadm-verwalteten Cluster.
1. Auf der Control Plane: `kubeadm` aktualisieren, `kubeadm upgrade plan` ausführen, dann `kubeadm upgrade apply`. 2. Auf jedem Worker-Node: `kubectl drain`, `kubelet` aktualisieren, kubelet-Dienst neu starten, `kubectl uncordon`.
Warum: Der Prozess ist mehrstufig und sequenziell. `kubeadm` aktualisiert nur Control Plane-Komponenten; `kubelet` muss auf jedem Node manuell aktualisiert werden. Das Draining von Nodes stellt sicher, dass Workloads vor der Wartung sicher entfernt werden.
Cluster-Zertifikate laufen ab und müssen überprüft oder erneuert werden.
Verwenden Sie `kubeadm certs check-expiration`, um Ablaufdaten anzuzeigen. Verwenden Sie `kubeadm certs renew all` (oder für bestimmte Komponenten), um sie zu erneuern. Starten Sie Control Plane Pods nach der Erneuerung neu.
Warum: Von Kubeadm generierte Zertifikate haben eine Gültigkeit von 1 Jahr. Die Erneuerung ist eine häufige Wartungsaufgabe. Control Plane-Komponenten müssen neu gestartet werden, um die neuen Zertifikate zu laden.
Eine Control Plane-Komponente (z. B. API server) muss konfiguriert oder neu gestartet werden.
Ändern Sie das Manifest der Komponente in `/etc/kubernetes/manifests/`. Der kubelet auf dem Node erkennt die Änderung automatisch und startet den Pod neu.
Warum: Control Plane-Komponenten in kubeadm werden als statische Pods ausgeführt, die direkt vom kubelet und nicht vom API server verwaltet werden. Die gesamte Verwaltung erfolgt über Manifest-Dateien im überwachten Verzeichnis.
Zugriffssteuerungen für Benutzer oder Anwendungen definieren.
Verwenden Sie eine `Role` und `RoleBinding` für Namespace-bezogene Berechtigungen. Verwenden Sie eine `ClusterRole` und `ClusterRoleBinding` für Cluster-weite Berechtigungen.
Warum: Dies ist die grundlegende Trennung in RBAC. Eine Role ist immer an einen Namespace gebunden, während eine ClusterRole Zugriff auf nicht-Namespace-bezogene Ressourcen (wie Nodes) oder auf Ressourcen über alle Namespaces hinweg gewähren kann.
Ein ServiceAccount muss auf Ressourcen über alle Namespaces hinweg zugreifen.
Erstellen Sie eine `ClusterRole`, die die Berechtigungen definiert. Erstellen Sie eine `ClusterRoleBinding`, um diese ClusterRole dem spezifischen `ServiceAccount` zu gewähren.
Warum: Obwohl ein ServiceAccount Namespace-bezogen ist, kann eine ClusterRoleBinding ihm Cluster-weite Berechtigungen gewähren. Eine `RoleBinding` würde die Berechtigungen nur innerhalb des eigenen Namespace der RoleBinding gewähren.
Dienste & Netzwerke
Eine Anwendung ohne Cloud Load Balancer externem Traffic zugänglich machen.
Verwenden Sie einen Service vom `type: NodePort`. Dieser macht den Service auf einem statischen Port (Standardbereich: 30000-32767) auf der IP-Adresse jedes Nodes zugänglich.
Warum: NodePort ist eine einfache Möglichkeit, externen Traffic in den Cluster zu leiten. Er ist kostengünstiger und plattformunabhängiger im Vergleich zu `type: LoadBalancer`, erfordert aber, dass Clients eine Node-IP kennen.
Mehrere HTTP/S-Dienste unter einer einzigen IP-Adresse mit Host- oder Pfad-basiertem Routing zugänglich machen.
Stellen Sie einen Ingress Controller bereit (z. B. NGINX). Erstellen Sie `Ingress`-Ressourcen, die Routing-Regeln von Hosts/Pfaden zu Backend-`Services` definieren.
Warum: Ingress ist die Standard-Kubernetes-Ressource für L7-Routing. Es erfordert einen separaten Controller, um die Routing-Logik tatsächlich zu implementieren. Dies entkoppelt Routing-Regeln von der Proxy-Implementierung.
Einen Namespace sichern, indem standardmäßig der gesamte Ingress-Traffic verweigert wird.
Erstellen Sie eine `NetworkPolicy`, die alle Pods auswählt (`podSelector: {}`) und eine leere Ingress-Regel angibt (`ingress: []`).
Warum: Sobald ein Pod von einer NetworkPolicy ausgewählt wird, wird der gesamte nicht explizit erlaubte Traffic verweigert. Eine Policy, die alle Pods mit einer leeren Ingress-Regel auswählt, erstellt effektiv eine "Alles verweigern"-Firewall für den Namespace.
Pods in einem "Frontend"-Namespace den Zugriff auf Pods in einem "Backend"-Namespace erlauben.
Erstellen Sie im "Backend"-Namespace eine NetworkPolicy. Verwenden Sie in der `ingress.from`-Regel einen `namespaceSelector`, um Labels auf der "Frontend"-`Namespace`-Ressource abzugleichen.
Warum: `podSelector` funktioniert nur innerhalb des Namespace der Policy. Um Traffic von anderen Namespaces zuzulassen, müssen Sie einen `namespaceSelector` verwenden. Dies erfordert das Labeling der `Namespace`-Objekte selbst.
Eine Anwendung muss sich mit einem anderen Dienst innerhalb des Clusters verbinden.
Verwenden Sie den internen DNS-Namen des Dienstes: `<service-name>.<namespace>.svc.cluster.local`. Wenn im selben Namespace, ist `<service-name>` ausreichend.
Warum: Kubernetes bietet über CoreDNS eine stabile DNS-basierte Service Discovery. Dies entkoppelt Anwendungen von spezifischen Pod-IPs, die kurzlebig sind.
Eine Stateful-Anwendung (z. B. ein Datenbank-Replica-Set) erfordert eine direkte Netzwerkidentität für jeden Pod.
Erstellen Sie einen Headless-`Service` (`clusterIP: None`) für das `StatefulSet`. Dies bietet einzigartige DNS A-Records für jeden Pod (z. B. `pod-0.my-service.my-ns...`).
Warum: Ein Headless Service verteilt die Last nicht. Stattdessen bietet er DNS-Einträge für jeden Pod, wodurch Clients sich mit spezifischen Instanzen verbinden können, was für Leader Election oder Peer Discovery in Stateful-Systemen entscheidend ist.
Ein nach außen gerichteter Dienst muss die ursprüngliche Client-IP-Adresse für Logging oder IP-basierte Filterung sehen.
Setzen Sie `externalTrafficPolicy: Local` für den `NodePort` oder `LoadBalancer` Service.
Warum: Die Standard-`Cluster`-Policy verschleiert die Client-IP über SNAT. `Local` vermeidet diesen zusätzlichen Netzwerk-Hop, indem der Traffic nur zu Pods auf dem Node geleitet wird, der den Traffic empfangen hat, wodurch die Quell-IP erhalten bleibt.
Workloads & Scheduling
Pods zur Leistungsoptimierung oder Hochverfügbarkeit zusammenlegen oder verteilen.
Verwenden Sie `podAffinity`, um Pods auf demselben Node/Zone wie andere spezifische Pods zu planen. Verwenden Sie `podAntiAffinity`, um zu vermeiden, dass sie zusammen geplant werden.
Warum: Dies bietet eine fortgeschrittenere Scheduling-Kontrolle als Node-Level-Affinität. Anti-Affinität mit `requiredDuringScheduling...` ist entscheidend für die Verteilung von Service-Replikaten über Nodes oder Zonen für HA.
Nodes bestimmten Workloads widmen oder verhindern, dass bestimmte Workloads darauf ausgeführt werden.
Wenden Sie einen `taint` auf einen Node an (z. B. `gpu=true:NoSchedule`). Fügen Sie eine passende `toleration` zu den Pods hinzu, die auf diesem Node ausgeführt werden dürfen.
Warum: Taints stoßen Pods ab, während Tolerations sie zulassen. Dies ist der primäre Mechanismus zur Widmung von Nodes. Der `NoExecute`-Effekt wird bereits laufende Pods, die die Toleration nicht haben, entfernen.
Einen Monitoring- oder Logging-Agent auf jedem Node im Cluster bereitstellen.
Verwenden Sie ein `DaemonSet`. Es stellt sicher, dass eine Kopie des Pods auf jedem Node läuft, der seinen Scheduling-Kriterien entspricht.
Warum: DaemonSet ist genau für diesen Zweck konzipiert. Es wird automatisch auf neuen Nodes bereitgestellt und handhabt das Pod-Management auf Node-Ebene, was mit einem Deployment schwierig wäre.
Eine einmalige Batch-Aufgabe oder eine wiederkehrende, geplante Aufgabe ausführen.
Verwenden Sie einen `Job` für eine Aufgabe, die einmal bis zum Abschluss läuft. Verwenden Sie einen `CronJob`, um Jobs nach einem sich wiederholenden Zeitplan zu erstellen (z. B. nächtliche Backups).
Warum: Jobs stellen sicher, dass Pods bis zu einer bestimmten Anzahl von Abschlüssen laufen. CronJobs sind ein übergeordneter Controller, der Jobs basierend auf einem Cron-Zeitplan verwaltet.
Eine Anwendung auf eine neue Version ohne Ausfallzeit aktualisieren.
Verwenden Sie ein `Deployment` mit der Standard-`RollingUpdate`-Strategie. Konfigurieren Sie `maxSurge` und `maxUnavailable`, um die Update-Geschwindigkeit und Verfügbarkeit zu steuern.
Warum: Rolling Updates ersetzen schrittweise alte Pods durch neue, wodurch die Verfügbarkeit des Dienstes gewährleistet wird. `maxUnavailable` garantiert eine Mindestanzahl laufender Pods, während `maxSurge` ein Überschreiten der gewünschten Replika-Anzahl ermöglicht, um den Rollout zu beschleunigen.
Sicherstellen, dass Pods garantierte Ressourcen erhalten und nicht übermäßige Ressourcen auf einem Node verbrauchen.
Legen Sie `resources.requests` (CPU/Speicher) fest, um ein Minimum für das Scheduling zu garantieren. Legen Sie `resources.limits` fest, um zu verhindern, dass ein Container eine bestimmte Menge überschreitet.
Warum: Requests werden vom Scheduler für die Platzierung verwendet und garantieren Ressourcen. Limits werden vom kubelet und der Container-Runtime durchgesetzt; das Überschreiten des Speicherlimits führt zu einem OOMKill.
Eine Stateful-Anwendung bereitstellen, die stabile, eindeutige Netzwerkidentifikatoren und persistenten Speicher pro Replika erfordert.
Verwenden Sie ein `StatefulSet` mit einem `volumeClaimTemplate`. Dies erstellt einen einzigartigen `PersistentVolumeClaim` für jeden Pod und stellt sicher, dass Daten bei einem Neustart an dieselbe Pod-Identität wieder angehängt werden.
Warum: StatefulSets bieten stabile Pod-Namen (z. B. `web-0`, `web-1`) und einen einzigartigen, persistenten PVC für jeden. Dies ist unerlässlich für Anwendungen, die auf stabile Identität und Speicher angewiesen sind.
Speicher
Persistenter Speicher für eine Anwendung bereitstellen, ohne Volumes vorab zu provisionieren.
Erstellen Sie eine `StorageClass`, die einen Storage Provisioner definiert. Erstellen Sie dann einen `PersistentVolumeClaim` (PVC), der Speicher von dieser Klasse anfordert. Ein `PersistentVolume` (PV) wird dynamisch provisioniert.
Warum: Dies entkoppelt Anwendungen von der zugrundeliegenden Speicherinfrastruktur. Entwickler fordern Speicher über PVCs an, und der Cluster-Administrator definiert, wie dieser Speicher über StorageClasses provisioniert wird.
Steuern, was mit einem persistenten Volume geschieht, nachdem dessen Claim gelöscht wurde.
Setzen Sie `persistentVolumeReclaimPolicy` auf dem PV oder der StorageClass. `Delete` löscht den zugrundeliegenden Speicher automatisch. `Retain` belässt das Volume und die Daten intakt und erfordert eine manuelle Bereinigung.
Warum: `Retain` ist die sicherste Option für Produktionsdaten, da es versehentlichen Datenverlust verhindert. `Delete` ist praktisch für kurzlebige oder Entwicklungsumgebungen. Der Standard hängt vom Provisioner ab.
Definieren, wie ein Volume von Pods gemountet werden kann.
Verwenden Sie `accessModes`: `ReadWriteOnce` (RWO) für Single-Node-Lese-/Schreibzugriff, `ReadOnlyMany` (ROX) für Multi-Node-Lesezugriff, `ReadWriteMany` (RWX) für Multi-Node-Lese-/Schreibzugriff.
Warum: Der Zugriffsmodus muss vom zugrundeliegenden Storage-Provider unterstützt werden. Eine Nichtübereinstimmung zwischen Anwendungsanforderungen (z. B. RWX benötigend) und Speicherfunktionen (nur RWO unterstützend) ist eine häufige Ursache für Pending PVCs.
Konfigurationsdateien oder sensible Daten in einen Pod injizieren.
Mounten Sie eine `ConfigMap` oder ein `Secret` als Volume. Jeder Schlüssel im Datenobjekt wird zu einer Datei im Mount-Pfad.
Warum: Dies ist die Standardmethode zur Bereitstellung von Konfigurationen für Pods. Es ermöglicht, Konfigurationen als Kubernetes-Objekte zu verwalten und unabhängig vom Pod-Image zu aktualisieren.
Eine Anwendung benötigt mehr Speicherplatz in ihrem bestehenden persistenten Volume.
Stellen Sie sicher, dass die `StorageClass` `allowVolumeExpansion: true` hat. Bearbeiten Sie den `PVC`, um eine größere Größe in `spec.resources.requests.storage` anzufordern.
Warum: Volume-Expansion ist eine Opt-in-Funktion. Die StorageClass muss dies explizit erlauben, und der zugrundeliegende CSI driver muss es unterstützen. Der Pod muss möglicherweise neu gestartet werden, damit das Dateisystem in der Größe angepasst wird.
Fehlerbehebung
Ein Pod hängt im `Pending`-Status fest und wird nicht geplant.
Führen Sie `kubectl describe pod <pod-name>` aus. Überprüfen Sie den Abschnitt `Events` auf Meldungen vom Scheduler.
Warum: Der `describe`-Befehl ist das primäre Werkzeug dafür. Er zeigt Gründe wie "Insufficient cpu/memory", "node(s) had taints the pod didn't tolerate" oder "didn't match node selector".
Ein Pod startet und schlägt wiederholt fehl, mit dem Status `CrashLoopBackOff`.
1. `kubectl logs <pod-name> --previous`, um die Logs des abgestürzten Containers zu sehen. 2. `kubectl describe pod <pod-name>`, um den Exit-Code und den Grund zu überprüfen.
Warum: `CrashLoopBackOff` bedeutet, dass die Anwendung im Container beendet wird. Die Logs der vorherigen Instanz (`--previous`) sind entscheidend, da der aktuelle Container möglicherweise noch nichts Nützliches protokolliert hat. Der Exit-Code kann auch die Art des Fehlers anzeigen.
Ein Pod startet nicht mit dem Status `ImagePullBackOff` oder `ErrImagePull`.
`kubectl describe pod <pod-name>`, um die Ereignismeldung zu sehen. Überprüfen Sie, ob der Image-Name und das Tag korrekt sind. Bei privaten Registries stellen Sie sicher, dass ein `imagePullSecrets` konfiguriert und das Secret gültig ist.
Warum: Dies ist ein Problem mit der Registry oder dem Image-Namen, nicht ein Anwendungsproblem. Häufige Ursachen sind Tippfehler, falsche Tags oder Authentifizierungsfehler bei einer privaten Registry.
Ein Node hat den Status `NotReady`.
Stellen Sie eine SSH-Verbindung zum betroffenen Node her. Überprüfen Sie den kubelet-Dienststatus mit `systemctl status kubelet`. Zeigen Sie dessen Logs mit `journalctl -u kubelet` an.
Warum: Der `kubelet` ist der Agent, der für die Meldung des Node-Zustands verantwortlich ist. Wenn er ausgefallen ist oder nicht mit dem API server kommunizieren kann, wird der Node als NotReady markiert. Seine Logs sind der erste Ort, an dem nachgesehen werden sollte.
Ein Service existiert, aber der Traffic erreicht die Backend-Pods nicht.
1. `kubectl describe svc <service-name>` und überprüfen Sie, ob der `Selector` mit den Pod-Labels übereinstimmt. 2. `kubectl get endpoints <service-name>` und stellen Sie sicher, dass die korrekten Pod-IPs aufgeführt sind. Falls nicht, sind die Labels falsch zugeordnet.
Warum: Die Verbindung zwischen einem Service und seinen Pods ist der Label-Selektor. Wenn der Selektor falsch ist oder die Pods nicht die richtigen Labels haben, ist das Endpoints-Objekt leer, und der Service hat keinen Ort, an den er Traffic routen kann.
Pods können Dienstnamen oder externe Hostnamen nicht auflösen.
1. Überprüfen Sie, ob CoreDNS-Pods in `kube-system` laufen. 2. Überprüfen Sie die CoreDNS-Logs. 3. Führen Sie einen Debug-Pod (z. B. `busybox`) aus und verwenden Sie `nslookup`, um die Auflösung innerhalb des Clusters zu testen.
Warum: DNS ist eine kritische Cluster-Abhängigkeit. Fehler gehen normalerweise auf die CoreDNS-Bereitstellung selbst, ihre Konfiguration (in einer ConfigMap) oder Netzwerk-Policies zurück, die DNS-Traffic auf UDP/TCP Port 53 blockieren.
Ein Node muss für Wartungsarbeiten offline genommen werden.
Zuerst `kubectl cordon <node-name>`, um ihn als nicht planbar zu markieren. Dann `kubectl drain <node-name> --ignore-daemonsets`, um alle Benutzer-Pods sicher zu entfernen.
Warum: `cordon` verhindert, dass neue Pods geplant werden. `drain` respektiert PodDisruptionBudgets und entfernt Pods graceful. `--ignore-daemonsets` wird benötigt, weil DaemonSet-Pods nicht entfernt werden können.
Identifizieren, welche Pods oder Nodes die meiste CPU oder den meisten Speicher verbrauchen.
Verwenden Sie `kubectl top pods` und `kubectl top nodes`. Dies erfordert, dass der `metrics-server` im Cluster bereitgestellt ist.
Warum: `kubectl top` bietet eine schnelle Echtzeitansicht des Ressourcenverbrauchs, unerlässlich zur Identifizierung ressourcenhungriger Anwendungen oder Node-Ressourcenengpässe.
Ein Pod befindet sich seit langem im `Terminating`-Status und wird nicht entfernt.
Löschen Sie den Pod zwangsweise mit `kubectl delete pod <pod-name> --grace-period=0 --force`.
Warum: Dies kann passieren, wenn ein Finalizer festhängt oder der kubelet Ressourcen nicht bereinigen kann. Das erzwungene Löschen entfernt den Pod sofort vom API server, sollte aber als letztes Mittel eingesetzt werden, da es verwaiste Ressourcen auf dem Node hinterlassen kann.