Ο φορητός σας δείχνει πράσινο τούνελ, το αρχείο καταγραφής του πελάτη αναφέρει ότι οι διαδρομές σπρώχτηκαν, και η μόνη διεύθυνση που απαντά είναι η δική της τούνελ IP του διακομιστή VPN. Τα ping πέρα από αυτήν πεθαίνουν ό,τι κι αν στοχεύσετε, είτε είναι ClusterIP, είτε διεύθυνση άλλου pod, είτε δημόσιο όνομα κεντρικού υπολογιστή. Αυτός ο συνδυασμός είναι διαγνωστικός και όχι αόριστος: η αποκαψύκλωση λειτουργεί, και το δεύτερο άλμα όχι.

Το συνάντησα σε κόμβο Debian που έτρεχε εικόνα OpenVPN εγκατεστημένη μέσω chart, και το τούνελ ήταν το εύκολο κομμάτι. Ο πελάτης πήρε μίσθωση 10.8.0.x, το 10.8.0.1 απάντησε, και το 10.96.0.10, η υπηρεσία DNS του cluster, έληξε σε timeout. Τίποτα στο αρχείο του διακομιστή δεν φαινόταν ανθυγιεινό, και γι' αυτό ακριβώς οι άνθρωποι αρχίζουν να ξαναγράφουν κανόνες iptables που ποτέ δεν χρειάστηκε να αγγίξουν.

Ένα pod VPN είναι δρομολογητής, και αξίζει να ειπωθεί καθαρά. Τα κρυπτογραφημένα πακέτα φτάνουν, ξετυλίγονται στο δικό του namespace δικτύου του pod, και μετά πρέπει να βγουν από διαφορετική διεπαφή. Το Linux αρνείται αυτό το δεύτερο βήμα εκτός αν η προώθηση είναι ενεργοποιημένη μέσα σε αυτό ακριβώς το namespace.

Τι μπορεί και τι δεν μπορεί να φτάσει ο πελάτης

Η διεύθυνση που απαντά ανήκει στο άκρο του τούνελ, και η διεργασία VPN την κατέχει τοπικά, οπότε δεν εμπλέκεται καθόλου προώθηση. Όλα τα άλλα, μαζί με άλλο pod, VIP υπηρεσίας ή το διαδίκτυο, χρειάζονται τον πυρήνα για να μετακινήσει ένα πακέτο από το tun0 στο eth0. Όταν αυτή η μετακίνηση απορρίπτεται, το σύμπτωμα είναι ομοιόμορφη σιωπή και όχι απόρριψη, επειδή τίποτα δεν παράγει σφάλμα ICMP πίσω κάτω από το τούνελ. Παίρνετε timeouts, όχι μηνύματα μη προσβασιμότητας, και αυτό είναι το στοιχείο ότι κανείς δεν δρομολογεί καθόλου.

Δύο λεπτά ταξινόμησης στενεύουν το επίπεδο. Αν τα ονόματα DNS αποτυγχάνουν ενώ τα ακατέργαστα ping σε IP υπηρεσίας περνούν, το πρόβλημα είναι στην υδραυλική του DNS, όχι στην προώθηση. Αν κάθε προορισμός πέρα από τη διεύθυνση του peer λήγει σε timeout, μαζί με γυμνή IP, ξεκινήστε από το namespace.

Διαβάστε τη ρύθμιση μέσα στο namespace

Κάθε pod παίρνει το δικό του namespace δικτύου, και το net.ipv4.ip_forward είναι sysctl ανά namespace. Η αλλαγή του στον κόμβο δεν σας λέει τίποτα για το container, και είναι ένας αξιόπιστος τρόπος να περάσετε ένα απόγευμα στο λάθος μηχάνημα.

kubectl exec -it deploy/openvpn -- sysctl net.ipv4.ip_forward
# net.ipv4.ip_forward = 0

Ένα μηδέν επιβεβαιώνει τη διάγνωση. Η τιμή δεν κληρονομείται ούτε από τη ρύθμιση χρόνου εκτέλεσης του κόμβου: ξεκινά από την προεπιλογή της εικόνας κάθε φορά που δημιουργείται ένα container. Μια διόρθωση που εφαρμόστηκε με το χέρι με kubectl exec ... sysctl -w επομένως εξαφανίζεται στην επόμενη επανεκκίνηση και επιστρέφει ως βλάβη που φαίνεται διακοπτόμενη.

Ενεργοποίηση ώστε το manifest να το κρατήσει

Η διαρκής επιλογή είναι ένα init container που τρέχει στο ίδιο pod sandbox και γράφει την τιμή πριν ξεκινήσει το container VPN. Τα container σε ένα pod μοιράζονται namespace δικτύου, οπότε η ρύθμιση περνά στο κύριο container.

initContainers:
- name: enable-forwarding
  image: busybox:1.36
  command: ["sysctl", "-w", "net.ipv4.ip_forward=1"]
  securityContext:
    privileged: true

Αυτό το privileged: true είναι η γραμμή στην οποία αντιδρούν οι reviewers, και έχουν δίκιο. Το γράψιμο ενός sysctl χρειάζεται είτε προνόμιο είτε στενά περιορισμένη δυνατότητα, και ένα cluster που τρέχει το περιοριστικό Pod Security Standard μπορεί να αρνηθεί κατηγορηματικά ένα προνομιούχο init container. Αν το admission απορρίψει το pod, το μαθαίνετε κατά τη δημιουργία, που τουλάχιστον είναι ειλικρινές και εύκολο να διαβαστεί.

Η καθαρότερη εναλλακτική είναι η λίστα securityContext.sysctls σε επίπεδο pod, που επιτρέπει στο kubelet να εφαρμόζει namespaced sysctls χωρίς να δίνει προνόμια σε κανένα container. Καλύπτει μόνο ονόματα στη λίστα επιτρεπόμενων του cluster. Το αν το net.ipv4.ip_forward είναι σε αυτή τη λίστα εξαρτάται από το πώς ρυθμίστηκε το kubelet, και ένα pod που ζητά sysctl έξω από αυτήν απορρίπτεται στο admission ή κολλάει σε CreateContainerConfigError όσο το sandbox επαναλαμβάνεται. Ελέγξτε τη λίστα επιτρεπόμενων πριν υποθέσετε ότι το πεδίο είναι χαλασμένο.

Πριν φτιάξετε με το χέρι οποιαδήποτε από τις δύο προσεγγίσεις, δείτε αν το chart εκθέτει ήδη τον διακόπτη, συχνά ως κάτι σαν ipForwardInitContainer: true. Η χρήση της τιμής του chart κρατά το αρχείο παράκαμψης μικρό και επιβιώνει από την επόμενη αναβάθμιση, κάτι που οι χειροκίνητες διορθώσεις Deployment δεν κάνουν.

Το δεύτερο μισό: διαδρομή επιστροφής και πολιτική

Η ενεργοποιημένη προώθηση είναι απαραίτητη, όχι αρκετή. Αν οι πελάτες χρησιμοποιούν ιδιωτική δεξαμενή για την οποία το δίκτυο του cluster δεν έχει διαδρομή, οι απαντήσεις δεν βρίσκουν τον δρόμο πίσω στο τούνελ, και το pod πρέπει να κάνει masquerade αυτής της κίνησης προς τον προορισμό του.

Η πολιτική κάθεται από πάνω. Τα αντικείμενα NetworkPolicy και οι κανόνες τείχους προστασίας του cloud αξιολογούνται με βάση τη διεύθυνση προέλευσης που φέρει το πακέτο μετά τη μετάφραση, οπότε ένας κανόνας γραμμένος για τη δεξαμενή πελατών μπορεί ήσυχα να πάψει να ταιριάζει μόλις ενεργοποιηθεί το masquerade.

Όταν οι πελάτες χρειάζονται μόνο υπηρεσίες μέσα στο cluster, το να τερματίζει το VPN στο VIP της υπηρεσίας είναι μικρότερο σχέδιο από το να δρομολογείς στο δίκτυο των pod. Κρατά επίσης τη δεξαμενή πελατών εντελώς έξω από τον πίνακα δρομολόγησης του CNI.

Απομόνωση του άλματος που αποτυγχάνει από τον πελάτη

Δουλέψτε προς τα έξω και σταματήστε στο πρώτο σιωπηλό βήμα. Ξεκινήστε με τον peer του VPN, μετά δοκιμάστε τη διεύθυνση κάποιου pod, μετά ένα VIP υπηρεσίας, και μόνο μετά έναν δημόσιο προορισμό. Κάθε επιτυχία μετακινεί το όριο ένα άλμα, και κάθε αποτυχία ονομάζει το επίπεδο που αξίζει επιθεώρηση. Μετά από κάθε rollout, μπείτε με exec και διαβάστε ξανά το sysctl, γιατί ένα pod που αντικαταστάθηκε ξεκινά από την προεπιλογή της εικόνας και μια διόρθωση που δεν ήταν ποτέ στο manifest έχει ήδη φύγει.

Η τεκμηρίωση του Kubernetes για τη χρήση sysctls σε ένα cluster απαριθμεί ποια ονόματα μπορούν να οριστούν μέσω του security context του pod, και είναι το πρώτο μέρος που κοιτάτε όταν το admission αρνείται την αλλαγή.

Σχετικά άρθρα