Το ping λειτουργεί από τον κόμβο και αποτυγχάνει από το pod, και τίποτα δεν φτάνει στην τοπική πλευρά. Το τούνελ και η διαδρομή είναι εντάξει· η διεύθυνση προέλευσης στο καλώδιο δεν είναι. Αυτό που διακρίνει τις δύο περιπτώσεις είναι τι δηλώνει το πακέτο ότι είναι όταν φεύγει από το σύμπλεγμα, και το GKE έχει άποψη γι’ αυτό. Ο μηχανισμός είναι μια λίστα εξαιρέσεων masquerade, και η ανάγνωσή της απαιτεί μία μόνο εντολή.

Διαβάστε την ισχύουσα λίστα πριν αλλάξετε οτιδήποτε

Το GKE παρέχει έναν πράκτορα που αποφασίζει, για κάθε εύρος προορισμού, αν η κίνηση των pod ξαναγράφεται στη διεύθυνση του κόμβου κατά την έξοδο. Η παρεχόμενη διαμόρφωσή του ονομάζει τα τρία μπλοκ RFC1918, 10.0.0.0/8, 172.16.0.0/12 και 192.168.0.0/16, ως εξαιρούμενους προορισμούς. Επομένως ό,τι στέλνετε από ένα pod σε έναν τοπικό host 10.x φεύγει από τον κόμβο με τη διεύθυνση του ίδιου του pod ακόμη κολλημένη. Η κίνηση του ίδιου του κόμβου δεν ξαναγράφεται, και γι’ αυτό ακριβώς λειτουργεί το ping του.

Διαβάστε τη σκοπούμενη διαμόρφωση και τους εγκατεστημένους κανόνες, γιατί μπορεί να διαφωνούν. Το kubectl -n kube-system get configmap ip-masq-agent -o yaml δείχνει τι ειπώθηκε στον πράκτορα, και το kubectl -n kube-system get pods -l k8s-app=ip-masq-agent δείχνει αν κάτι εκτελείται για να το εφαρμόσει. Σε έναν κόμβο, το iptables-save | grep -i masq δείχνει τους κανόνες που υπάρχουν πράγματι στον πυρήνα. Όταν το ConfigMap λέει ένα και οι κανόνες άλλο, ο ύποπτος είναι ο πράκτορας, όχι το δίκτυο.

Επιβεβαιώστε τη διεύθυνση προέλευσης με σύλληψη

Κάντε σύλληψη πριν αλλάξετε μια λίστα. Ένα φίλτρο στον έναν προορισμό κρατά την έξοδο αναγνώσιμη: tcpdump -ni any host 10.20.30.40.

Συγκρίνετε το με αυτό που αναφέρει η άλλη πλευρά. Μια σύλληψη τοπικά που δείχνει τη διεύθυνση του pod και καμία απάντηση κλείνει τον κύκλο: η λίστα εξαιρέσεων εξηγεί την ασυμμετρία χωρίς καμία βλάβη του τούνελ. Δύο παρατηρήσεις μιας διεύθυνσης προέλευσης αρκούν για να σταματήσετε να εικάζετε για το CNI.

Περιορίστε την εξαίρεση στο CIDR των pod

Η υποστηριζόμενη διόρθωση περιορίζει την εξαίρεση αντί να την αφαιρεί: κρατήστε το CIDR των pod εξαιρούμενο και αφήστε το υπόλοιπο του χώρου 10.x. Αυτή η λίστα ζει στο ConfigMap του πράκτορα κάτω από το nonMasqueradeCIDRs, και η αλλαγή της είναι μια επεξεργασία που ακολουθείται από ανάπτυξη. Αντικαταστήστε τη φαρδιά εγγραφή με το πραγματικό εύρος pod του συμπλέγματος, κρατήστε τα άλλα ιδιωτικά μπλοκ αν η κίνηση μέσα στο σύμπλεγμα τα χρειάζεται ακόμη, και αφήστε το resyncInterval ήσυχο εκτός αν έχετε λόγο. Εφαρμόστε το, επιβεβαιώστε ότι τα pod του πράκτορα επανεκκινήθηκαν και επιβεβαιώστε ότι οι κανόνες του πυρήνα άλλαξαν.

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

Σε ένα σύμπλεγμα με πολλές δεξαμενές κόμβων, ελέγξτε ότι ο πράκτορας είναι προγραμματισμένος στους κόμβους όπου τα επηρεαζόμενα pod εκτελούνται πραγματικά. Μια δεξαμενή χωρίς DaemonSet κρατά τους παλιούς της κανόνες, και τίποτα στο ConfigMap δεν θα το δείξει.

Η εναλλακτική και το κόστος της

Η άλλη επιλογή κρατά τις διευθύνσεις pod άθικτες και διδάσκει τη διαδρομή γι’ αυτές. Το CIDR των pod μπαίνει στους επιλογείς κίνησης του Cloud VPN, και η τοπική πλευρά χρειάζεται μια διαδρομή επιστροφής γι’ αυτό, ώστε οι απαντήσεις να ξέρουν πού να πάνε. Αυτό διατηρεί την ταυτότητα του pod, που θέλουν ορισμένα μοντέλα ασφαλείας, και διευρύνει τόσο το εύρος δρομολόγησης όσο και το εύρος του τείχους προστασίας που πρέπει να αποδεχτεί η άλλη πλευρά.

Το αντιστάθμισμα είναι αναγνωσιμότητα έναντι εύρους. Η μετάφραση κάνει την τοπική πλευρά να βλέπει μία διεύθυνση ανά κόμβο, κάτι εύκολο να μπει σε λίστα επιτρεπόμενων και που κρύβει ποιο pod έστειλε τι. Χωρίς μετάφραση, η διεύθυνση του pod διατηρείται από άκρη σε άκρη, που είναι καλύτερο για απόδοση ευθύνης και χειρότερο για κάθε συσκευή στη διαδρομή που πρέπει να μάθει ένα νέο εύρος. Καμία επιλογή δεν είναι ελάττωμα του Docker ή του CNI· και οι δύο είναι αποφάσεις δρομολόγησης με λειτουργικό λογαριασμό. Διαλέξτε αυτήν που ο λογαριασμός της μπορεί να πληρωθεί από την ομάδα σας, και γράψτε γιατί.

Επαληθεύστε και επαναφέρετε

Εκτελέστε την ίδια σύλληψη ξανά. Μια σύλληψη σε επίπεδο κόμβου που μετά την επεξεργασία σας εκτυπώνει ακόμη τη διεύθυνση του pod σημαίνει ότι οι κανόνες δεν άλλαξαν ποτέ, ό,τι κι αν λέει το ConfigMap. Το καλώδιο είναι το γεγονός· όλα τα άλλα είναι συμπέρασμα.

Έπειτα ελέγξτε την αντίστροφη κατεύθυνση, γιατί οι μισές από αυτές τις αλλαγές επαληθεύονται μόνο προς τα έξω. Επιβεβαιώστε ότι η απάντηση φτάνει στον κόμβο ή το pod που έστειλε το αίτημα, και επιβεβαιώστε ότι η εφαρμογή ολοκληρώθηκε αντί να λάβει απλώς ένα SYN. Μια σύλληψη που δείχνει αίτημα χωρίς απάντηση είναι πρόβλημα δρομολόγησης στην άλλη πλευρά, όχι πρόβλημα masquerade σε αυτήν.

Η επαναφορά είναι το προηγούμενο ConfigMap, εφαρμοσμένο με τον ίδιο τρόπο, με την ίδια επιβεβαίωση ότι ο πράκτορας επανεκκινήθηκε και οι κανόνες άλλαξαν. Κρατήστε τη διεύθυνση προέλευσης πριν και μετά για ένα γνωστό αίτημα στο αρχείο αλλαγών, γιατί εκείνη η μία γραμμή είναι που αποδεικνύει ότι η αλλαγή έκανε αυτό που είπατε. Ο οδηγός του GKE για τον πράκτορα IP masquerade τεκμηριώνει τις προεπιλογές και τα πεδία του ConfigMap. Αν η διεύθυνση προέλευσης δεν αλλάξει μετά την ανάπτυξη, ο πράκτορας δεν εκτελείται σε εκείνον τον κόμβο και καμία επεξεργασία YAML δεν θα το διορθώσει.

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