Musterlösung: Kubernetes-Prüfung 01 – Fundamentals
Schwierigkeitsgrad: Fundamentals
Sprache: Deutsch
Typ: Musterlösung / Erwartungshorizont
Diese Datei ist eine passende Lösung zur Prüfung
01-fundamentals-kubernetes-pruefung-DE.md.
Die Befehle und Manifeste sind für einen Lab-Cluster gedacht. Verwende keine produktiven Cluster-Kontexte und keine echten Zugangsdaten.
1. Hinweise zur Verwendung
Diese Musterlösung zeigt eine vollständige, nachvollziehbare Fundamentals-Abgabe. Konkrete Ausgaben wie Pod-Namen, Clustername, Node-Namen, IP-Adressen und Kubernetes-Versionen sind im echten Lab anders. Entscheidend ist, dass die Kandidatin oder der Kandidat:
- im Namespace
exam-fundamentalsarbeitet, - die Ressourcen als YAML-Manifeste abgibt,
- den Rollout und den Service über
kubectlvalidiert, - keine echten Secrets verwendet,
- Fehlerbilder methodisch mit Status, Events, Logs und Endpoints untersucht.
Empfohlene Arbeitsvariable:
export NS=exam-fundamentals
2. Teil A: Musterantworten Wissensfragen
1. Zweck von Kubernetes und deklarativer gewünschter Zustand
Kubernetes ist eine Plattform zur deklarativen Orchestrierung containerisierter Anwendungen. Man beschreibt in Ressourcen wie Deployments, Services, ConfigMaps oder Secrets den gewünschten Zustand. Kubernetes speichert diesen Zustand über den API Server und Controller vergleichen ihn kontinuierlich mit dem aktuellen Zustand. Abweichungen werden durch Reconciliation korrigiert, zum Beispiel indem ein fehlender Pod neu erstellt wird.
Validierung:
kubectl get deployment,pod,svc -n exam-fundamentals
kubectl describe deployment web -n exam-fundamentals
Typischer Fehler: Ein fehlerhaftes Manifest wird genauso zuverlässig reconciled wie ein korrektes Manifest.
2. Aufgabe des API Servers
Der API Server ist die zentrale Schnittstelle des Clusters. kubectl, Controller, Scheduler und andere Komponenten sprechen über ihn mit der Kubernetes API. Er authentifiziert Anfragen, autorisiert sie, führt Admission-Prüfungen aus und persistiert zugelassene Objekte im Clusterzustand.
Validierung:
kubectl cluster-info
kubectl api-resources
3. Warum etcd kritisch ist
etcd speichert den Clusterzustand, darunter Kubernetes-Objekte, Konfiguration und je nach Setup auch Secrets. Fällt etcd aus oder gehen Daten verloren, kann der Cluster seinen gewünschten Zustand nicht mehr zuverlässig rekonstruieren. In Produktion sind Backup, Restore-Test, Zugriffsschutz und Verschlüsselung relevant.
Fundamentals-Einordnung: Man muss etcd nicht selbst betreiben, aber seine Kritikalität verstehen.
4. Scheduler, Controller Manager und kubelet
| Komponente | Aufgabe |
|---|---|
| Scheduler | weist neue Pods geeigneten Nodes zu |
| Controller Manager | führt Controller-Schleifen aus, zum Beispiel Deployment-, ReplicaSet- und Node-Controller |
| kubelet | läuft auf jedem Node und setzt PodSpecs über die Container Runtime um |
Validierung bei Pod-Problemen:
kubectl get pod -o wide -n exam-fundamentals
kubectl describe pod <pod> -n exam-fundamentals
5. Unterschied zwischen Pod, ReplicaSet und Deployment
Ein Pod ist die kleinste deploybare Einheit. Ein ReplicaSet stellt sicher, dass eine gewünschte Anzahl gleichartiger Pods läuft. Ein Deployment verwaltet ReplicaSets und bietet Rollouts, Rollback und skalierbare deklarative Updates.
Im Normalbetrieb erstellt man für stateless Anwendungen meist Deployments, nicht einzelne Pods.
6. Warum Pods selten direkt erstellt werden
Direkt erstellte Pods werden nicht automatisch durch einen höheren Controller ersetzt, wenn sie gelöscht oder verändert werden. Deployments, StatefulSets, Jobs oder DaemonSets liefern Reconciliation, Rollouts, Skalierung und Betriebssemantik.
Validierung der Owner-Kette:
kubectl get pod -n exam-fundamentals -o yaml | grep -A5 ownerReferences
7. Wie ein Service seine Pods findet
Ein Service findet Pods über Label-Selectoren. Der Service-Selector muss zu den Labels der Pods passen. Der Service selbst kennt keine festen Pod-Namen.
Prüfung:
kubectl get pods --show-labels -n exam-fundamentals
kubectl get svc web -o yaml -n exam-fundamentals
kubectl get endpoints,endpointslices -n exam-fundamentals
8. Unterschied zwischen Label und Annotation
Labels sind kurze, selektierbare Metadaten für Gruppierung und Auswahl. Services und Deployments nutzen Labels über Selectors. Annotations sind nicht-selektierende Metadaten für Tools, Beschreibungen oder zusätzliche Informationen.
Beispiel:
labels:
app: web
environment: exam
annotations:
description: "Fundamentals-Prüfungsworkload"
9. Namespace und Sicherheitsgrenze
Ein Namespace ordnet Kubernetes-Ressourcen logisch und ermöglicht getrennte Sicht, RBAC, Quotas, LimitRanges und Policies. Ein Namespace ersetzt keine vollständige Sicherheitsisolation. Ohne RBAC, NetworkPolicy, Pod Security und Quotas können Risiken weiterhin namespace-übergreifend wirken.
10. ConfigMaps und Secrets
ConfigMaps enthalten nicht-sensitive Konfiguration wie Feature-Flags, URLs oder Betriebsmodi. Secrets sind für sensitive Werte gedacht, etwa Tokens oder Passwörter. Im Lab werden nur Beispielwerte verwendet.
Wichtig: Kubernetes Secrets sind nicht automatisch sicher, nur weil sie als Secret-Ressource gespeichert sind. Zugriff, Ablage und Rotation müssen geschützt werden.
11. Warum Base64 keine Verschlüsselung ist
Base64 ist nur eine Kodierung. Jeder kann Base64-kodierte Werte wieder dekodieren. Schutz von Kubernetes Secrets entsteht durch RBAC, Verschlüsselung sensibler Daten at rest, Zugriffsschutz auf Backups und sichere Secret-Prozesse.
Beispiel:
echo bm90LWEtcmVhbC1zZWNyZXQ= | base64 -d
12. Erste Befehle bei typischen Fehlern
| Fehlerbild | Erste Diagnosebefehle | Typische Ursache |
|---|---|---|
ImagePullBackOff |
kubectl describe pod <pod> und Events |
falscher Image-Name, Tag, Registry oder Pull Secret |
CrashLoopBackOff |
kubectl logs <pod> und kubectl logs <pod> --previous |
Prozess beendet sich, fehlerhafte Konfiguration |
| Service ohne Endpoints | kubectl get endpoints, Labels und Service-Selector prüfen |
Selector passt nicht zu Pod-Labels oder Pods sind nicht ready |
Pod Pending |
kubectl describe pod <pod> und Events |
Ressourcen, Node-Selector, Taints oder PVC blockieren Scheduling |
3. Teil B: Manifest-Analyse
Ausgangsmanifest:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: exam-fundamentals
labels:
app: web
tier: frontend
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
tier: frontend
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
Antworten
| Frage | Musterantwort |
|---|---|
| API-Gruppe und Version | apps/v1; die Ressource liegt in der Apps-API-Gruppe. |
| Ressource | Ein Deployment mit dem Namen web. |
| Gewünschter Zustand | Der gewünschte Zustand steht unter spec, zum Beispiel replicas: 2 und das Pod-Template. |
| Deployment-Labels | Das Deployment erhält app=web und tier=frontend. |
| Pod-Labels | Die Pods erhalten im Template ebenfalls app=web und tier=frontend. |
Rolle von spec.selector.matchLabels |
Der Selector legt fest, welche Pods vom Deployment verwaltet werden. |
| Warum Selector und Pod-Template-Labels passen müssen | Wenn sie nicht passen, kann das Deployment seine Pods nicht korrekt verwalten; bei Deployments ist der Selector außerdem praktisch unveränderlich. |
| Indirekt erzeugte Ressource | Das Deployment erzeugt ein ReplicaSet, und dieses erzeugt Pods. |
| Rollout-Prüfung | kubectl rollout status deployment/web -n exam-fundamentals plus kubectl get deployment,rs,pod -n exam-fundamentals. |
4. Teil C: Praxislösung
C1: Namespace vorbereiten
namespace.yml
apiVersion: v1
kind: Namespace
metadata:
name: exam-fundamentals
labels:
environment: exam
level: fundamentals
Anwenden und prüfen:
kubectl config current-context
kubectl get nodes -o wide
kubectl apply -f namespace.yml
kubectl get namespace exam-fundamentals
kubectl version --client
Optional den Namespace im aktuellen Kontext setzen:
kubectl config set-context --current --namespace=exam-fundamentals
C2: Deployment ausrollen
configmap.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: web-config
namespace: exam-fundamentals
labels:
app: web
environment: exam
data:
APP_MODE: exam
WELCOME_TEXT: "Hallo aus der Fundamentals-Prüfung"
secret.yml
apiVersion: v1
kind: Secret
metadata:
name: web-secret
namespace: exam-fundamentals
labels:
app: web
environment: exam
type: Opaque
stringData:
DEMO_PASSWORD: "not-a-real-secret"
deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: exam-fundamentals
labels:
app: web
tier: frontend
environment: exam
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
tier: frontend
environment: exam
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- name: http
containerPort: 80
env:
- name: APP_MODE
valueFrom:
configMapKeyRef:
name: web-config
key: APP_MODE
volumeMounts:
- name: demo-secret
mountPath: /etc/demo-secret
readOnly: true
volumes:
- name: demo-secret
secret:
secretName: web-secret
Anwenden:
kubectl apply --dry-run=server -f configmap.yml
kubectl apply --dry-run=server -f secret.yml
kubectl apply --dry-run=server -f deployment.yml
kubectl apply -f configmap.yml
kubectl apply -f secret.yml
kubectl apply -f deployment.yml
kubectl rollout status deployment/web -n exam-fundamentals
kubectl get deployment,replicaset,pod -n exam-fundamentals
Validierung der ConfigMap- und Secret-Einbindung:
POD=$(kubectl get pod -l app=web -n exam-fundamentals -o jsonpath='{.items[0].metadata.name}')
kubectl exec "$POD" -n exam-fundamentals -- printenv APP_MODE
kubectl exec "$POD" -n exam-fundamentals -- ls -l /etc/demo-secret
kubectl exec "$POD" -n exam-fundamentals -- cat /etc/demo-secret/DEMO_PASSWORD
Erwartung:
APP_MODEgibtexamaus.- Unter
/etc/demo-secretexistiert eine DateiDEMO_PASSWORD. - Der Wert ist nur ein Lab-Beispielwert.
C3: Service erstellen
service.yml
apiVersion: v1
kind: Service
metadata:
name: web
namespace: exam-fundamentals
labels:
app: web
environment: exam
spec:
type: ClusterIP
selector:
app: web
ports:
- name: http
port: 80
targetPort: 80
Anwenden und prüfen:
kubectl apply --dry-run=server -f service.yml
kubectl apply -f service.yml
kubectl get svc,endpoints,endpointslices -n exam-fundamentals
kubectl describe svc web -n exam-fundamentals
Optionaler Funktionstest mit temporärem Pod:
kubectl run curl --rm -i --tty --restart=Never \
--image=curlimages/curl:8.8.0 \
-n exam-fundamentals -- http://web
Falls interaktive Pods in der Umgebung nicht funktionieren:
kubectl run curl --restart=Never --image=curlimages/curl:8.8.0 -n exam-fundamentals -- sleep 3600
kubectl wait --for=condition=Ready pod/curl -n exam-fundamentals --timeout=60s
kubectl exec curl -n exam-fundamentals -- curl -s http://web
kubectl delete pod curl -n exam-fundamentals
C4: ConfigMap und Secret einbinden
Die Einbindung ist in deployment.yml bereits enthalten. Eine gute Antwort erklärt zusätzlich:
- ConfigMap-Werte können als Environment-Variablen oder Dateien eingebunden werden.
- Secret-Werte können ebenfalls als Environment-Variablen oder Volumes eingebunden werden.
- Secret-Volumes sollten read-only gemountet werden.
- Echte Secrets gehören nicht in diese Prüfung und nicht unverschlüsselt in Git.
C5: Rollout, Skalierung und Rollback
kubectl scale deployment/web --replicas=3 -n exam-fundamentals
kubectl rollout status deployment/web -n exam-fundamentals
kubectl get pods -l app=web -n exam-fundamentals
kubectl set image deployment/web nginx=nginx:1.26 -n exam-fundamentals
kubectl rollout status deployment/web -n exam-fundamentals
kubectl rollout history deployment/web -n exam-fundamentals
kubectl get deployment web -n exam-fundamentals -o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'
kubectl rollout undo deployment/web -n exam-fundamentals
kubectl rollout status deployment/web -n exam-fundamentals
kubectl get deployment web -n exam-fundamentals -o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'
Erwartung:
- Nach dem Skalieren laufen drei gewünschte Replikate.
- Nach
set imagezeigt das Deploymentnginx:1.26. - Nach
rollout undoläuft wieder die vorherige Revision, in dieser Musterlösungnginx:1.27.
5. Teil D: Diagnose und Betriebsnotiz
D1: Service ohne Endpoints
Absichtlich falscher Service-Selector:
selector:
app: wrong-web
Symptom:
kubectl get endpoints web -n exam-fundamentals
Typische Ausgabe:
NAME ENDPOINTS AGE
web <none> ...
Diagnose:
kubectl get pods -n exam-fundamentals --show-labels
kubectl get svc web -n exam-fundamentals -o yaml
kubectl describe svc web -n exam-fundamentals
kubectl get endpoints,endpointslices -n exam-fundamentals
Ursache:
Der Service sucht Pods mit app=wrong-web, die tatsächlichen Pods tragen aber app=web.
Fix:
selector:
app: web
Validierung:
kubectl apply -f service.yml
kubectl get endpoints web -n exam-fundamentals
kubectl get endpointslices -l kubernetes.io/service-name=web -n exam-fundamentals
D2: Fehlerbilder erklären
| Fehlerbild | Diagnose | Wahrscheinlichste Ursache | Fix |
|---|---|---|---|
ImagePullBackOff |
kubectl describe pod <pod> und Events |
Image-Name, Tag, Registry oder Pull Secret falsch | korrektes Image setzen, Registry-Zugang prüfen |
CrashLoopBackOff |
kubectl logs <pod> und kubectl logs <pod> --previous |
Prozess beendet sich wiederholt | Startkommando, ConfigMap, Secret oder App-Konfiguration korrigieren |
| Service ohne Endpoints | kubectl get endpoints, kubectl get pods --show-labels, Service-YAML |
Selector passt nicht zu Labels oder Pods sind nicht ready | Selector oder Labels korrigieren, Readiness prüfen |
Pod bleibt Pending |
kubectl describe pod <pod>, Events, Node-Status |
Ressourcenmangel, NodeSelector, Taints, PVC | Ressourcen, Scheduling-Regeln oder Storage korrigieren |
D3: Muster für evidence.md
# Evidence – Fundamentals-Prüfung
## Kontext
- Cluster-Kontext: <Ausgabe von kubectl config current-context>
- Namespace: exam-fundamentals
- Node-Anzahl: <aus kubectl get nodes>
- Client-Version: <aus kubectl version --client>
## Angewendete Manifeste
- namespace.yml
- configmap.yml
- secret.yml
- deployment.yml
- service.yml
## Erzeugte Ressourcen
```bash
kubectl get namespace exam-fundamentals
kubectl get configmap,secret,deployment,replicaset,pod,svc,endpoints,endpointslices -n exam-fundamentals
```
## Rollout
```bash
kubectl rollout status deployment/web -n exam-fundamentals
kubectl rollout history deployment/web -n exam-fundamentals
```
## Service-Prüfung
```bash
kubectl describe svc web -n exam-fundamentals
kubectl get endpoints web -n exam-fundamentals
```
## Fehler und Fix
| Fehler | Ursache | Fix | Validierung |
| --- | --- | --- | --- |
| Service ohne Endpoints | falscher Selector `app=wrong-web` | Selector auf `app=web` korrigiert | Endpoints wieder vorhanden |
## Rückbau
```bash
kubectl delete namespace exam-fundamentals
```
6. Erwartete Abgabedateien
01-fundamentals-abgabe/
answers.md
namespace.yml
deployment.yml
service.yml
configmap.yml
secret.yml
evidence.md
cleanup.md
answers.md – Mindestinhalt
- Antworten zu allen Wissensfragen.
- Manifest-Analyse mit API-Version, Kind, Labels, Selector, ReplicaSet und Rollout-Prüfung.
- Kurze Erklärung zu ConfigMap, Secret, Service-Selector und Rollback.
cleanup.md – Muster
# Cleanup
Alle Lab-Ressourcen liegen im Namespace `exam-fundamentals`.
```bash
kubectl delete namespace exam-fundamentals
kubectl get namespace exam-fundamentals
```
Erwartung: Der Namespace ist gelöscht oder kurzzeitig im Status `Terminating`.
7. Cleanup
Gesamtrückbau:
kubectl delete namespace exam-fundamentals
Nur einzelne Dateien zurückbauen:
kubectl delete -f service.yml
kubectl delete -f deployment.yml
kubectl delete -f secret.yml
kubectl delete -f configmap.yml
kubectl delete -f namespace.yml
8. Bewertungs- und Prüferhinweise
Eine sehr gute Fundamentals-Lösung erfüllt:
- Kontext und Namespace wurden vor Änderungen geprüft.
- Alle Ressourcen liegen im Namespace
exam-fundamentals. - Deployment, ReplicaSet, Pod und Service werden korrekt unterschieden.
- Service-Selector und Pod-Labels passen nach dem Fix zusammen.
- ConfigMap und Secret werden korrekt eingebunden.
DEMO_PASSWORDist eindeutig ein Beispielwert und kein echtes Secret.- Rollout, Skalierung und Rollback sind dokumentiert.
- Diagnose nutzt Events, Logs, Endpoints und Rollout-Status statt Raten.
- Cleanup ist sicher und nachvollziehbar.