Workshop-Wiki · Deutsch

Kubernetes Workshop: Fundamentals – Übungsaufgaben mit Lösungen

Bezug: 01-fundamentals-DE-aktualisiert.md Schwierigkeitsgrad: Fundamentals Format: Hands-on-Lab mit Musterlösungen und Walkthroughs

Workshop-Beispiele als ZIP
Lernstand in der Web-App

Kapitel als gelesen markieren, Lesefortschritt sehen und Praxismodule abhaken: Diese Funktionen stehen nach Aktivierung der optionalen Web-App zur Verfügung. Der Workshop-Fortschritt ergibt sich automatisch aus den Kapiteln aller Dokumentseiten. Deine Auswahl bleibt auf diesem Gerät; es gibt kein Konto und keinen Serverabgleich. Eine Installation ist nicht erforderlich. Beim Widerruf in den Datenschutz-Einstellungen wird der Lernstand gelöscht.

Lesefortschritt0%
0%
0 / 22 Kapitel gelesen
Weitere SprachfassungEnglisch ↗Griechisch ↗

Kubernetes Workshop: Fundamentals – Übungsaufgaben mit Lösungen

Bezug: 01-fundamentals-DE-aktualisiert.md
Schwierigkeitsgrad: Fundamentals
Format: Hands-on-Lab mit Musterlösungen und Walkthroughs

Ziel dieses Übungsdokuments

Dieses Übungsdokument ergänzt den Fundamentals-Workshop mit konkreten Aufgaben, überprüfbaren Ergebnissen und vollständigen Lösungen. Der Schwerpunkt liegt auf sicherer Grundbedienung, Kubernetes-Objektmodell, kubectl, Pods, Deployments, ReplicaSets, Services, Labels, Selectors, ConfigMaps, Secrets, Namespaces, Rollouts, Skalierung, Rollback und erster Fehlerdiagnose.

Du arbeitest ausschließlich in einem Lab-Cluster. Verwende keine produktiven Cluster-Kontexte und keine echten Zugangsdaten.

01 / 22

Voraussetzungen

Du brauchst:

  • kubectl
  • einen lokalen oder bereitgestellten Kubernetes-Cluster, zum Beispiel kind, minikube oder k3d
  • einen ungefährlichen Cluster-Kontext
  • Schreibrechte in einem eigenen Namespace

Empfohlener Namespace für alle Übungen:

bash
export NS=workshop-fundamentals
02 / 22

Arbeitsregeln

  1. Prüfe vor jeder Übung den aktiven Kontext.
  2. Arbeite nur im Namespace $NS.
  3. Speichere Manifeste als Dateien, bevor du sie anwendest.
  4. Nutze kubectl apply --dry-run=server, sofern dein Cluster das unterstützt.
  5. Prüfe nach jeder Änderung Status, Events und Logs.
  6. Dokumentiere am Ende den Rückbau.
03 / 22

Aufgabenübersicht

Nr. Thema Ergebnis
1 Kontext, Cluster und Namespace sicherer Lab-Kontext und Namespace
2 Objektmodell lesen Deployment-Manifest erklären
3 Deployment und Service einfache Web-App intern erreichbar
4 Labels und Selectors Service-Fehler diagnostiziert und behoben
5 ConfigMap und Secret Konfiguration und Beispiel-Secret eingebunden
6 Rollout, Skalierung und Rollback Image-Update, Skalierung und Rollback durchgeführt
7 Troubleshooting: ImagePullBackOff falsches Image diagnostiziert und korrigiert
8 Troubleshooting: CrashLoopBackOff crashende Anwendung diagnostiziert und korrigiert
9 Betriebsnotiz und Rückbau Ressourcenliste, Validierung und Cleanup dokumentiert

Teil A – Aufgaben

04 / 22

Aufgabe 1: Kontext, Cluster und Namespace prüfen

Ziel

Du stellst sicher, dass du im richtigen Cluster arbeitest und erstellst einen eigenen Namespace.

Arbeitsauftrag

  1. Prüfe den aktiven Kontext.
  2. Prüfe Cluster-Informationen und Nodes.
  3. Erstelle den Namespace workshop-fundamentals.
  4. Setze den Namespace für den aktuellen Kontext.
  5. Dokumentiere Clustername, Node-Anzahl und Kubernetes-Version.

Erwartetes Ergebnis

  • Der Namespace existiert.
  • kubectl get pods zeigt standardmäßig Ressourcen aus workshop-fundamentals.
  • Du kannst erklären, warum der Kontext vor jedem Lab geprüft wird.

05 / 22

Aufgabe 2: Kubernetes-Objektmodell lesen

Ziel

Du liest ein Deployment-Manifest und erkennst apiVersion, kind, metadata, spec, selector, Pod-Template und Container-Konfiguration.

Arbeitsauftrag

Erstelle die Datei deployment.yml:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: workshop-fundamentals
  labels:
    app: web
    tier: frontend
    environment: lab
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
        tier: frontend
        environment: lab
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          ports:
            - containerPort: 80

Beantworte schriftlich:

  1. Welche API-Gruppe wird verwendet?
  2. Welche Ressource wird erstellt?
  3. Wo steht der gewünschte Zustand?
  4. Welche Labels bekommen die Pods?
  5. Wofür wird der Selector verwendet?

06 / 22

Aufgabe 3: Deployment und Service ausrollen

Ziel

Du rollst eine einfache Webanwendung aus und machst sie über einen internen ClusterIP-Service erreichbar.

Arbeitsauftrag

  1. Wende deployment.yml an.
  2. Erstelle die Datei service.yml:
yaml
apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: workshop-fundamentals
  labels:
    app: web
spec:
  type: ClusterIP
  selector:
    app: web
  ports:
    - name: http
      port: 80
      targetPort: 80
  1. Wende service.yml an.
  2. Prüfe Deployment, ReplicaSet, Pods, Service, Endpoints und EndpointSlices.
  3. Teste den Service per temporärem Debug-Pod.

Erwartetes Ergebnis

  • Zwei Pods laufen.
  • Der Service hat Endpoints.
  • Ein temporärer Pod kann http://web erreichen.

07 / 22

Aufgabe 4: Labels und Selectors absichtlich brechen

Ziel

Du verstehst, warum Services Pods über Labels und Selectors finden und nicht über Pod-Namen.

Arbeitsauftrag

  1. Ändere den Service-Selector in service.yml absichtlich falsch:
yaml
selector:
  app: wrong-web
  1. Wende die Änderung an.
  2. Prüfe Service, Endpoints und EndpointSlices.
  3. Korrigiere den Selector wieder auf app: web.
  4. Prüfe erneut.

Erwartetes Ergebnis

  • Mit falschem Selector hat der Service keine Endpoints.
  • Nach der Korrektur sind Endpoints wieder vorhanden.

08 / 22

Aufgabe 5: ConfigMap und Secret einbinden

Ziel

Du unterscheidest nicht-sensitive Konfiguration von sensiblen Beispielwerten und bindest beides in einen Pod ein.

Arbeitsauftrag

Erstelle configmap.yml:

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: web-config
  namespace: workshop-fundamentals
data:
  APP_MODE: lab
  WELCOME_TEXT: "Hallo aus Kubernetes"

Erstelle secret.yml:

yaml
apiVersion: v1
kind: Secret
metadata:
  name: web-secret
  namespace: workshop-fundamentals
type: Opaque
stringData:
  DEMO_PASSWORD: "not-a-real-secret"

Erweitere dein Deployment so, dass APP_MODE als Environment-Variable und DEMO_PASSWORD als Datei eingebunden wird.

Erwartetes Ergebnis

  • Die ConfigMap existiert.
  • Das Secret existiert.
  • Der Pod enthält APP_MODE als Environment-Variable.
  • Das Secret ist als Datei im Container sichtbar.

09 / 22

Aufgabe 6: Rollout, Skalierung und Rollback durchführen

Ziel

Du nutzt Deployment-Rollouts kontrolliert und kannst eine Änderung zurücknehmen.

Arbeitsauftrag

  1. Prüfe den aktuellen Rollout-Status.
  2. Skaliere das Deployment auf drei Replikate.
  3. Ändere das Image von nginx:1.27 auf nginx:1.26.
  4. Prüfe Rollout-Status und Rollout-History.
  5. Führe ein Rollback durch.
  6. Prüfe, welches Image danach aktiv ist.

Erwartetes Ergebnis

  • Drei Pods laufen.
  • Die Rollout-History zeigt mindestens zwei Revisionen.
  • Nach dem Rollback läuft wieder das vorherige Image.

10 / 22

Aufgabe 7: Fehlerbild ImagePullBackOff diagnostizieren

Ziel

Du provozierst einen Image-Pull-Fehler und behebst ihn anhand von Events.

Arbeitsauftrag

Erstelle bad-image.yml:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: bad-image
  namespace: workshop-fundamentals
spec:
  replicas: 1
  selector:
    matchLabels:
      app: bad-image
  template:
    metadata:
      labels:
        app: bad-image
    spec:
      containers:
        - name: app
          image: nginx:this-tag-does-not-exist
          ports:
            - containerPort: 80
  1. Wende das Manifest an.
  2. Prüfe Pod-Status und Events.
  3. Korrigiere das Image auf nginx:1.27.
  4. Prüfe erneut.

11 / 22

Aufgabe 8: Fehlerbild CrashLoopBackOff diagnostizieren

Ziel

Du provozierst eine crashende Anwendung, liest Logs und korrigierst das Startkommando.

Arbeitsauftrag

Erstelle crashloop.yml:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: crashloop
  namespace: workshop-fundamentals
spec:
  replicas: 1
  selector:
    matchLabels:
      app: crashloop
  template:
    metadata:
      labels:
        app: crashloop
    spec:
      containers:
        - name: app
          image: busybox:1.36
          command: ["sh", "-c", "echo 'ich beende mich sofort'; exit 1"]
  1. Wende das Manifest an.
  2. Prüfe den Pod-Status.
  3. Lies Logs und vorherige Logs.
  4. Korrigiere das Kommando so, dass der Container läuft.
  5. Prüfe erneut.

12 / 22

Aufgabe 9: Betriebsnotiz und Rückbau

Ziel

Du dokumentierst, was erstellt wurde, wie du den Zustand geprüft hast und wie alles zurückgebaut wird.

Arbeitsauftrag

Erstelle notes.md mit:

  • Cluster-Kontext
  • Namespace
  • angewendete Manifeste
  • erzeugte Ressourcen
  • wichtigste Diagnosebefehle
  • bekannte Fehler und Fixes
  • Cleanup-Befehl

Teil B – Lösungen und Walkthroughs

13 / 22

Lösung 1: Kontext, Cluster und Namespace prüfen

bash
kubectl config current-context
kubectl cluster-info
kubectl version --client
kubectl get nodes -o wide
kubectl create namespace workshop-fundamentals
kubectl config set-context --current --namespace=workshop-fundamentals
kubectl get pods

Validierung:

bash
kubectl get namespace workshop-fundamentals
kubectl config view --minify --output 'jsonpath={..namespace}'

Mustererklärung:

  • Der Kontext bestimmt, mit welchem Cluster kubectl spricht.
  • Der Namespace begrenzt die Standard-Sicht von kubectl, ersetzt aber keine Sicherheitsisolation.
  • kubectl cluster-info zeigt API-Erreichbarkeit.
  • kubectl get nodes -o wide zeigt Node-Status und Laufzeitumgebung.

14 / 22

Lösung 2: Kubernetes-Objektmodell lesen

Musterantworten:

Frage Antwort
API-Gruppe apps/v1; Ressource aus der Apps-API-Gruppe
Ressource Deployment
gewünschter Zustand unter spec
Pod-Labels app=web, tier=frontend, environment=lab
Selector verbindet Deployment mit den von ihm verwalteten Pods

Hilfreiche Erkundung:

bash
kubectl explain deployment
kubectl explain deployment.spec
kubectl explain deployment.spec.template.spec.containers
kubectl api-resources | grep -i deployment

15 / 22

Lösung 3: Deployment und Service ausrollen

bash
kubectl apply --dry-run=server -f deployment.yml
kubectl apply -f deployment.yml
kubectl rollout status deployment/web
kubectl apply --dry-run=server -f service.yml
kubectl apply -f service.yml

Prüfung:

bash
kubectl get deployment,replicaset,pod,svc,endpoints,endpointslices
kubectl describe deployment web
kubectl describe svc web

Service-Test:

bash
kubectl run curl --rm -i --tty --restart=Never --image=curlimages/curl:8.8.0 -- http://web

Alternative, falls interaktives kubectl run in deiner Umgebung anders reagiert:

bash
kubectl run curl --restart=Never --image=curlimages/curl:8.8.0 -- sleep 3600
kubectl wait --for=condition=Ready pod/curl --timeout=60s
kubectl exec curl -- curl -s http://web
kubectl delete pod curl

Erwartung:

  • deployment.apps/web ist verfügbar.
  • service/web hat eine ClusterIP.
  • endpoints/web enthält Pod-IP-Adressen.

16 / 22

Lösung 4: Labels und Selectors korrigieren

Falschen Selector anwenden:

bash
kubectl apply -f service.yml
kubectl get svc,endpoints,endpointslices
kubectl describe svc web

Typisches Symptom:

text
Endpoints: <none>

Diagnose:

bash
kubectl get pods --show-labels
kubectl get svc web -o yaml

Korrektur in service.yml:

yaml
selector:
  app: web

Danach:

bash
kubectl apply -f service.yml
kubectl get endpoints web
kubectl get endpointslices -l kubernetes.io/service-name=web

Fachliche Erklärung:

Ein Service kennt keine festen Pod-Namen. Er findet Pods über den Selector. Wenn Selector und Pod-Labels nicht zusammenpassen, existiert zwar der Service, aber er hat keine Ziele.


17 / 22

Lösung 5: ConfigMap und Secret einbinden

ConfigMap und Secret anwenden:

bash
kubectl apply -f configmap.yml
kubectl apply -f secret.yml
kubectl get configmap,secret

Deployment-Erweiterung:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: workshop-fundamentals
  labels:
    app: web
    tier: frontend
    environment: lab
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
        tier: frontend
        environment: lab
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          ports:
            - containerPort: 80
          env:
            - name: APP_MODE
              valueFrom:
                configMapKeyRef:
                  name: web-config
                  key: APP_MODE
          volumeMounts:
            - name: web-secret-volume
              mountPath: /etc/demo-secret
              readOnly: true
      volumes:
        - name: web-secret-volume
          secret:
            secretName: web-secret

Anwenden und prüfen:

bash
kubectl apply -f deployment.yml
kubectl rollout status deployment/web
POD=$(kubectl get pod -l app=web -o jsonpath='{.items[0].metadata.name}')
kubectl exec "$POD" -- printenv APP_MODE
kubectl exec "$POD" -- ls -l /etc/demo-secret
kubectl exec "$POD" -- cat /etc/demo-secret/DEMO_PASSWORD

Fachliche Einordnung:

  • ConfigMaps sind für nicht-sensitive Konfiguration gedacht.
  • Secrets sind für sensitive Werte gedacht, aber Base64 ist keine Verschlüsselung.
  • Echte Secrets gehören nicht in Lernmanifeste oder Klartext-Git.

18 / 22

Lösung 6: Rollout, Skalierung und Rollback

Status prüfen:

bash
kubectl rollout status deployment/web
kubectl get deployment web

Skalieren:

bash
kubectl scale deployment/web --replicas=3
kubectl rollout status deployment/web
kubectl get pods -l app=web

Image ändern:

bash
kubectl set image deployment/web nginx=nginx:1.26
kubectl rollout status deployment/web
kubectl rollout history deployment/web

Aktives Image prüfen:

bash
kubectl get deployment web -o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'

Rollback:

bash
kubectl rollout undo deployment/web
kubectl rollout status deployment/web
kubectl get deployment web -o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'

Mustererklärung:

  • scale verändert spec.replicas.
  • set image verändert das Pod-Template und erzeugt dadurch eine neue Revision.
  • rollout undo setzt die vorherige Revision wieder als Zielzustand.

19 / 22

Lösung 7: ImagePullBackOff

Anwenden:

bash
kubectl apply -f bad-image.yml
kubectl get pods -l app=bad-image

Diagnose:

bash
POD=$(kubectl get pod -l app=bad-image -o jsonpath='{.items[0].metadata.name}')
kubectl describe pod "$POD"
kubectl get events --sort-by=.metadata.creationTimestamp

Typischer Befund:

  • Image-Tag existiert nicht.
  • Events enthalten Meldungen zu Failed to pull image oder ErrImagePull.

Korrektur:

bash
kubectl set image deployment/bad-image app=nginx:1.27
kubectl rollout status deployment/bad-image
kubectl get pods -l app=bad-image

Oder Datei korrigieren und erneut anwenden:

bash
sed -i 's/nginx:this-tag-does-not-exist/nginx:1.27/' bad-image.yml
kubectl apply -f bad-image.yml

20 / 22

Lösung 8: CrashLoopBackOff

Anwenden:

bash
kubectl apply -f crashloop.yml
kubectl get pods -l app=crashloop

Diagnose:

bash
POD=$(kubectl get pod -l app=crashloop -o jsonpath='{.items[0].metadata.name}')
kubectl describe pod "$POD"
kubectl logs "$POD"
kubectl logs "$POD" --previous

Typischer Befund:

  • Container startet.
  • Kommando beendet sich mit Exit-Code 1.
  • Kubernetes startet ihn erneut; dadurch entsteht CrashLoopBackOff.

Korrektur per Manifest:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: crashloop
  namespace: workshop-fundamentals
spec:
  replicas: 1
  selector:
    matchLabels:
      app: crashloop
  template:
    metadata:
      labels:
        app: crashloop
    spec:
      containers:
        - name: app
          image: busybox:1.36
          command: ["sh", "-c", "echo 'ich bleibe aktiv'; sleep 3600"]

Anwenden:

bash
kubectl apply -f crashloop.yml
kubectl rollout status deployment/crashloop
kubectl get pods -l app=crashloop

21 / 22

Lösung 9: Betriebsnotiz und Rückbau

Muster für notes.md:

markdown
# Betriebsnotiz – Fundamentals Lab

## Kontext

- Cluster-Kontext: <aus kubectl config current-context>
- Namespace: workshop-fundamentals
- Datum: <Datum eintragen>

## Manifeste

- deployment.yml
- service.yml
- configmap.yml
- secret.yml
- bad-image.yml
- crashloop.yml

## Validierung

- kubectl get deployment,rs,pod,svc,endpoints,endpointslices
- kubectl rollout status deployment/web
- kubectl describe pod <pod>
- kubectl logs <pod>

## Fehler und Fixes

| Fehler | Ursache | Fix |
| --- | --- | --- |
| Service ohne Endpoints | falscher Selector | Selector auf app=web korrigiert |
| ImagePullBackOff | ungültiger Image-Tag | Image auf nginx:1.27 gesetzt |
| CrashLoopBackOff | Prozess beendet sich mit exit 1 | Kommando auf sleep 3600 geändert |

## Rückbau

kubectl delete namespace workshop-fundamentals

Cleanup:

bash
kubectl delete namespace workshop-fundamentals

Validierung nach Cleanup:

bash
kubectl get namespace workshop-fundamentals

Erwartung: Der Namespace ist gelöscht oder befindet sich kurzzeitig im Status Terminating.


Bewertungscheckliste

Kriterium Erfüllt?
Kontext vor Anwendung geprüft ☐
eigener Namespace verwendet ☐
Deployment-Manifest erklärt ☐
Service mit Endpoints erstellt ☐
Selector-Fehler diagnostiziert ☐
ConfigMap und Secret korrekt eingebunden ☐
Rollout, Skalierung und Rollback durchgeführt ☐
ImagePullBackOff anhand von Events erklärt ☐
CrashLoopBackOff anhand von Logs erklärt ☐
Cleanup dokumentiert ☐
22 / 22

K8S · Orthevs Academy

31 Module als durchgängiger Lernpfad.

Die Reihenfolge bleibt unverändert: von der Laborgrundstruktur über fachliche Grundlagen und Betriebsmodelle bis zum abschließenden Troubleshooting. Die technischen Verzeichnisnamen werden bewusst beibehalten.

Orthevs – Engineering als Grundlage für das, was als Nächstes kommt.

Orthevs als App

Orthevs installieren

Die Orthevs Web-App kann auf unterstützten Mobilgeräten und Desktop-Browsern installiert werden.

iPhone und iPad

Öffnen Sie Orthevs in Safari. Tippen Sie auf Teilen, dann auf ‚Zum Home-Bildschirm‘. Aktivieren Sie gegebenenfalls ‚Als Web-App öffnen‘ und tippen Sie auf ‚Hinzufügen‘.

Android

Für die Web-App öffnen Sie das Browsermenü und wählen ‚App installieren‘ oder ‚Zum Startbildschirm hinzufügen‘. Bestätigen Sie die Installation.

Desktop-Browser

Öffnen Sie das Browsermenü oder das Installationssymbol in der Adressleiste und wählen Sie ‚App installieren‘ beziehungsweise ‚Zum Dock hinzufügen‘.

Die Web-App-Installation hängt vom Browser ab. Falls kein Installationsdialog erscheint, nutzen Sie die angezeigten Schritte im Browser.