Λεπτομερής δρομολόγηση για το MetalLB σε λειτουργία L2

Λεπτομερής δρομολόγηση για το MetalLB σε λειτουργία L2
Πριν από λίγο καιρό αντιμετώπισα ένα πολύ ασυνήθιστο καθήκον να ρυθμίσω τη δρομολόγηση για το MetalLB. Όλα θα ήταν καλά γιατί... Συνήθως το MetalLB δεν απαιτεί πρόσθετες ενέργειες, αλλά στην περίπτωσή μας έχουμε ένα αρκετά μεγάλο cluster με πολύ απλή διαμόρφωση δικτύου.

Σε αυτό το άρθρο θα σας πω πώς να διαμορφώσετε τη δρομολόγηση βάσει πηγής και πολιτικής για το εξωτερικό δίκτυο του συμπλέγματός σας.

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

Περίπτωση 1: Όταν δεν απαιτείται διαμόρφωση

Ας δούμε μια απλή περίπτωση.

Λεπτομερής δρομολόγηση για το MetalLB σε λειτουργία L2

Δεν απαιτείται πρόσθετη διαμόρφωση δρομολόγησης όταν οι διευθύνσεις που εκδίδονται από τη MetalLB βρίσκονται στο ίδιο υποδίκτυο με τις διευθύνσεις των κόμβων σας.

Για παράδειγμα, έχετε ένα υποδίκτυο 192.168.1.0/24, έχει ρούτερ 192.168.1.1και οι κόμβοι σας λαμβάνουν διευθύνσεις: 192.168.1.10-30, τότε για το MetalLB μπορείτε να προσαρμόσετε το εύρος 192.168.1.100-120 και να είστε σίγουροι ότι θα λειτουργήσουν χωρίς καμία πρόσθετη διαμόρφωση.

Γιατί αυτό? Επειδή οι κόμβοι σας έχουν ήδη διαμορφωμένες διαδρομές:

# ip route
default via 192.168.1.1 dev eth0 onlink 
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10

Και οι διευθύνσεις από το ίδιο εύρος θα τις χρησιμοποιήσουν ξανά χωρίς πρόσθετες ενέργειες.

Περίπτωση 2: Όταν απαιτείται πρόσθετη προσαρμογή

Λεπτομερής δρομολόγηση για το MetalLB σε λειτουργία L2

Θα πρέπει να διαμορφώνετε πρόσθετες διαδρομές κάθε φορά που οι κόμβοι σας δεν έχουν διαμορφωμένη διεύθυνση IP ή διαδρομή προς το υποδίκτυο για το οποίο διευθύνει τα ζητήματα MetalLB.

Θα εξηγήσω λίγο πιο αναλυτικά. Κάθε φορά που το MetalLB εξάγει μια διεύθυνση, μπορεί να συγκριθεί με μια απλή ανάθεση όπως:

ip addr add 10.9.8.7/32 dev lo

Δώσε προσοχή στο:

  • a) Η διεύθυνση εκχωρείται με ένα πρόθεμα /32 Δηλαδή, μια διαδρομή δεν θα προστεθεί αυτόματα στο υποδίκτυο για αυτήν (είναι απλώς μια διεύθυνση)
  • b) Η διεύθυνση είναι προσαρτημένη σε οποιαδήποτε διεπαφή κόμβου (για παράδειγμα επαναφορά βρόχου). Αξίζει να αναφέρουμε εδώ τα χαρακτηριστικά της στοίβας δικτύου Linux. Ανεξάρτητα από το σε ποια διεπαφή προσθέτετε τη διεύθυνση, ο πυρήνας θα επεξεργάζεται πάντα αιτήματα arp και θα στέλνει απαντήσεις arp σε οποιοδήποτε από αυτά, αυτή η συμπεριφορά θεωρείται σωστή και, επιπλέον, χρησιμοποιείται ευρέως σε ένα τόσο δυναμικό περιβάλλον όπως το Kubernetes.

Αυτή η συμπεριφορά μπορεί να προσαρμοστεί, για παράδειγμα, ενεργοποιώντας το αυστηρό arp:

echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce

Σε αυτήν την περίπτωση, οι απαντήσεις arp θα αποστέλλονται μόνο εάν η διεπαφή περιέχει ρητά μια συγκεκριμένη διεύθυνση IP. Αυτή η ρύθμιση απαιτείται εάν σκοπεύετε να χρησιμοποιήσετε το MetalLB και το kube-proxy σας εκτελείται σε λειτουργία IPVS.

Ωστόσο, το MetalLB δεν χρησιμοποιεί τον πυρήνα για την επεξεργασία αιτημάτων arp, αλλά το κάνει το ίδιο στο χώρο χρήστη, επομένως αυτή η επιλογή δεν θα επηρεάσει τη λειτουργία του MetalLB.

Ας επιστρέψουμε στο έργο μας. Εάν η διαδρομή για τις εκδοθείσες διευθύνσεις δεν υπάρχει στους κόμβους σας, προσθέστε την εκ των προτέρων σε όλους τους κόμβους:

ip route add 10.9.8.0/24 dev eth1

Περίπτωση 3: Όταν χρειάζεστε δρομολόγηση βάσει πηγής

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

Για παράδειγμα, έχετε το ίδιο υποδίκτυο 192.168.1.0/24 αφιερωμένο στους κόμβους σας, αλλά θέλετε να εκδώσετε εξωτερικές διευθύνσεις χρησιμοποιώντας το MetalLB. Ας υποθέσουμε ότι έχετε πολλές διευθύνσεις από ένα υποδίκτυο 1.2.3.0/24 βρίσκονται στο VLAN 100 και θέλετε να τα χρησιμοποιήσετε για εξωτερική πρόσβαση στις υπηρεσίες Kubernetes.

Λεπτομερής δρομολόγηση για το MetalLB σε λειτουργία L2

Κατά την επικοινωνία 1.2.3.4 θα κάνετε αιτήματα από διαφορετικό υποδίκτυο από αυτό 1.2.3.0/24 και περίμενε απάντηση. Ο κόμβος που είναι επί του παρόντος ο κύριος για τη διεύθυνση που εκδόθηκε από το MetalLB 1.2.3.4, θα λάβει το πακέτο από το δρομολογητή 1.2.3.1, αλλά η απάντηση γι 'αυτόν πρέπει απαραίτητα να ακολουθήσει την ίδια διαδρομή, μέσω 1.2.3.1.

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

Πώς να αντιμετωπίσετε αυτή την κατάσταση;

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

ip link add link eth0 name eth0.100 type vlan id 100
ip link set eth0.100 up

Και μετά προσθέστε διαδρομές:

ip route add 1.2.3.0/24 dev eth0.100 table 100
ip route add default via 1.2.3.1 table 100

Λάβετε υπόψη ότι προσθέτουμε διαδρομές σε ξεχωριστό πίνακα δρομολόγησης 100 θα περιέχει μόνο δύο διαδρομές που είναι απαραίτητες για την αποστολή ενός πακέτου απόκρισης μέσω της πύλης 1.2.3.1, που βρίσκεται πίσω από τη διεπαφή eth0.100.

Τώρα πρέπει να προσθέσουμε έναν απλό κανόνα:

ip rule add from 1.2.3.0/24 lookup 100

που λέει ρητά: εάν η διεύθυνση πηγής του πακέτου είναι μέσα 1.2.3.0/24, τότε πρέπει να χρησιμοποιήσετε τον πίνακα δρομολόγησης 100. Σε αυτό έχουμε ήδη περιγράψει τη διαδρομή που θα τον στείλει 1.2.3.1

Περίπτωση 4: Όταν χρειάζεστε δρομολόγηση βάσει πολιτικής

Η τοπολογία δικτύου είναι η ίδια όπως στο προηγούμενο παράδειγμα, αλλά ας υποθέσουμε ότι θέλετε επίσης να έχετε πρόσβαση σε εξωτερικές διευθύνσεις πισίνας 1.2.3.0/24 από τους λοβούς σας:

Λεπτομερής δρομολόγηση για το MetalLB σε λειτουργία L2

Η ιδιαιτερότητα είναι ότι κατά την πρόσβαση σε οποιαδήποτε διεύθυνση σε 1.2.3.0/24, το πακέτο απόκρισης χτυπά τον κόμβο και έχει μια διεύθυνση πηγής στην περιοχή 1.2.3.0/24 θα σταλεί υπάκουα σε eth0.100, αλλά θέλουμε η Kubernetes να το ανακατευθύνει στο πρώτο μας pod, το οποίο δημιούργησε το αρχικό αίτημα.

Η επίλυση αυτού του προβλήματος αποδείχθηκε δύσκολη, αλλά κατέστη δυνατή χάρη στη δρομολόγηση βάσει πολιτικής:

Για καλύτερη κατανόηση της διαδικασίας, εδώ είναι ένα μπλοκ διάγραμμα φίλτρου δικτύου:
Λεπτομερής δρομολόγηση για το MetalLB σε λειτουργία L2

Αρχικά, όπως στο προηγούμενο παράδειγμα, ας δημιουργήσουμε έναν επιπλέον πίνακα δρομολόγησης:

ip route add 1.2.3.0/24 dev eth0.100 table 100
ip route add default via 1.2.3.1 table 100

Τώρα ας προσθέσουμε μερικούς κανόνες στα iptables:

iptables -t mangle -A PREROUTING -i eth0.100 -j CONNMARK --set-mark 0x100
iptables -t mangle -A PREROUTING  -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j RETURN
iptables -t mangle -A POSTROUTING -j CONNMARK --save-mark

Αυτοί οι κανόνες θα επισημαίνουν τις εισερχόμενες συνδέσεις στη διεπαφή eth0.100, επισημαίνοντας όλα τα πακέτα με την ετικέτα 0x100, οι απαντήσεις εντός της ίδιας σύνδεσης θα επισημαίνονται επίσης με την ίδια ετικέτα.

Τώρα μπορούμε να προσθέσουμε έναν κανόνα δρομολόγησης:

ip rule add from 1.2.3.0/24 fwmark 0x100 lookup 100

Δηλαδή όλα τα πακέτα με διεύθυνση πηγής 1.2.3.0/24 και ετικέτα 0x100 πρέπει να δρομολογηθεί χρησιμοποιώντας έναν πίνακα 100.

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

Υπάρχει κάτι ακόμα, στο Linux υπάρχει ένα λεγόμενο φίλτρο αντίστροφης διαδρομής, το οποίο χαλάει το όλο πράγμα· κάνει έναν απλό έλεγχο: για όλα τα εισερχόμενα πακέτα, αλλάζει τη διεύθυνση πηγής του πακέτου με τη διεύθυνση αποστολέα και ελέγχει αν το πακέτο μπορεί να φύγει μέσω της ίδιας διεπαφής στην οποία ελήφθη, εάν όχι, θα το φιλτράρει.

Το πρόβλημα είναι ότι στην περίπτωσή μας δεν θα λειτουργήσει σωστά, αλλά μπορούμε να το απενεργοποιήσουμε:

echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/eth0.100/rp_filter

Λάβετε υπόψη ότι η πρώτη εντολή ελέγχει την καθολική συμπεριφορά του rp_filter· εάν δεν είναι απενεργοποιημένη, η δεύτερη εντολή δεν θα έχει κανένα αποτέλεσμα. Ωστόσο, οι υπόλοιπες διεπαφές θα παραμείνουν με ενεργοποιημένο το rp_filter.

Για να μην περιορίσουμε εντελώς τη λειτουργία του φίλτρου, μπορούμε να χρησιμοποιήσουμε την υλοποίηση rp_filter για το netfilter. Χρησιμοποιώντας το rpfilter ως λειτουργική μονάδα iptables, μπορείτε να διαμορφώσετε αρκετά ευέλικτους κανόνες, για παράδειγμα:

iptables -t raw -A PREROUTING -i eth0.100 -d 1.2.3.0/24 -j RETURN
iptables -t raw -A PREROUTING -i eth0.100 -m rpfilter --invert -j DROP

ενεργοποιήστε το rp_filter στη διεπαφή eth0.100 για όλες τις διευθύνσεις εκτός 1.2.3.0/24.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο