Workshop-Wiki · Griechisch

Kubernetes Workshop: Intermediate – Ασκήσεις με λύσεις

Δέκα πρακτικές Kubernetes Intermediate ασκήσεις με πλήρεις λύσεις, Manifests, ελέγχους και Troubleshooting.

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 / 23 Kapitel gelesen
Weitere SprachfassungDeutsch ↗Englisch ↗

Kubernetes Workshop: Intermediate – Ασκήσεις με λύσεις

Αναφορά: Workshop Intermediate

Επίπεδο δυσκολίας: Intermediate

Μορφή: πρακτικό Lab με ενδεικτικές λύσεις και οδηγίες βήμα προς βήμα

Στόχος αυτού του εγγράφου ασκήσεων

Αυτό το έγγραφο συμπληρώνει το Workshop Intermediate με πρακτικές εργασίες, λύσεις και οδηγίες βήμα προς βήμα. Εστιάζει στην επιλογή Workloads, σε Init Containers, Sidecars, Ephemeral Containers, Probes, Graceful Shutdown, PodDisruptionBudgets, Requests, Limits, QoS, LimitRange, ResourceQuota, Scheduling, NetworkPolicy, DNS, Ingress ή Gateway API, Storage, Helm, Kustomize και συστηματικό Troubleshooting.

01 / 23

Προαπαιτούμενα

Χρειάζεστε:

  • Lab Cluster με λειτουργικό CNI,
  • CoreDNS,
  • kubectl,
  • προαιρετικά helm,
  • προαιρετικά kustomize ή kubectl kustomize,
  • προαιρετικά StorageClass,
  • προαιρετικά Ingress Controller ή Gateway Controller.

Προτεινόμενο Namespace:

bash
export NS=workshop-intermediate
kubectl create namespace "$NS"
kubectl config set-context --current --namespace="$NS"
02 / 23

Επισκόπηση ασκήσεων

Αρ. Θέμα Αποτέλεσμα
1 Επιλογή Workload Τεχνική διάκριση Deployment, Job και CronJob.
2 Init Container και Sidecar Παρακολούθηση του κύκλου ζωής των Containers στο Pod.
3 Probes και κύκλος ζωής Σαφής διάκριση Startup, Readiness και Liveness.
4 Resources, QoS, LimitRange, Quota Έλεγχος ορίων Namespace και επίδρασης στο Scheduling.
5 Scheduling Δοκιμή Node Labels, nodeSelector, Taints και Tolerations.
6 NetworkPolicy και DNS Δημιουργία Default Deny με στοχευμένες εξαιρέσεις.
7 Ingress ή Gateway Εξωτερική έκθεση HTTP App ή σωστή ταξινόμηση των περιορισμών.
8 PVC και StatefulSet Δοκιμή Persistent State.
9 Helm και Kustomize Σύγκριση παραγόμενων Manifests.
10 Διαδρομή Troubleshooting Συστηματική διόρθωση συνήθων σφαλμάτων.

Μέρος A – Ασκήσεις

03 / 23

Άσκηση 1: Επιλογή Workload Resource

Στόχος

Αποφασίστε αν τεχνικά ταιριάζει Deployment, Job ή CronJob.

Σενάριο

Πρέπει να μοντελοποιήσετε τρεις απαιτήσεις:

  1. Ένας Web Server πρέπει να εκτελείται συνεχώς και να ενημερώνεται με Rolling Updates.
  2. Ένα Data Migration πρέπει να εκτελείται μία φορά και έπειτα να ολοκληρώνεται.
  3. Μια εργασία Cleanup πρέπει να εκτελείται κάθε ώρα.

Εργασία

  1. Δημιουργήστε ελάχιστο Manifest για κάθε περίπτωση.
  2. Εφαρμόστε τα Manifests.
  3. Ελέγξτε το Status και τα Events.
  4. Τεκμηριώστε γιατί ταιριάζει το επιλεγμένο Resource.

04 / 23

Άσκηση 2: Ταξινόμηση Init Container και Sidecar

Στόχος

Κατανοήστε πότε πρέπει να εκτελεστεί ένα Init Container πριν από την εφαρμογή και πότε ένα πρόσθετο Container μοιράζεται τον κύκλο ζωής του ίδιου Pod.

Εργασία

Δημιουργήστε Pod στο οποίο:

  • ένα Init Container γράφει αρχείο σε emptyDir,
  • το App Container διαβάζει αυτό το αρχείο,
  • ένα Sidecar Container γράφει περιοδικά ένα Heartbeat File.

Ελέγξτε:

  1. τη σειρά εκκίνησης των Containers,
  2. τα Logs όλων των Containers,
  3. τα περιεχόμενα του κοινόχρηστου Volume.

05 / 23

Άσκηση 3: Σωστός διαχωρισμός Probes

Στόχος

Διορθώστε ελαττωματικό Probe Configuration που προκαλεί επανεκκινήσεις.

Σενάριο

Μια δοκιμαστική εφαρμογή εκκινεί αργά. Το Liveness Probe ελέγχει την ίδια διαδρομή με το Readiness υπερβολικά νωρίς.

Εργασία

  1. Δημιουργήστε Deployment με σκόπιμα υπερβολικά επιθετικό Liveness Probe.
  2. Παρατηρήστε Events και επανεκκινήσεις.
  3. Προσθέστε Startup Probe.
  4. Διαχωρίστε εννοιολογικά Readiness και Liveness.
  5. Εξηγήστε γιατί το Readiness ελέγχει την κυκλοφορία, ενώ το Liveness προκαλεί επανεκκινήσεις.

06 / 23

Άσκηση 4: Resources, QoS, LimitRange και ResourceQuota

Στόχος

Ορίστε Requests και Limits, παρατηρήστε τις QoS Classes και δημιουργήστε όρια Namespace.

Εργασία

  1. Δημιουργήστε LimitRange με προεπιλεγμένα Requests και Limits.
  2. Δημιουργήστε ResourceQuota για CPU, Memory και αριθμό Pods.
  3. Κάντε Rollout τριών Pods:
    • χωρίς ρητά Resources,
    • με Requests μικρότερα από τα Limits,
    • με Requests ίσα με τα Limits.
  4. Προσδιορίστε τις QoS Classes.
  5. Προκαλέστε σκόπιμα υπέρβαση Quota.

07 / 23

Άσκηση 5: Scheduling με Node Labels, nodeSelector, Taint και Toleration

Στόχος

Ελέγξτε την τοποθέτηση Pods και ερμηνεύστε Events για την κατάσταση Pending.

Εργασία

  1. Προσθέστε σε Lab Node το Label workshop-role=apps.
  2. Δημιουργήστε Pod με αντίστοιχο nodeSelector.
  3. Δημιουργήστε Pod με nodeSelector που δεν ταιριάζει.
  4. Ορίστε Taint στο Node.
  5. Δημιουργήστε ένα Pod χωρίς Toleration και ένα με Toleration.
  6. Τεκμηριώστε τα Events.

08 / 23

Άσκηση 6: NetworkPolicy Default Deny με εξαίρεση DNS

Στόχος

Δημιουργήστε Policy Default Deny και έπειτα επιτρέψτε ρητά την επικοινωνία DNS και της εφαρμογής.

Εργασία

  1. Δημιουργήστε δύο Deployments: frontend και backend.
  2. Δημιουργήστε Services και για τα δύο.
  3. Ελέγξτε ότι το frontend μπορεί να συνδεθεί στο backend.
  4. Δημιουργήστε Policy Default Deny για Ingress και Egress.
  5. Ελέγξτε ότι η κυκλοφορία αποκλείεται.
  6. Επιτρέψτε DNS Egress.
  7. Επιτρέψτε σύνδεση του frontend προς το backend στην Port 8080.
  8. Ελέγξτε ξανά.

09 / 23

Άσκηση 7: Παροχή Ingress ή Gateway

Στόχος

Εκθέστε μια HTTP Application μέσω Ingress ή, εναλλακτικά, περιγράψτε τα Resources του Gateway API αν δεν είναι εγκατεστημένος Controller.

Εργασία

  1. Ελέγξτε αν υπάρχει Ingress Controller ή Gateway Controller.
  2. Αναπτύξτε HTTP App.
  3. Δημιουργήστε είτε Ingress Resource είτε παράδειγμα Gateway/HTTPRoute.
  4. Ελέγξτε Controller Events, Backend Service και Routing.
  5. Τεκμηριώστε γιατί ένα Ingress Resource δεν έχει αποτέλεσμα χωρίς Controller.

10 / 23

Άσκηση 8: Χρήση PVC και StatefulSet

Στόχος

Εκτελέστε μικρό Stateful Workload με PVC και ελέγξτε αν τα δεδομένα διατηρούνται μετά την αναδημιουργία του Pod.

Εργασία

  1. Ελέγξτε τα υπάρχοντα StorageClasses.
  2. Δημιουργήστε StatefulSet με volumeClaimTemplates.
  3. Γράψτε ένα αρχείο στο Volume.
  4. Διαγράψτε το Pod.
  5. Μετά την αναδημιουργία του, ελέγξτε αν το αρχείο εξακολουθεί να υπάρχει.
  6. Τεκμηριώστε γιατί ένα Lab με hostPath δεν αποτελεί παραδοχή για Production.

11 / 23

Άσκηση 9: Σύγκριση Helm και Kustomize

Στόχος

Κάντε Render των Manifests πριν τα εφαρμόσετε και συγκρίνετε Helm με Kustomize.

Εργασία

  1. Δημιουργήστε ένα μικρό Kustomize Base και ένα dev Overlay.
  2. Κάντε Render του Overlay.
  3. Δημιουργήστε ένα ελάχιστο Helm Chart ή χρησιμοποιήστε ένα τοπικό παράδειγμα Chart.
  4. Κάντε Render του Helm Chart.
  5. Συγκρίνετε τη δυνατότητα Review, την Παραμετροποίηση και τον κίνδυνο σφαλμάτων.

12 / 23

Άσκηση 10: Διαδρομή Troubleshooting

Στόχος

Διερευνήστε μεθοδικά πέντε συνήθη μοτίβα σφαλμάτων.

Μοτίβα σφαλμάτων

  1. Pod παραμένει Pending λόγω λανθασμένου nodeSelector.
  2. Pod εμφανίζει ImagePullBackOff λόγω λάθος Image Tag.
  3. Pod εμφανίζει CrashLoopBackOff λόγω ελαττωματικού Startup Command.
  4. PVC παραμένει Pending λόγω λάθος StorageClass.
  5. Service δεν έχει Endpoints λόγω λανθασμένου Selector.

Εργασία

Για κάθε σφάλμα τεκμηριώστε:

  • το σύμπτωμα,
  • την εντολή διάγνωσης,
  • τα σχετικά Events ή Logs,
  • την αιτία,
  • τη διόρθωση,
  • την επαλήθευση.

Μέρος B – Λύσεις και οδηγίες βήμα προς βήμα

13 / 23

Λύση 1: Επιλογή Workload Resource

Deployment για Web Server που εκτελείται συνεχώς

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

Job για Migration μίας εκτέλεσης

yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: migration
  namespace: workshop-intermediate
spec:
  template:
    spec:
      restartPolicy: OnFailure
      containers:
        - name: migration
          image: busybox:1.36
          command: ["sh", "-c", "echo Migration running; sleep 3; echo Migration complete"]

CronJob για Cleanup κάθε ώρα

yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: cleanup
  namespace: workshop-intermediate
spec:
  schedule: "0 * * * *"
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: cleanup
              image: busybox:1.36
              command: ["sh", "-c", "date; echo cleanup"]

Έλεγχος:

bash
kubectl apply -f deployment.yml
kubectl apply -f job.yml
kubectl apply -f cronjob.yml
kubectl get deployment,job,cronjob,pod
kubectl logs job/migration

Τεχνική απόφαση:

Απαίτηση Resource Αιτία
HTTP Service που εκτελείται συνεχώς Deployment Replicas, Rollouts και Rollbacks.
Migration μίας εκτέλεσης Job Η ολοκληρωμένη κατάσταση είναι ο τεχνικός στόχος.
Cleanup κάθε ώρα CronJob Δημιουργία Jobs βάσει χρονοδιαγράμματος.

14 / 23

Λύση 2: Init Container και Sidecar

Manifest:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
  namespace: workshop-intermediate
  labels:
    app: lifecycle-demo
spec:
  volumes:
    - name: shared
      emptyDir: {}
  initContainers:
    - name: init-write
      image: busybox:1.36
      command: ["sh", "-c", "echo prepared > /shared/init.txt"]
      volumeMounts:
        - name: shared
          mountPath: /shared
  containers:
    - name: app
      image: busybox:1.36
      command: ["sh", "-c", "while true; do cat /shared/init.txt; sleep 30; done"]
      volumeMounts:
        - name: shared
          mountPath: /shared
    - name: sidecar
      image: busybox:1.36
      command: ["sh", "-c", "while true; do date > /shared/heartbeat.txt; sleep 10; done"]
      volumeMounts:
        - name: shared
          mountPath: /shared

Έλεγχος:

bash
kubectl apply -f lifecycle-demo.yml
kubectl get pod lifecycle-demo
kubectl describe pod lifecycle-demo
kubectl logs lifecycle-demo -c init-write
kubectl logs lifecycle-demo -c app
kubectl exec lifecycle-demo -c app -- ls -l /shared
kubectl exec lifecycle-demo -c app -- cat /shared/heartbeat.txt

Εξήγηση:

  • Τα Init Containers εκτελούνται πριν από τα App Containers και πρέπει να ολοκληρωθούν επιτυχώς.
  • Τα Sidecars εκτελούνται παράλληλα με την εφαρμογή.
  • Το emptyDir μοιράζει αρχεία μέσα στο ίδιο Pod, αλλά δεν διατηρεί τα δεδομένα μετά τη διαγραφή του Pod.

15 / 23

Λύση 3: Σωστά Probes

Ανθεκτικό δοκιμαστικό Manifest:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: probe-demo
  namespace: workshop-intermediate
spec:
  replicas: 1
  selector:
    matchLabels:
      app: probe-demo
  template:
    metadata:
      labels:
        app: probe-demo
    spec:
      containers:
        - name: app
          image: registry.k8s.io/e2e-test-images/agnhost:2.53
          args: ["netexec", "--http-port=8080"]
          ports:
            - containerPort: 8080
          startupProbe:
            httpGet:
              path: /healthz
              port: 8080
            failureThreshold: 30
            periodSeconds: 2
          readinessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 2
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 10
            periodSeconds: 10

Έλεγχος:

bash
kubectl apply -f probe-demo.yml
kubectl rollout status deployment/probe-demo
kubectl describe pod -l app=probe-demo
kubectl get pods -w

Ενδεικτική εξήγηση:

  • Το Startup Probe προστατεύει τις αργές εκκινήσεις· όσο δεν επιτυγχάνει, τα Liveness και Readiness δεν είναι ενεργά.
  • Το Readiness καθορίζει αν ένα Pod περιλαμβάνεται στα Endpoints των Services.
  • Το Liveness καθορίζει αν το kubelet επανεκκινεί το Container.
  • Ένα υπερβολικά επιθετικό Liveness Probe δημιουργεί βρόχους επανεκκίνησης.

16 / 23

Λύση 4: Resources, QoS, LimitRange και ResourceQuota

LimitRange:

yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: defaults
  namespace: workshop-intermediate
spec:
  limits:
    - type: Container
      defaultRequest:
        cpu: 100m
        memory: 128Mi
      default:
        cpu: 500m
        memory: 256Mi
      max:
        cpu: "1"
        memory: 512Mi

ResourceQuota:

yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: namespace-quota
  namespace: workshop-intermediate
spec:
  hard:
    pods: "5"
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "3"
    limits.memory: 2Gi

Έλεγχος:

bash
kubectl apply -f limitrange.yml
kubectl apply -f quota.yml
kubectl describe limitrange defaults
kubectl describe resourcequota namespace-quota

Pod με Burstable QoS:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: burstable-pod
  namespace: workshop-intermediate
spec:
  containers:
    - name: app
      image: busybox:1.36
      command: ["sh", "-c", "sleep 3600"]
      resources:
        requests:
          cpu: 100m
          memory: 128Mi
        limits:
          cpu: 500m
          memory: 256Mi

Pod με Guaranteed QoS:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: guaranteed-pod
  namespace: workshop-intermediate
spec:
  containers:
    - name: app
      image: busybox:1.36
      command: ["sh", "-c", "sleep 3600"]
      resources:
        requests:
          cpu: 100m
          memory: 128Mi
        limits:
          cpu: 100m
          memory: 128Mi

Έλεγχος QoS:

bash
kubectl apply -f burstable-pod.yml
kubectl apply -f guaranteed-pod.yml
kubectl get pod burstable-pod -o jsonpath='{.status.qosClass}{"\n"}'
kubectl get pod guaranteed-pod -o jsonpath='{.status.qosClass}{"\n"}'

Προκαλέστε υπέρβαση Quota:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: too-large
  namespace: workshop-intermediate
spec:
  containers:
    - name: app
      image: busybox:1.36
      command: ["sh", "-c", "sleep 3600"]
      resources:
        requests:
          cpu: "2"
          memory: 2Gi
        limits:
          cpu: "2"
          memory: 2Gi

Αναμενόμενο αποτέλεσμα:

bash
kubectl apply -f too-large.yml

Ο API Server απορρίπτει το Resource λόγω του ResourceQuota.


17 / 23

Λύση 5: Scheduling

Επιλέξτε Node:

bash
NODE=$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')
kubectl label node "$NODE" workshop-role=apps
kubectl get nodes --show-labels | grep workshop-role

Pod με nodeSelector που ταιριάζει:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: scheduled-ok
  namespace: workshop-intermediate
spec:
  nodeSelector:
    workshop-role: apps
  containers:
    - name: app
      image: busybox:1.36
      command: ["sh", "-c", "sleep 3600"]

Pod με nodeSelector που δεν ταιριάζει:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: scheduled-pending
  namespace: workshop-intermediate
spec:
  nodeSelector:
    workshop-role: does-not-exist
  containers:
    - name: app
      image: busybox:1.36
      command: ["sh", "-c", "sleep 3600"]

Έλεγχος:

bash
kubectl apply -f scheduled-ok.yml
kubectl apply -f scheduled-pending.yml
kubectl get pods -o wide
kubectl describe pod scheduled-pending

Ορίστε Taint:

bash
kubectl taint node "$NODE" dedicated=apps:NoSchedule

Pod με Toleration:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: tolerated
  namespace: workshop-intermediate
spec:
  nodeSelector:
    workshop-role: apps
  tolerations:
    - key: dedicated
      operator: Equal
      value: apps
      effect: NoSchedule
  containers:
    - name: app
      image: busybox:1.36
      command: ["sh", "-c", "sleep 3600"]

Cleanup:

bash
kubectl delete pod scheduled-ok scheduled-pending tolerated --ignore-not-found
kubectl taint node "$NODE" dedicated=apps:NoSchedule-
kubectl label node "$NODE" workshop-role-

Εξήγηση:

  • Το nodeSelector είναι υποχρεωτική συνθήκη: χωρίς Node που να ταιριάζει, το Pod μένει Pending.
  • Ένα Taint αποκλείει Pods.
  • Ένα Toleration επιτρέπει σε Pod να ανεχθεί Taint· από μόνο του δεν επιβάλλει την τοποθέτηση.

18 / 23

Λύση 6: NetworkPolicy και DNS

Δοκιμαστική εφαρμογή:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  namespace: workshop-intermediate
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
        - name: backend
          image: registry.k8s.io/e2e-test-images/agnhost:2.53
          args: ["netexec", "--http-port=8080"]
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: backend
  namespace: workshop-intermediate
spec:
  selector:
    app: backend
  ports:
    - name: http
      port: 8080
      targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  namespace: workshop-intermediate
spec:
  replicas: 1
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
        - name: frontend
          image: curlimages/curl:8.8.0
          command: ["sh", "-c", "sleep 3600"]

Δοκιμή πριν από την Policy:

bash
kubectl apply -f net-demo.yml
kubectl wait --for=condition=Available deployment/backend --timeout=90s
kubectl wait --for=condition=Available deployment/frontend --timeout=90s
FRONTEND=$(kubectl get pod -l app=frontend -o jsonpath='{.items[0].metadata.name}')
kubectl exec "$FRONTEND" -- curl -s http://backend:8080/hostname

Default Deny:

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
  namespace: workshop-intermediate
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

Επιτρέψτε DNS Egress:

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns-egress
  namespace: workshop-intermediate
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53

Επιτρέψτε επικοινωνία Frontend προς Backend:

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: workshop-intermediate
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8080
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-egress-to-backend
  namespace: workshop-intermediate
spec:
  podSelector:
    matchLabels:
      app: frontend
  policyTypes:
    - Egress
  egress:
    - to:
        - podSelector:
            matchLabels:
              app: backend
      ports:
        - protocol: TCP
          port: 8080

Έλεγχος:

bash
kubectl apply -f default-deny.yml
kubectl apply -f allow-dns-egress.yml
kubectl apply -f allow-frontend-backend.yml
kubectl exec "$FRONTEND" -- nslookup backend
kubectl exec "$FRONTEND" -- curl -s --max-time 5 http://backend:8080/hostname

Σημείωση:

Τα NetworkPolicies λειτουργούν μόνο αν το CNI Plugin τα επιβάλλει.


19 / 23

Λύση 7: Ingress ή Gateway

Ελέγξτε αν υπάρχει Controller:

bash
kubectl get ingressclass
kubectl get gatewayclass 2>/dev/null || true
kubectl get pods -A | grep -Ei 'ingress|gateway|traefik|nginx|envoy|haproxy'

Παράδειγμα Ingress:

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
  namespace: workshop-intermediate
spec:
  rules:
    - host: web.localtest.me
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: backend
                port:
                  number: 8080

Έλεγχος:

bash
kubectl apply -f ingress.yml
kubectl describe ingress web
kubectl get ingress web

Παράδειγμα Gateway API, αν είναι εγκατεστημένο:

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: web
  namespace: workshop-intermediate
spec:
  parentRefs:
    - name: shared-gateway
      namespace: gateway-system
  hostnames:
    - web.localtest.me
  rules:
    - backendRefs:
        - name: backend
          port: 8080

Τεχνική εξήγηση:

  • Το Ingress περιγράφει μόνο κανόνες.
  • Ένας Ingress Controller πρέπει να μετατρέψει τον κανόνα σε Proxy ή Load Balancer Configuration.
  • Το Gateway API διαχωρίζει σαφέστερα την ευθύνη υποδομής από το Application Routing.

20 / 23

Λύση 8: PVC και StatefulSet

Ελέγξτε το StorageClass:

bash
kubectl get storageclass

StatefulSet:

yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: data-demo
  namespace: workshop-intermediate
spec:
  serviceName: data-demo
  replicas: 1
  selector:
    matchLabels:
      app: data-demo
  template:
    metadata:
      labels:
        app: data-demo
    spec:
      containers:
        - name: app
          image: busybox:1.36
          command: ["sh", "-c", "while true; do sleep 3600; done"]
          volumeMounts:
            - name: data
              mountPath: /data
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 1Gi

Εφαρμογή και δοκιμή:

bash
kubectl apply -f statefulset.yml
kubectl rollout status statefulset/data-demo
kubectl exec data-demo-0 -- sh -c 'echo persistence-test > /data/test.txt'
kubectl delete pod data-demo-0
kubectl wait --for=condition=Ready pod/data-demo-0 --timeout=120s
kubectl exec data-demo-0 -- cat /data/test.txt

Αναμενόμενη κατάσταση:

Το αρχείο εξακολουθεί να υπάρχει μετά την αναδημιουργία του Pod, επειδή το PVC προσαρτάται ξανά στο data-demo-0.

Ταξινόμηση:

  • Τα StatefulSets παρέχουν σταθερά Pod Names και σταθερή αντιστοίχιση PVC.
  • Ένα τοπικό Volume hostPath είναι βολικό σε Lab, αλλά δεν είναι φορητό ούτε αποτελεί Storage για Production.

21 / 23

Λύση 9: Helm και Kustomize

Δομή Kustomize:

text
kustomize-demo/
  base/
    deployment.yml
    service.yml
    kustomization.yml
  overlays/
    dev/
      kustomization.yml

base/kustomization.yml:

yaml
resources:
  - deployment.yml
  - service.yml

overlays/dev/kustomization.yml:

yaml
resources:
  - ../../base
namePrefix: dev-
labels:
  - pairs:
      environment: dev
images:
  - name: nginx
    newTag: "1.27"

Render:

bash
kubectl kustomize kustomize-demo/overlays/dev
kubectl apply -k kustomize-demo/overlays/dev --dry-run=server

Ελάχιστο Helm Chart:

bash
helm create webchart
helm template web ./webchart
helm lint ./webchart

Σύγκριση:

Κριτήριο Helm Kustomize
Μοντέλο Package με Templates και Values. Base/Overlay χωρίς Template Language.
Πλεονέκτημα Πολλές παράμετροι, Releases και οικοσύστημα Charts. Κοντά στο YAML, εύκολο Review.
Κίνδυνος Πολύπλοκα Templates μπορεί να είναι δύσκολο να επαληθευτούν. Τα Overlays μπορεί να γίνουν δυσνόητα.
Υποχρεωτικός έλεγχος helm template, helm lint. kubectl kustomize, dry-run.

22 / 23

Λύση 10: Διαδρομή Troubleshooting

Ενδεικτική διάγνωση:

Μοτίβο σφάλματος Διάγνωση Αιτία Διόρθωση
Pending kubectl describe pod Κανένα Node δεν ταιριάζει με το nodeSelector. Διορθώστε το Label ή αφαιρέστε τον Selector.
ImagePullBackOff Events του Pod Λάθος Image, Tag ή Registry. Ορίστε έγκυρο Image.
CrashLoopBackOff kubectl logs --previous Η διεργασία τερματίζεται με σφάλμα. Διορθώστε Startup Command ή Configuration της εφαρμογής.
PVC Pending kubectl describe pvc Λείπει StorageClass ή Provisioner. Διορθώστε ή διαθέστε StorageClass.
Service χωρίς Endpoints kubectl get endpoints, έλεγχος Labels Ο Selector δεν ταιριάζει. Διορθώστε τον Selector ή τα Pod Labels.

Τυπική ακολουθία:

bash
kubectl get all
kubectl get pod -o wide
kubectl describe pod <pod>
kubectl get events --sort-by=.metadata.creationTimestamp
kubectl logs <pod>
kubectl logs <pod> --previous
kubectl get svc,endpoints,endpointslices
kubectl describe pvc <pvc>

Cleanup

bash
kubectl delete namespace workshop-intermediate

Λίστα ελέγχου αξιολόγησης

Κριτήριο Ολοκληρώθηκε;
Τα Workload Resources διακρίθηκαν τεχνικά. ☐
Εξηγήθηκαν Init Container, Sidecar και App Container. ☐
Τα Probes διαχωρίστηκαν σωστά. ☐
Εφαρμόστηκαν Requests, Limits, QoS, LimitRange και Quota. ☐
Ερμηνεύτηκαν τα Scheduling Events. ☐
Εξετάστηκε NetworkPolicy που λαμβάνει υπόψη το DNS. ☐
Εξηγήθηκε ο ρόλος του Ingress/Gateway Controller. ☐
Δοκιμάστηκαν PVC και StatefulSet. ☐
Έγινε Render με Helm και Kustomize. ☐
Τεκμηριώθηκε η διαδρομή Troubleshooting. ☐
23 / 23

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.