Τύποι υπηρεσιών Kubernetes — εξαιρετικά περιεκτικός οδηγός

13 λεπτά

Έργο projet11-kubernetes-services · Έγγραφο αναφοράς σε βάθος.

Αυτό το έγγραφο πηγαίνει πολύ πιο μακριά από τη διόρθωση: αναλύει όλους τους τύπους Services, τις εσωτερικές έννοιες (kube-proxy, Endpoints, EndpointSlices, DNS), τα σημαντικά πεδία YAML, τις πολιτικές κίνησης, το session affinity, το multi-port, τις κλασικές παγίδες και τις καλές πρακτικές.

Πίνακας περιεχομένων

  1. Υπενθύμιση: ο ρόλος ενός Service
  2. Ανατομία ενός Service (όλα τα πεδία)
  3. Τύπος 1 — ClusterIP
  4. Τύπος 2 — NodePort
  5. Τύπος 3 — LoadBalancer
  6. Τύπος 4 — ExternalName
  7. Service Headless (χωρίς ClusterIP)
  8. Service χωρίς επιλογέα (χειροκίνητα Endpoints)
  9. port vs targetPort vs nodePort
  10. Multi-port και ονομασμένες θύρες
  11. Πώς λειτουργεί κάτω από το καπό: kube-proxy
  12. Endpoints και EndpointSlices
  13. Το DNS των Services (CoreDNS)
  14. Πολιτικές κίνησης (externalTrafficPolicy / internalTrafficPolicy)
  15. Session affinity
  16. Πρωτόκολλα: TCP, UDP, SCTP, appProtocol
  17. Service vs Ingress vs Gateway API
  18. Συνοπτικός πίνακας των τύπων
  19. Κλασικές παγίδες και αντιμετώπιση προβλημάτων
  20. Καλές πρακτικές
  21. Μίνι-ασκήσεις

1. Υπενθύμιση: ο ρόλος ενός Service

Ένα Pod είναι εφήμερο: μπορεί να αναδημιουργηθεί ανά πάσα στιγμή, με νέα IP. Δεν μπορούμε λοιπόν να βασιστούμε στην IP ενός Pod για επικοινωνία.

Ένα Service είναι μια σταθερή αφαίρεση που:

  • παρέχει μια μόνιμη ταυτότητα δικτύου (μια εικονική IP και/ή ένα όνομα DNS)·
  • επιλέγει ένα σύνολο Pods μέσω των ετικετών τους·
  • κατανέμει την κίνηση (load balancing) μεταξύ αυτών των Pods·
  • ενημερώνεται αυτόματα όταν τα Pods εμφανίζονται ή εξαφανίζονται.

Κεντρική ιδέα: το Service δεν «περιέχει» τα Pods. Τα ξαναβρίσκει συνεχώς χάρη στον επιλογέα ετικετών, και διατηρεί τη λίστα των διευθύνσεών τους στα Endpoints.


2. Ανατομία ενός Service (όλα τα πεδία)

yaml
apiVersion: v1
kind: Service
metadata:
  name: mon-service
  labels:
    app: demo
  annotations: {}               # μεταδεδομένα (συχνά χρησιμοποιούνται από τους LoadBalancer cloud)
spec:
  type: ClusterIP               # ClusterIP | NodePort | LoadBalancer | ExternalName
  selector:                     # ποια Pods στοχεύει αυτό το Service (ανά ετικέτες)
    app: demo
  ports:
    - name: http                # όνομα της θύρας (χρήσιμο αν υπάρχουν πολλές θύρες)
      protocol: TCP             # TCP (προεπιλογή) | UDP | SCTP
      port: 80                  # θύρα του Service (αυτό που βλέπουν οι πελάτες)
      targetPort: 5000          # θύρα του κοντέινερ (ή όνομα θύρας του κοντέινερ)
      nodePort: 30080           # (NodePort/LoadBalancer) θύρα ανοιχτή στον κόμβο
  clusterIP: 10.96.0.10         # (προαιρετικό) σταθερή IP· "None" = headless
  sessionAffinity: None         # None | ClientIP
  externalTrafficPolicy: Cluster  # Cluster | Local (NodePort/LoadBalancer)
  internalTrafficPolicy: Cluster  # Cluster | Local
  ipFamilyPolicy: SingleStack   # SingleStack | PreferDualStack | RequireDualStack
  externalIPs: []               # εξωτερικές IP δρομολογημένες προς αυτό το Service (προχωρημένο)

Κάθε πεδίο αναλύεται παρακάτω. Μπορούμε να δημιουργήσουμε ένα ελάχιστο Service σε 8 γραμμές· όλα τα άλλα πεδία έχουν λογικές προεπιλεγμένες τιμές.


3. Τύπος 1 — ClusterIP

Ο προεπιλεγμένος τύπος. Αποδίδει μια εσωτερική εικονική IP (στο εύρος Service CIDR, π.χ. 10.96.0.0/12), προσβάσιμη μόνο από το εσωτερικό του συμπλέγματος.

yaml
apiVersion: v1
kind: Service
metadata:
  name: demo-clusterip
spec:
  type: ClusterIP
  selector:
    app: demo-back
  ports:
    - port: 80
      targetPort: 5000

Χαρακτηριστικά:

  • Απρόσιτο από έξω (χωρίς EXTERNAL-IP).
  • Βάση της εσωτερικής επικοινωνίας (frontend → backend, εφαρμογή → βάση δεδομένων, μικροϋπηρεσίες μεταξύ τους).
  • Προσβάσιμο με όνομα DNS: http://demo-clusterip (βλ. §13).

Πότε να το χρησιμοποιήσετε: για ό,τι μένει μέσα στο σύμπλεγμα. Είναι ο πιο συνηθισμένος τύπος.


4. Τύπος 2 — NodePort

Κάνει όλα όσα κάνει το ClusterIP (λαμβάνει μια εσωτερική IP), συν: ανοίγει μια στατική θύρα σε κάθε κόμβο του συμπλέγματος (προεπιλεγμένο εύρος 30000–32767).

yaml
apiVersion: v1
kind: Service
metadata:
  name: demo-nodeport
spec:
  type: NodePort
  selector:
    app: demo-back
  ports:
    - port: 80          # θύρα του Service (εσωτερική)
      targetPort: 5000  # θύρα του κοντέινερ
      nodePort: 30082   # θύρα ανοιχτή σε ΚΑΘΕ κόμβο

Πρόσβαση: http://<ip-de-n-importe-quel-noeud>:30082 (με Docker Desktop: http://localhost:30082).

Σημαντικά σημεία:

  • Αν δεν ορίσετε nodePort, το Kubernetes επιλέγει μία στο εύρος.
  • Η ίδια θύρα είναι ανοιχτή σε όλους τους κόμβους (χάρη στο routing mesh / kube-proxy), ακόμη και σε εκείνους που δεν φιλοξενούν κανένα Pod του Service.
  • Λίγο κομψό για παραγωγή (μη τυπικές θύρες, χειροκίνητη διαχείριση), αλλά ιδανικό σε dev/τοπικό και συχνά το δομικό στοιχείο κάτω από έναν LoadBalancer.

5. Τύπος 3 — LoadBalancer

Κάνει όλα όσα κάνει το NodePort, συν: ζητά από την υποδομή (το νέφος) να προμηθεύσει έναν εξωτερικό εξισορροπητή φορτίου με δημόσια IP.

yaml
apiVersion: v1
kind: Service
metadata:
  name: demo-lb
spec:
  type: LoadBalancer
  selector:
    app: demo-back
  ports:
    - port: 8090
      targetPort: 5000

Ανάλογα με το περιβάλλον:

ΠεριβάλλονΣυμπεριφορά
AWS / GCP / AzureΔημιουργεί έναν πραγματικό διαχειριζόμενο LB (ELB/NLB, GCP LB…) και γεμίζει το EXTERNAL-IP
Docker DesktopEXTERNAL-IP = localhosthttp://localhost:8090
minikubeminikube tunnel παρέχει την εξωτερική IP
kind / bare-metalΜένει <pending> χωρίς ελεγκτή όπως το MetalLB

Πλήρης αλυσίδα: LoadBalancer → NodePort → ClusterIP → Endpoints → Pods.

Οι σχολιασμοί (ειδικοί ανά πάροχο) κατευθύνουν τον LB, π.χ. στο AWS:

yaml
metadata:
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
    service.beta.kubernetes.io/aws-load-balancer-internal: "true"

Ένας LoadBalancer ανά υπηρεσία = ακριβός στο νέφος. Στην παραγωγή, προτιμάμε συχνά ένα μόνο σημείο εισόδου (Ingress/Gateway) μπροστά από πολλές υπηρεσίες (βλ. §17).


6. Τύπος 4 — ExternalName

Ιδιαίτερη περίπτωση: κανένας επιλογέας, κανένα Pod, καμία IP. Δημιουργεί απλώς ένα ψευδώνυμο DNS (εγγραφή CNAME) προς ένα εξωτερικό όνομα.

yaml
apiVersion: v1
kind: Service
metadata:
  name: base-externe
spec:
  type: ExternalName
  externalName: db.exemple.com     # τα Pods που καλούν "base-externe" ανακατευθύνονται εδώ

Χρήση: να δείχνει ένα σταθερό εσωτερικό όνομα (base-externe) προς μια υπηρεσία ή εκτός συμπλέγματος (διαχειριζόμενη βάση, API τρίτου). Αν η διεύθυνση αλλάξει, τροποποιούμε ένα μόνο σημείο.

Όριο: είναι καθαρό DNS, χωρίς κατανομή φορτίου ούτε έλεγχο θύρας. Δεν ταιριάζει αν η εξωτερική υπηρεσία περιμένει ένα συγκεκριμένο HTTP Host.


7. Service Headless (χωρίς ClusterIP)

Θέτοντας clusterIP: None, λαμβάνουμε ένα Service χωρίς εικονική IP. Το DNS επιστρέφει τότε απευθείας τις IP όλων των Pods (λίστα εγγραφών A), αντί για μία μοναδική IP.

yaml
apiVersion: v1
kind: Service
metadata:
  name: demo-headless
spec:
  clusterIP: None        # <-- headless
  selector:
    app: demo-back
  ports:
    - port: 80
      targetPort: 5000

Σε τι χρησιμεύει:

  • Όταν ο πελάτης θέλει να δει κάθε Pod ξεχωριστά (χωρίς κεντρικό LB).
  • Απαραίτητο για τα StatefulSet: κάθε Pod λαμβάνει ένα σταθερό όνομα DNS (pod-0.demo-headless, pod-1.demo-headless…), χρήσιμο για αναπαραγόμενες βάσεις (Cassandra, Kafka, κ.λπ.).
Κανονικό ClusterIPHeadless (clusterIP: None)
Εικονική IPΝαι (μία μόνο)Όχι
Απάντηση DNS1 IP (του Service)N IP (των Pods)
ΚατανομήΑπό το kube-proxyΣτην ευθύνη του πελάτη
Περίπτωση χρήσηςWeb/API χωρίς κατάστασηΑναπαραγόμενες βάσεις, StatefulSet

8. Service χωρίς επιλογέα (χειροκίνητα Endpoints)

Ένα Service μπορεί να μην έχει επιλογέα. Σε αυτή την περίπτωση, το Kubernetes δεν γεμίζει μόνο του τα Endpoints: εσείς τα ορίζετε χειροκίνητα. Πρακτικό για να εκθέσετε έναν εξωτερικό πόρο κάτω από μια σταθερή εσωτερική IP.

yaml
apiVersion: v1
kind: Service
metadata:
  name: api-legacy
spec:
  ports:
    - port: 80
      targetPort: 8080
---
apiVersion: v1
kind: Endpoints           # (ή EndpointSlice, πιο σύγχρονο)
metadata:
  name: api-legacy         # ΙΔΙΟ όνομα με το Service
subsets:
  - addresses:
      - ip: 192.168.1.50   # εξωτερικός διακομιστής
    ports:
      - port: 8080

Διαφορά με το ExternalName: εδώ δρομολογούμε ανά IP (με δυνατότητα load balancing σε πολλές IP), όχι με CNAME DNS.


9. port vs targetPort vs nodePort

Αυτή είναι η πηγή σύγχυσης. Τρεις διαφορετικές θύρες, τρεις ρόλοι:

ΠεδίοΠούΣημασία
portΣτο ServiceΗ θύρα που χρησιμοποιούν οι πελάτες για να φτάσουν το Service
targetPortΣτο κοντέινερΗ θύρα όπου ακούει πραγματικά η εφαρμογή στο Pod
nodePortΣτον κόμβο(NodePort/LoadBalancer) η θύρα ανοιχτή στο μηχάνημα

Παράδειγμα διαβασμένο φωναχτά: «οι πελάτες χτυπούν τη θύρα 80 του Service, που μεταβιβάζει στη θύρα 5000 του κοντέινερ· σε NodePort, εισερχόμαστε επίσης από τη θύρα 30082 του μηχανήματος».

Το targetPort μπορεί να αναφέρεται σε ένα όνομα θύρας ορισμένο στο κοντέινερ (βλ. §10), ώστε να μην κωδικοποιούμε τον αριθμό στα σκληρά.


10. Multi-port και ονομασμένες θύρες

Ένα Service μπορεί να εκθέσει πολλές θύρες (π.χ. HTTP + μετρικές). Σε αυτή την περίπτωση, κάθε εγγραφή πρέπει να έχει name.

yaml
spec:
  selector:
    app: demo
  ports:
    - name: http
      port: 80
      targetPort: web          # αναφορά σε ΟΝΟΜΑΣΜΕΝΗ θύρα του κοντέινερ
    - name: metrics
      port: 9090
      targetPort: 9090

Στην πλευρά του κοντέινερ, ονομάζουμε τις θύρες:

yaml
containers:
  - name: app
    ports:
      - name: web              # <-- επαναχρησιμοποιείται από targetPort: web
        containerPort: 5000
      - name: metrics
        containerPort: 9090

Πλεονέκτημα των ονομασμένων θυρών: αν αλλάξει η θύρα του κοντέινερ, δεν αλλάζουμε τίποτα στο Service.


11. Πώς λειτουργεί κάτω από το καπό: kube-proxy

Το Service είναι ένα αφηρημένο αντικείμενο: δεν είναι μια διεργασία που δέχεται κίνηση. Η μαγεία γίνεται από το kube-proxy, ένα στοιχείο παρόν σε κάθε κόμβο, που προγραμματίζει τους κανόνες δικτύου του πυρήνα ώστε να ανακατευθύνει «IP:port του Service» προς «IP:port ενός Pod».

Λειτουργίες του kube-proxy:

ΛειτουργίαΑρχήΣημειώσεις
iptables (προεπιλογή)Κανόνες iptables, τυχαία επιλογή ενός PodΑπλό, στιβαρό, πολύ διαδεδομένο
IPVSΠίνακας κατακερματισμού πυρήνα, πραγματικοί αλγόριθμοι LB (rr, lc, sh…)Πιο αποδοτικό σε μεγάλα συμπλέγματα
nftablesΔιάδοχος του iptablesΠιο πρόσφατο

Πρακτικές συνέπειες:

  • Η κατανομή iptables είναι τυχαία (όχι αληθινό διατεταγμένο round-robin).
  • Το kube-proxy δεν βλέπει το στρώμα HTTP: είναι L3/L4 (IP/port). Για HTTP δρομολόγηση (ανά διαδρομή, ανά host), χρειάζεται Ingress (§17).

12. Endpoints και EndpointSlices

Ο δεσμός Service ↔ Pods υλοποιείται από αντικείμενα:

  • Endpoints (ιστορικό): ένα μόνο αντικείμενο που απαριθμεί όλα τα IP:port των έτοιμων Pods.
  • EndpointSlices (σύγχρονο, συνιστώμενο): η λίστα κόβεται σε φέτες (μέγ. ~100 endpoints η καθεμία) → πολύ καλύτερη κλιμάκωση σε μεγάλες υπηρεσίες.
bash
kubectl get endpoints demo-clusterip
kubectl get endpointslices -l kubernetes.io/service-name=demo-clusterip

Ποιος ενημερώνει τη λίστα; Ο endpoint controller: μόλις ένα Pod γίνει Ready (readinessProbe OK) και αντιστοιχεί στον επιλογέα, η IP του εισέρχεται· αν πέσει, βγαίνει.

Ένα Pod μη Ready αφαιρείται από τα Endpoints → δεν λαμβάνει κίνηση. Γι' αυτό το readinessProbe είναι ουσιώδες: ελέγχει ποιος είναι «μέσα» στο Service. (Εξαίρεση: publishNotReadyAddresses: true δημοσιεύει και τα μη έτοιμα Pods — ειδική χρήση headless.)


13. Το DNS των Services (CoreDNS)

Το Kubernetes εκτελεί το CoreDNS. Κάθε Service λαμβάνει ένα ντετερμινιστικό όνομα DNS:

<service>                                   # ίδιος χώρος ονομάτων
<service>.<namespace>                        # άλλος χώρος ονομάτων
<service>.<namespace>.svc.cluster.local      # πλήρες FQDN

Παράδειγμα από ένα Pod:

bash
curl http://demo-clusterip                       # ίδιος χώρος ονομάτων
curl http://demo-clusterip.default               # ρητό
curl http://demo-clusterip.default.svc.cluster.local

Εγγραφές που παράγονται:

  • Κανονικό Service → μία εγγραφή A προς το ClusterIP.
  • Service headlessπολλές A, μία ανά Pod.
  • Ονομασμένες θύρες → εγγραφές SRV: _http._tcp.demo-clusterip….
  • ExternalNameCNAME προς τον στόχο.

Ιστορικά, το Kubernetes εισήγε επίσης μεταβλητές περιβάλλοντος (DEMO_CLUSTERIP_SERVICE_HOST, ..._PORT) στα Pods που δημιουργήθηκαν μετά το Service. Το DNS παραμένει η συνιστώμενη μέθοδος (λειτουργεί ανεξάρτητα από τη σειρά δημιουργίας).


14. Πολιτικές κίνησης

externalTrafficPolicy (εισερχόμενη εξωτερική κίνηση, NodePort/LoadBalancer)

ΤιμήΑποτέλεσμαΣυμβιβασμός
Cluster (προεπιλογή)Η κίνηση μπορεί να ανακατευθυνθεί σε άλλον κόμβο για να φτάσει ένα PodΚαλή κατανομή, αλλά η IP πηγής του πελάτη καλύπτεται (SNAT) και ένα επιπλέον άλμα δικτύου
LocalΕξυπηρετεί μόνο τα Pods του κόμβου που δέχεται το πακέτοΔιατηρεί την IP πηγής του πελάτη, χωρίς άλμα· αλλά ανισορροπία αν τα Pods είναι κακά κατανεμημένα

internalTrafficPolicy (εσωτερική κίνηση, μεταξύ Pods)

ΤιμήΑποτέλεσμα
Cluster (προεπιλογή)Δρομολογεί προς οποιοδήποτε Pod του Service
LocalΔρομολογεί μόνο προς τα Pods του ίδιου κόμβου (χρήσιμο για καθυστέρηση / τοπικότητα)

Το externalTrafficPolicy: Local είναι η κρίσιμη ρύθμιση όταν χρειάζεστε να γνωρίζετε την πραγματική IP του πελάτη (ημερολόγια, ασφάλεια, γεωεντοπισμός).


15. Session affinity

Από προεπιλογή, κάθε αίτημα μπορεί να πάει σε οποιοδήποτε Pod. Για να «κολλήσει» ένας πελάτης στο ίδιο Pod:

yaml
spec:
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800     # 3 ώρες
  • None (προεπιλογή): κατανομή σε κάθε αίτημα.
  • ClientIP: όλα τα αιτήματα της ίδιας IP πηγαίνουν στο ίδιο Pod (βασικά sticky sessions L4).

Για λεπτότερες HTTP συνεδρίες (ανά cookie), χρησιμοποιούμε μάλλον ένα Ingress (L7).


16. Πρωτόκολλα: TCP, UDP, SCTP, appProtocol

  • protocol: TCP (προεπιλογή), UDP (DNS, παιχνίδια, ροή), SCTP (τηλεπικοινωνίες).
  • Μπορούμε να αναμείξουμε πολλά πρωτόκολλα στο ίδιο Service (διακριτές θύρες).
  • Το appProtocol (ενδεικτικό) διευκρινίζει το πρωτόκολλο εφαρμογής (http, https, grpc) για τα εργαλεία/LB.
yaml
ports:
  - name: dns-udp
    port: 53
    protocol: UDP
    targetPort: 53
  - name: dns-tcp
    port: 53
    protocol: TCP
    targetPort: 53

17. Service vs Ingress vs Gateway API

Ένα Service εργάζεται σε L4 (IP/port). Δεν ξέρει να δρομολογεί ανά URL, όνομα κεντρικού υπολογιστή, ούτε να διαχειρίζεται TLS. Για αυτό:

ΑντικείμενοΣτρώμαΡόλος
Service (ClusterIP/NodePort/LB)L3/L4Σταθερή διεύθυνση + απλό LB προς Pods
IngressL7 (HTTP/HTTPS)Δρομολόγηση ανά host και διαδρομή, TLS, ένα σημείο εισόδου για πολλές υπηρεσίες
Gateway APIL7 (διάδοχος του Ingress)Πιο εκφραστικό, διαχωρισμός ρόλων, πολλαπλά πρωτόκολλα

Τυπικό μοντέλο παραγωγής: ένας μόνο LoadBalancer → Ingress → πολλά εσωτερικά ClusterIP. Εξοικονομούμε ακριβούς LB και συγκεντρώνουμε TLS/δρομολόγηση.


18. Συνοπτικός πίνακας των τύπων

ΤύποςΕσωτερική IPΕξωτερική πρόσβασηDNSΕπιλογέαςΠερίπτωση χρήσης
ClusterIPΝαιΌχι1 A (ClusterIP)ΝαιΕσωτερική επικοινωνία (το πιο συνηθισμένο)
NodePortΝαιΘύρα του κόμβου1 AΝαιDev/τοπικό, δομικό στοιχείο ενός LB
LoadBalancerΝαιΔημόσια IP1 AΝαιΔημόσια υπηρεσία στο νέφος
ExternalNameΌχι— (CNAME)CNAMEΌχιΨευδώνυμο προς εξωτερική υπηρεσία
Headless (clusterIP: None)ΌχιΌχιN A (Pods)ΝαιStatefulSet, αναπαραγόμενες βάσεις
Χωρίς επιλογέαΝαιανάλογα με τον τύπο1 AΌχιΧειροκίνητα Endpoints (εξωτερικός πόρος)

19. Κλασικές παγίδες και αντιμετώπιση προβλημάτων

ΣύμπτωμαΣυχνή αιτίαΛύση
Το Service δεν απαντάΕπιλογέας ≠ ετικέτες των PodsΕυθυγραμμίστε spec.selector και τα labels του προτύπου Pod
Κενά EndpointsΚανένα Pod Ready ή κανένα αντίστοιχο Podkubectl get endpoints <svc>· ελέγξτε readinessProbe και ετικέτες
Άρνηση σύνδεσης εσωτερικάΛάθος targetPorttargetPort = πραγματική θύρα του κοντέινερ
Το EXTERNAL-IP μένει <pending>Χωρίς ελεγκτή LB (kind/bare-metal)Docker Desktop OK· αλλιώς MetalLB / port-forward
Η IP πηγής του πελάτη καλύπτεταιexternalTrafficPolicy: ClusterΠεράστε σε Local
NodePort απρόσιτοΘύρα εκτός εύρους / κατειλημμένηΧρησιμοποιήστε 30000–32767, αλλάξτε nodePort
Το DNS δεν επιλύειΛάθος χώρος ονομάτων / CoreDNS KOΔοκιμάστε το FQDN· kubectl -n kube-system get pods (coredns)

Εντολές διάγνωσης:

bash
kubectl get svc <nom> -o wide
kubectl describe svc <nom>
kubectl get endpoints <nom>
kubectl get endpointslices -l kubernetes.io/service-name=<nom>
kubectl run test --rm -it --image=busybox:1.36 -- sh   # nslookup <svc>, wget -qO- http://<svc>

20. Καλές πρακτικές

  • Από προεπιλογή, ClusterIP. Εκθέτετε προς τα έξω μόνο ό,τι πρέπει.
  • Ένας μόνο LoadBalancer + Ingress μπροστά από πολλά ClusterIP (κόστος + συγκεντρωμένο TLS).
  • Ονομάστε τις θύρες σας (multi-port, και targetPort ανά όνομα → αποσύνδεση).
  • Φροντίστε τα readinessProbe: αποφασίζουν ποιος είναι μέσα στα Endpoints.
  • Συνέπεια ετικετών/επιλογέων: είναι το σφάλμα αρ. 1. Κρατήστε σταθερές ετικέτες (app, tier, version).
  • Χρησιμοποιήστε externalTrafficPolicy: Local όταν μετράει η πραγματική IP πελάτη.
  • Προτιμήστε τα EndpointSlices (ενεργά από προεπιλογή στις πρόσφατες εκδόσεις) για την κλιμάκωση.
  • Ποτέ μην κωδικοποιείτε στα σκληρά μια IP Pod: χρησιμοποιήστε το όνομα DNS του Service.

21. Μίνι-ασκήσεις

Άσκηση 1 — Μετατροπή ενός NodePort σε ClusterIP

Αφαιρέστε το type: NodePort (ή βάλτε ClusterIP), εφαρμόστε ξανά, και αποδείξτε ότι δεν είναι πλέον προσβάσιμο από τον οικοδεσπότη αλλά είναι με όνομα από ένα Pod (curl http://demo-nodeport... μετονομασμένο). Παρατηρήστε το kubectl get svc: χωρίς στήλη nodePort.

Άσκηση 2 — Σπάσιμο και επισκευή των Endpoints

Αλλάξτε τον επιλογέα του Service σε app: inexistant, εφαρμόστε ξανά, και διαπιστώστε kubectl get endpoints κενό + υπηρεσία απρόσιτη. Επαναφέρετε app: demo-back: τα Endpoints επιστρέφουν.

Άσκηση 3 — Service headless

Δημιουργήστε ένα Service με clusterIP: None, έπειτα από ένα Pod: nslookup demo-headless. Πρέπει να δείτε πολλές IP (μία ανά Pod) αντί για μία μόνο.

Άσκηση 4 — Multi-port

Προσθέστε μια θύρα metrics (9090) ονομασμένη στο κοντέινερ και στο Service. Επαληθεύστε με kubectl describe svc ότι εμφανίζονται και οι δύο θύρες, και ότι το targetPort αναφέρεται στο όνομα της θύρας.

Άσκηση 5 — ExternalName

Δημιουργήστε ένα Service ExternalName προς example.com. Από ένα Pod: nslookup mon-alias πρέπει να επιστρέψει ένα CNAME προς example.com.


Επιστροφή στη διόρθωση του έργου · Βασικές έννοιες: 01-CONCEPTS-SERVICES.md · Εντολές: 02-COMMANDES.md.


Μάθημα δημιουργημένο από τον Dr. Haythem REHOUMA — Ανάπτυξη και ανάπτυξη λύσεων δεδομένων