Kubernetes Workshop: Fundamentals – Ασκήσεις με λύσεις
Αναφορά: Workshop Fundamentals
Επίπεδο δυσκολίας: Fundamentals
Μορφή: πρακτικό Lab με ενδεικτικές λύσεις και οδηγίες βήμα προς βήμα
Στόχος αυτού του εγγράφου ασκήσεων
Αυτό το έγγραφο συμπληρώνει το Workshop Fundamentals με συγκεκριμένες εργασίες, επαληθεύσιμα αποτελέσματα και πλήρεις λύσεις. Εστιάζει στην ασφαλή βασική λειτουργία, στο μοντέλο Kubernetes Objects, στο kubectl, στα Pods, Deployments, ReplicaSets, Services, Labels, Selectors, ConfigMaps, Secrets, Namespaces, Rollouts, Scaling, Rollback και στο αρχικό Troubleshooting.
Εργάζεστε αποκλειστικά σε Lab Cluster. Μη χρησιμοποιείτε Production Cluster Contexts ή πραγματικά Credentials.
Προαπαιτούμενα
Χρειάζεστε:
kubectl,- ένα τοπικό ή παρεχόμενο Kubernetes Cluster, για παράδειγμα
kind,minikubeήk3d, - ένα μη κρίσιμο Cluster Context,
- δικαιώματα εγγραφής στο δικό σας Namespace.
Προτεινόμενο Namespace για όλες τις ασκήσεις:
export NS=workshop-fundamentals
Κανόνες εργασίας
- Ελέγχετε το ενεργό Context πριν από κάθε άσκηση.
- Εργάζεστε μόνο στο Namespace
$NS. - Αποθηκεύετε τα Manifests ως αρχεία πριν τα εφαρμόσετε.
- Χρησιμοποιείτε
kubectl apply --dry-run=server, αν το Cluster σας το υποστηρίζει. - Μετά από κάθε αλλαγή ελέγχετε Status, Events και Logs.
- Τεκμηριώνετε το Cleanup στο τέλος.
Επισκόπηση ασκήσεων
| Αρ. | Θέμα | Αποτέλεσμα |
|---|---|---|
| 1 | Context, Cluster και Namespace | Ασφαλές Lab Context και Namespace. |
| 2 | Ανάγνωση του μοντέλου Objects | Εξηγημένο Deployment Manifest. |
| 3 | Deployment και Service | Απλή Web Application προσβάσιμη εσωτερικά. |
| 4 | Labels και Selectors | Διάγνωση και διόρθωση σφάλματος Service. |
| 5 | ConfigMap και Secret | Προσάρτηση Configuration και δοκιμαστικού Secret. |
| 6 | Rollout, Scaling και Rollback | Ενημέρωση Image, Scaling και Rollback ολοκληρωμένα. |
| 7 | Troubleshooting: ImagePullBackOff | Διάγνωση και διόρθωση λανθασμένου Image. |
| 8 | Troubleshooting: CrashLoopBackOff | Διάγνωση και διόρθωση εφαρμογής που τερματίζεται. |
| 9 | Λειτουργική σημείωση και Cleanup | Τεκμηρίωση Resources, επαλήθευσης και Cleanup. |
Μέρος A – Ασκήσεις
Άσκηση 1: Έλεγχος Context, Cluster και Namespace
Στόχος
Βεβαιωθείτε ότι εργάζεστε στο σωστό Cluster και δημιουργήστε το δικό σας Namespace.
Εργασία
- Ελέγξτε το ενεργό Context.
- Ελέγξτε τις πληροφορίες του Cluster και τα Nodes.
- Δημιουργήστε το Namespace
workshop-fundamentals. - Ορίστε αυτό το Namespace στο τρέχον Context.
- Τεκμηριώστε το όνομα του Cluster, τον αριθμό των Nodes και την Kubernetes Version.
Αναμενόμενο αποτέλεσμα
- Το Namespace υπάρχει.
- Το
kubectl get podsεμφανίζει εξ ορισμού Resources από τοworkshop-fundamentals. - Μπορείτε να εξηγήσετε γιατί ελέγχετε το Context πριν από κάθε Lab.
Άσκηση 2: Ανάγνωση του μοντέλου Kubernetes Objects
Στόχος
Διαβάστε ένα Deployment Manifest και εντοπίστε τα apiVersion, kind, metadata, spec, selector, Pod Template και Container Configuration.
Εργασία
Δημιουργήστε το αρχείο deployment.yml:
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
Απαντήστε γραπτώς:
- Ποιο API Group χρησιμοποιείται;
- Ποιο Resource δημιουργείται;
- Πού ορίζεται το Desired State;
- Ποια Labels λαμβάνουν τα Pods;
- Σε τι χρησιμοποιείται ο Selector;
Άσκηση 3: Rollout του Deployment και του Service
Στόχος
Εκτελέστε Rollout μιας απλής Web Application και κάντε την προσβάσιμη μέσω εσωτερικού ClusterIP Service.
Εργασία
- Εφαρμόστε το
deployment.yml. - Δημιουργήστε το αρχείο
service.yml:
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
- Εφαρμόστε το
service.yml. - Ελέγξτε Deployment, ReplicaSet, Pods, Service, Endpoints και EndpointSlices.
- Δοκιμάστε το Service με προσωρινό Debug Pod.
Αναμενόμενο αποτέλεσμα
- Εκτελούνται δύο Pods.
- Το Service έχει Endpoints.
- Ένα προσωρινό Pod μπορεί να συνδεθεί στο
http://web.
Άσκηση 4: Σκόπιμο σφάλμα σε Labels και Selectors
Στόχος
Κατανοήστε γιατί τα Services βρίσκουν Pods μέσω Labels και Selectors και όχι μέσω ονομάτων Pods.
Εργασία
- Αλλάξτε σκόπιμα τον Service Selector στο
service.ymlσε λανθασμένη τιμή:
selector:
app: wrong-web
- Εφαρμόστε την αλλαγή.
- Ελέγξτε Service, Endpoints και EndpointSlices.
- Επαναφέρετε τον Selector σε
app: web. - Ελέγξτε ξανά.
Αναμενόμενο αποτέλεσμα
- Με λανθασμένο Selector, το Service δεν έχει Endpoints.
- Μετά τη διόρθωση, υπάρχουν ξανά Endpoints.
Άσκηση 5: Προσάρτηση ConfigMap και Secret
Στόχος
Διακρίνετε το μη ευαίσθητο Configuration από τις ευαίσθητες δοκιμαστικές τιμές και προσαρτήστε και τα δύο σε ένα Pod.
Εργασία
Δημιουργήστε το configmap.yml:
apiVersion: v1
kind: ConfigMap
metadata:
name: web-config
namespace: workshop-fundamentals
data:
APP_MODE: lab
WELCOME_TEXT: "Hello from Kubernetes"
Δημιουργήστε το secret.yml:
apiVersion: v1
kind: Secret
metadata:
name: web-secret
namespace: workshop-fundamentals
type: Opaque
stringData:
DEMO_PASSWORD: "not-a-real-secret"
Επεκτείνετε το Deployment ώστε το APP_MODE να διατίθεται ως Environment Variable και το DEMO_PASSWORD ως αρχείο.
Αναμενόμενο αποτέλεσμα
- Το ConfigMap υπάρχει.
- Το Secret υπάρχει.
- Το Pod περιέχει το
APP_MODEως Environment Variable. - Το Secret είναι διαθέσιμο ως αρχείο μέσα στο Container.
Άσκηση 6: Rollout, Scaling και Rollback
Στόχος
Χρησιμοποιήστε τα Deployment Rollouts με ελεγχόμενο τρόπο και επαναφέρετε μια αλλαγή.
Εργασία
- Ελέγξτε το τρέχον Rollout Status.
- Αυξήστε τα Replicas του Deployment σε τρία.
- Αλλάξτε το Image από
nginx:1.27σεnginx:1.26. - Ελέγξτε το Rollout Status και το Rollout History.
- Εκτελέστε Rollback.
- Ελέγξτε ποιο Image είναι ενεργό μετά το Rollback.
Αναμενόμενο αποτέλεσμα
- Εκτελούνται τρία Pods.
- Το Rollout History εμφανίζει τουλάχιστον δύο Revisions.
- Μετά το Rollback εκτελείται ξανά το προηγούμενο Image.
Άσκηση 7: Διάγνωση του ImagePullBackOff
Στόχος
Προκαλέστε σφάλμα Image Pull και διορθώστε το με βάση τα Events.
Εργασία
Δημιουργήστε το bad-image.yml:
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
- Εφαρμόστε το Manifest.
- Ελέγξτε το Pod Status και τα Events.
- Διορθώστε το Image σε
nginx:1.27. - Ελέγξτε ξανά.
Άσκηση 8: Διάγνωση του CrashLoopBackOff
Στόχος
Προκαλέστε τερματισμό μιας εφαρμογής, διαβάστε τα Logs και διορθώστε το Startup Command.
Εργασία
Δημιουργήστε το crashloop.yml:
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 'I terminate immediately'; exit 1"]
- Εφαρμόστε το Manifest.
- Ελέγξτε το Pod Status.
- Διαβάστε τα Logs και τα προηγούμενα Logs.
- Διορθώστε το Command ώστε το Container να συνεχίσει να εκτελείται.
- Ελέγξτε ξανά.
Άσκηση 9: Λειτουργική σημείωση και Cleanup
Στόχος
Τεκμηριώστε τι δημιουργήθηκε, πώς επαληθεύσατε την κατάσταση και πώς καθαρίζονται όλα τα Resources.
Εργασία
Δημιουργήστε το notes.md με:
- το Cluster Context,
- το Namespace,
- τα Manifests που εφαρμόστηκαν,
- τα Resources που δημιουργήθηκαν,
- τις σημαντικότερες εντολές διάγνωσης,
- τα γνωστά σφάλματα και τις διορθώσεις τους,
- την εντολή Cleanup.
Μέρος B – Λύσεις και οδηγίες βήμα προς βήμα
Λύση 1: Έλεγχος Context, Cluster και Namespace
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
Επαλήθευση:
kubectl get namespace workshop-fundamentals
kubectl config view --minify --output 'jsonpath={..namespace}'
Ενδεικτική εξήγηση:
- Το Context καθορίζει με ποιο Cluster επικοινωνεί το
kubectl. - Το Namespace περιορίζει την προεπιλεγμένη προβολή του
kubectl, αλλά δεν αντικαθιστά την απομόνωση ασφαλείας. - Το
kubectl cluster-infoδείχνει αν το API είναι προσβάσιμο. - Το
kubectl get nodes -o wideδείχνει την κατάσταση των Nodes και το Runtime Environment.
Λύση 2: Ανάγνωση του μοντέλου Kubernetes Objects
Ενδεικτικές απαντήσεις:
| Ερώτηση | Απάντηση |
|---|---|
| API Group | apps/v1· Resource από το Apps API Group. |
| Resource | Deployment. |
| Desired State | Ορίζεται στο spec. |
| Pod Labels | app=web, tier=frontend, environment=lab. |
| Selector | Συνδέει το Deployment με τα Pods που διαχειρίζεται. |
Χρήσιμη διερεύνηση:
kubectl explain deployment
kubectl explain deployment.spec
kubectl explain deployment.spec.template.spec.containers
kubectl api-resources | grep -i deployment
Λύση 3: Rollout του Deployment και του Service
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
Έλεγχος:
kubectl get deployment,replicaset,pod,svc,endpoints,endpointslices
kubectl describe deployment web
kubectl describe svc web
Δοκιμή του Service:
kubectl run curl --rm -i --tty --restart=Never --image=curlimages/curl:8.8.0 -- http://web
Εναλλακτική, αν το διαδραστικό kubectl run συμπεριφέρεται διαφορετικά στο περιβάλλον σας:
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
Αναμενόμενη κατάσταση:
- Το
deployment.apps/webείναι Available. - Το
service/webέχει ClusterIP. - Το
endpoints/webπεριέχει Pod IP Addresses.
Λύση 4: Διόρθωση Labels και Selectors
Εφαρμόστε τον λανθασμένο Selector:
kubectl apply -f service.yml
kubectl get svc,endpoints,endpointslices
kubectl describe svc web
Τυπικό σύμπτωμα:
Endpoints: <none>
Διάγνωση:
kubectl get pods --show-labels
kubectl get svc web -o yaml
Διόρθωση στο service.yml:
selector:
app: web
Έπειτα:
kubectl apply -f service.yml
kubectl get endpoints web
kubectl get endpointslices -l kubernetes.io/service-name=web
Τεχνική εξήγηση:
Ένα Service δεν γνωρίζει σταθερά ονόματα Pods. Βρίσκει Pods μέσω του Selector. Αν ο Selector δεν ταιριάζει με τα Pod Labels, το Service υπάρχει, αλλά δεν έχει Targets.
Λύση 5: Προσάρτηση ConfigMap και Secret
Εφαρμόστε το ConfigMap και το Secret:
kubectl apply -f configmap.yml
kubectl apply -f secret.yml
kubectl get configmap,secret
Επέκταση του Deployment:
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
Εφαρμογή και έλεγχος:
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
Τεχνική ταξινόμηση:
- Τα ConfigMaps προορίζονται για μη ευαίσθητο Configuration.
- Τα Secrets προορίζονται για ευαίσθητες τιμές, αλλά το Base64 δεν είναι Encryption.
- Πραγματικά Secrets δεν ανήκουν σε εκπαιδευτικά Manifests ή σε αρχεία Plaintext υπό Version Control.
Λύση 6: Rollout, Scaling και Rollback
Έλεγχος Status:
kubectl rollout status deployment/web
kubectl get deployment web
Scaling:
kubectl scale deployment/web --replicas=3
kubectl rollout status deployment/web
kubectl get pods -l app=web
Αλλαγή Image:
kubectl set image deployment/web nginx=nginx:1.26
kubectl rollout status deployment/web
kubectl rollout history deployment/web
Έλεγχος του ενεργού Image:
kubectl get deployment web -o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'
Rollback:
kubectl rollout undo deployment/web
kubectl rollout status deployment/web
kubectl get deployment web -o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'
Ενδεικτική εξήγηση:
- Το
scaleαλλάζει τοspec.replicas. - Το
set imageαλλάζει το Pod Template και συνεπώς δημιουργεί νέο Revision. - Το
rollout undoεπαναφέρει το προηγούμενο Revision ως Desired State.
Λύση 7: ImagePullBackOff
Εφαρμογή:
kubectl apply -f bad-image.yml
kubectl get pods -l app=bad-image
Διάγνωση:
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
Τυπικό εύρημα:
- Το Image Tag δεν υπάρχει.
- Τα Events περιέχουν μηνύματα
Failed to pull imageήErrImagePull.
Διόρθωση:
kubectl set image deployment/bad-image app=nginx:1.27
kubectl rollout status deployment/bad-image
kubectl get pods -l app=bad-image
Εναλλακτικά, διορθώστε το αρχείο και εφαρμόστε το ξανά:
sed -i 's/nginx:this-tag-does-not-exist/nginx:1.27/' bad-image.yml
kubectl apply -f bad-image.yml
Λύση 8: CrashLoopBackOff
Εφαρμογή:
kubectl apply -f crashloop.yml
kubectl get pods -l app=crashloop
Διάγνωση:
POD=$(kubectl get pod -l app=crashloop -o jsonpath='{.items[0].metadata.name}')
kubectl describe pod "$POD"
kubectl logs "$POD"
kubectl logs "$POD" --previous
Τυπικό εύρημα:
- Το Container εκκινεί.
- Το Command τερματίζεται με Exit Code
1. - Το Kubernetes το επανεκκινεί· έτσι προκύπτει το
CrashLoopBackOff.
Διόρθωση μέσω Manifest:
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 'I stay active'; sleep 3600"]
Εφαρμογή:
kubectl apply -f crashloop.yml
kubectl rollout status deployment/crashloop
kubectl get pods -l app=crashloop
Λύση 9: Λειτουργική σημείωση και Cleanup
Πρότυπο για το notes.md:
# Operations Note – Fundamentals Lab
## Context
- Cluster Context: <από kubectl config current-context>
- Namespace: workshop-fundamentals
- Ημερομηνία: <συμπληρώστε ημερομηνία>
## Manifests
- deployment.yml
- service.yml
- configmap.yml
- secret.yml
- bad-image.yml
- crashloop.yml
## Επαλήθευση
- kubectl get deployment,rs,pod,svc,endpoints,endpointslices
- kubectl rollout status deployment/web
- kubectl describe pod <pod>
- kubectl logs <pod>
## Σφάλματα και διορθώσεις
| Σφάλμα | Αιτία | Διόρθωση |
| --- | --- | --- |
| Service χωρίς Endpoints | Λανθασμένος Selector | Επαναφορά του Selector σε app=web. |
| ImagePullBackOff | Μη έγκυρο Image Tag | Αλλαγή Image σε nginx:1.27. |
| CrashLoopBackOff | Η διεργασία τερματίζεται με Exit Code 1 | Αλλαγή Command σε sleep 3600. |
## Cleanup
kubectl delete namespace workshop-fundamentals
Cleanup:
kubectl delete namespace workshop-fundamentals
Επαλήθευση μετά το Cleanup:
kubectl get namespace workshop-fundamentals
Αναμενόμενη κατάσταση: Το Namespace έχει διαγραφεί ή παραμένει για λίγο σε κατάσταση Terminating.
Λίστα ελέγχου αξιολόγησης
| Κριτήριο | Ολοκληρώθηκε; |
|---|---|
| Το Context ελέγχθηκε πριν από τις αλλαγές | ☐ |
| Χρησιμοποιήθηκε ξεχωριστό Namespace | ☐ |
| Το Deployment Manifest εξηγήθηκε | ☐ |
| Δημιουργήθηκε Service με Endpoints | ☐ |
| Διαγνώστηκε το σφάλμα Selector | ☐ |
| Το ConfigMap και το Secret προσαρτήθηκαν σωστά | ☐ |
| Εκτελέστηκαν Rollout, Scaling και Rollback | ☐ |
Το ImagePullBackOff εξηγήθηκε με βάση τα Events |
☐ |
Το CrashLoopBackOff εξηγήθηκε με βάση τα Logs |
☐ |
| Το Cleanup τεκμηριώθηκε | ☐ |