Netramesh - ελαφρύ πλέγμα εξυπηρέτησης

Καθώς περνάμε από μια μονολιθική εφαρμογή σε μια αρχιτεκτονική μικροϋπηρεσιών, αντιμετωπίζουμε νέες προκλήσεις.

Σε μια μονολιθική εφαρμογή, είναι συνήθως αρκετά εύκολο να προσδιοριστεί σε ποιο μέρος του συστήματος παρουσιάστηκε το σφάλμα. Πιθανότατα, το πρόβλημα βρίσκεται στον κώδικα του ίδιου του monolith ή στη βάση δεδομένων. Αλλά όταν αρχίζουμε να αναζητούμε ένα πρόβλημα σε μια αρχιτεκτονική microservice, όλα δεν είναι πλέον τόσο προφανή. Πρέπει να βρούμε ολόκληρη τη διαδρομή που πήρε το αίτημα από την αρχή μέχρι το τέλος και να την επιλέξουμε από εκατοντάδες μικροϋπηρεσίες. Επιπλέον, πολλά από αυτά έχουν επίσης τις δικές τους εγκαταστάσεις αποθήκευσης, οι οποίες μπορούν επίσης να προκαλέσουν λογικά σφάλματα, καθώς και προβλήματα με την απόδοση και την ανοχή σφαλμάτων.

Netramesh - ελαφρύ πλέγμα εξυπηρέτησης

Έψαχνα εδώ και πολύ καιρό για ένα εργαλείο που θα βοηθούσε στην αντιμετώπιση τέτοιων προβλημάτων (έγραψα για αυτό στο Habré: 1, 2), αλλά στο τέλος έφτιαξα τη δική μου λύση ανοιχτού κώδικα. Σε αυτό το άρθρο μιλάω για τα οφέλη της προσέγγισης του πλέγματος υπηρεσιών και μοιράζομαι ένα νέο εργαλείο για την υλοποίησή της.

Η κατανεμημένη ανίχνευση είναι μια κοινή λύση στο πρόβλημα της εύρεσης σφαλμάτων στα κατανεμημένα συστήματα. Αλλά τι γίνεται εάν αυτή η προσέγγιση για τη συλλογή πληροφοριών σχετικά με τις αλληλεπιδράσεις δικτύου δεν έχει εφαρμοστεί ακόμη στο σύστημα ή, χειρότερα, σε μέρος του συστήματος λειτουργεί ήδη σωστά, αλλά εν μέρει όχι, καθώς δεν έχει προστεθεί σε παλιές υπηρεσίες ? Για να προσδιορίσετε την ακριβή βασική αιτία ενός προβλήματος, είναι απαραίτητο να έχετε μια πλήρη εικόνα του τι συμβαίνει στο σύστημα. Είναι ιδιαίτερα σημαντικό να κατανοήσουμε ποιες μικροϋπηρεσίες εμπλέκονται σε βασικά κρίσιμα για τις επιχειρήσεις μονοπάτια.

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

Προσέγγιση πλέγματος εξυπηρέτησης

Η κύρια ιδέα της προσέγγισης του πλέγματος υπηρεσιών είναι να προσθέσουμε ένα άλλο επίπεδο υποδομής στο δίκτυο, το οποίο θα μας επιτρέψει να κάνουμε οτιδήποτε με την αλληλεπίδραση μεταξύ των υπηρεσιών. Οι περισσότερες υλοποιήσεις λειτουργούν ως εξής: ένα πρόσθετο κοντέινερ sidecar με διαφανή διακομιστή μεσολάβησης προστίθεται σε κάθε microservice, μέσω του οποίου διέρχεται όλη η εισερχόμενη και εξερχόμενη κίνηση της υπηρεσίας. Και αυτό είναι ακριβώς το μέρος όπου μπορούμε να κάνουμε εξισορρόπηση πελατών, να εφαρμόζουμε πολιτικές ασφαλείας, να επιβάλλουμε περιορισμούς στον αριθμό των αιτημάτων και να συλλέγουμε σημαντικές πληροφορίες για την αλληλεπίδραση των υπηρεσιών στην παραγωγή.

Netramesh - ελαφρύ πλέγμα εξυπηρέτησης

Λύσεις

Υπάρχουν ήδη αρκετές εφαρμογές αυτής της προσέγγισης: Ίστιο и linkerd2. Παρέχουν πολλά χαρακτηριστικά εκτός συσκευασίας. Αλλά την ίδια στιγμή, υπάρχει μεγάλο κόστος για τους πόρους. Επιπλέον, όσο μεγαλύτερο είναι το σύμπλεγμα στο οποίο λειτουργεί ένα τέτοιο σύστημα, τόσο περισσότεροι πόροι θα απαιτούνται για τη συντήρηση της νέας υποδομής. Στην Avito, λειτουργούμε συμπλέγματα kubernetes που περιέχουν χιλιάδες παρουσίες υπηρεσιών (και ο αριθμός τους συνεχίζει να αυξάνεται γρήγορα). Στην τρέχουσα εφαρμογή του, το Istio καταναλώνει ~300Mb μνήμης RAM ανά παρουσία υπηρεσίας. Λόγω του μεγάλου αριθμού δυνατοτήτων, η διαφανής εξισορρόπηση επηρεάζει και τον συνολικό χρόνο απόκρισης των υπηρεσιών (έως 10ms).

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

Ως αποτέλεσμα, καταλήξαμε στην απόφασή μας:  Netramesh.

Netramesh

Netramesh είναι μια ελαφριά λύση service mesh με δυνατότητα άπειρης κλίμακας, ανεξάρτητα από τον αριθμό των υπηρεσιών στο σύστημα.

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

Σήμερα, οι περισσότερες λύσεις cloud υλοποιούνται στο Golang. Και, φυσικά, υπάρχουν λόγοι για αυτό. Η σύνταξη εφαρμογών δικτύου στο Golang που λειτουργούν ασύγχρονα με I/O και κλιμακώνονται μεταξύ των πυρήνων όπως απαιτείται είναι βολική και αρκετά απλή. Και, αυτό που είναι επίσης πολύ σημαντικό, η απόδοση είναι επαρκής για να λύσει αυτό το πρόβλημα. Γι' αυτό και επιλέξαμε το Golang.

Παραγωγικότητα

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

Ας δούμε τι αποτελέσματα έχουμε.

RAM

Το Netramesh καταναλώνει ~10Mb χωρίς κίνηση και 50Mb μέγιστο με φορτίο έως και 10000 RPS ανά παρουσία.

Το Istio envoy proxy καταναλώνει πάντα ~300Mb στα cluster μας με χιλιάδες περιπτώσεις. Αυτό δεν του επιτρέπει να κλιμακωθεί σε ολόκληρο το σύμπλεγμα.

Netramesh - ελαφρύ πλέγμα εξυπηρέτησης

Netramesh - ελαφρύ πλέγμα εξυπηρέτησης

Με το Netramesh είχαμε ~ 10x μείωση στην κατανάλωση μνήμης.

CPU

Η χρήση της CPU είναι σχετικά ίση υπό φορτίο. Εξαρτάται από τον αριθμό των αιτημάτων ανά μονάδα χρόνου στο πλαϊνό καρότσι. Τιμές σε 3000 αιτήματα ανά δευτερόλεπτο στο μέγιστο:

Netramesh - ελαφρύ πλέγμα εξυπηρέτησης

Netramesh - ελαφρύ πλέγμα εξυπηρέτησης

Υπάρχει ένα ακόμη σημαντικό σημείο: Netramesh - μια λύση χωρίς επίπεδο ελέγχου και χωρίς φορτίο δεν καταναλώνει χρόνο CPU. Με το Istio, τα sidecars ενημερώνουν πάντα τα τελικά σημεία υπηρεσίας. Ως αποτέλεσμα, μπορούμε να δούμε αυτήν την εικόνα χωρίς φορτίο:

Netramesh - ελαφρύ πλέγμα εξυπηρέτησης

Χρησιμοποιούμε το HTTP/1 για επικοινωνία μεταξύ των υπηρεσιών. Η αύξηση του χρόνου απόκρισης για το Istio κατά τη διαμεσολάβηση μέσω envoy ήταν έως και 5-10ms, κάτι που είναι αρκετά μεγάλο για υπηρεσίες που είναι έτοιμες να ανταποκριθούν σε ένα χιλιοστό του δευτερολέπτου. Με το Netramesh αυτός ο χρόνος μειώθηκε στα 0.5-2ms.

Επεκτασιμότητα

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

Ανακάλυψη υπηρεσίας

Netramesh - ελαφρύ πλέγμα εξυπηρέτησης

Το Netramesh δεν προσθέτει επιπλέον μηχανισμούς για την ανακάλυψη υπηρεσίας. Όλη η κίνηση γίνεται με διαφάνεια μέσω του netra sidecar.

Το Netramesh υποστηρίζει πρωτόκολλο εφαρμογής HTTP/1. Για να το ορίσετε, χρησιμοποιείται μια διαμορφώσιμη λίστα θυρών. Συνήθως, το σύστημα έχει πολλές θύρες μέσω των οποίων πραγματοποιείται η επικοινωνία HTTP. Για παράδειγμα, χρησιμοποιούμε 80, 8890, 8080 για αλληλεπίδραση μεταξύ υπηρεσιών και εξωτερικών αιτημάτων. Σε αυτήν την περίπτωση, μπορούν να οριστούν χρησιμοποιώντας μια μεταβλητή περιβάλλοντος NETRA_HTTP_PORTS.

Εάν χρησιμοποιείτε το Kubernetes ως ενορχηστρωτή και τον μηχανισμό της οντότητας Υπηρεσίας για επικοινωνία εντός του συμπλέγματος μεταξύ των υπηρεσιών, τότε ο μηχανισμός παραμένει ακριβώς ο ίδιος. Πρώτα, η microservice αποκτά μια διεύθυνση IP υπηρεσίας χρησιμοποιώντας kube-dns και ανοίγει μια νέα σύνδεση σε αυτήν. Αυτή η σύνδεση δημιουργείται πρώτα με το τοπικό netra-sidecar και όλα τα πακέτα TCP αρχικά φτάνουν στο netra. Στη συνέχεια, το netra-sidecar δημιουργεί μια σύνδεση με τον αρχικό προορισμό. Το NAT στο pod IP στον κόμβο παραμένει ακριβώς το ίδιο όπως χωρίς netra.

Κατανεμημένη ανίχνευση και προώθηση περιβάλλοντος

Το Netramesh παρέχει τη λειτουργικότητα που απαιτείται για την αποστολή διαστημάτων ανίχνευσης σχετικά με τις αλληλεπιδράσεις HTTP. Το Netra-sidecar αναλύει το πρωτόκολλο HTTP, μετρά τις καθυστερήσεις αιτημάτων και εξάγει τις απαραίτητες πληροφορίες από τις κεφαλίδες HTTP. Τελικά, έχουμε όλα τα ίχνη σε ένα ενιαίο σύστημα Jaeger. Για λεπτομερείς ρυθμίσεις, μπορείτε επίσης να χρησιμοποιήσετε τις μεταβλητές περιβάλλοντος που παρέχονται από την επίσημη βιβλιοθήκη jaeger go βιβλιοθήκη.

Netramesh - ελαφρύ πλέγμα εξυπηρέτησης

Netramesh - ελαφρύ πλέγμα εξυπηρέτησης

Όμως υπάρχει ένα πρόβλημα. Έως ότου οι υπηρεσίες δημιουργήσουν και στείλουν μια ειδική κεφαλίδα uber, δεν θα δούμε συνδεδεμένα διαστήματα ανίχνευσης στο σύστημα. Και αυτό είναι που χρειαζόμαστε για να βρούμε γρήγορα την αιτία των προβλημάτων. Και εδώ η Netramesh έχει μια λύση. Οι διακομιστής μεσολάβησης διαβάζουν τις κεφαλίδες HTTP και, εάν δεν περιέχουν το αναγνωριστικό ανίχνευσης uber, δημιουργούν ένα. Το Netramesh αποθηκεύει επίσης πληροφορίες σχετικά με τα εισερχόμενα και εξερχόμενα αιτήματα σε ένα sidecar και τα αντιστοιχίζει εμπλουτίζοντάς τα με τις απαραίτητες κεφαλίδες εξερχόμενων αιτημάτων. Το μόνο που χρειάζεται να κάνετε στις υπηρεσίες είναι να στείλετε μόνο μία κεφαλίδα X-Request-Id, το οποίο μπορεί να διαμορφωθεί χρησιμοποιώντας μια μεταβλητή περιβάλλοντος NETRA_HTTP_REQUEST_ID_HEADER_NAME. Για να ελέγξετε το μέγεθος του περιβάλλοντος στο Netramesh, μπορείτε να ορίσετε τις ακόλουθες μεταβλητές περιβάλλοντος: NETRA_TRACING_CONTEXT_EXPIRATION_MILLISECONDS (ο χρόνος για τον οποίο θα αποθηκευτεί το πλαίσιο) και NETRA_TRACING_CONTEXT_CLEANUP_INTERVAL (συχνότητα εκκαθάρισης περιβάλλοντος).

Είναι επίσης δυνατό να συνδυάσετε πολλαπλές διαδρομές στο σύστημά σας επισημαίνοντάς τις με ένα ειδικό διακριτικό περιόδου λειτουργίας. Το Netra σας επιτρέπει να εγκαταστήσετε HTTP_HEADER_TAG_MAP για να μετατρέψετε τις κεφαλίδες HTTP σε αντίστοιχες ετικέτες διαστήματος ανίχνευσης. Αυτό μπορεί να είναι ιδιαίτερα χρήσιμο για δοκιμές. Αφού περάσετε τη λειτουργική δοκιμή, μπορείτε να δείτε ποιο μέρος του συστήματος επηρεάστηκε από το φιλτράρισμα από το αντίστοιχο κλειδί συνεδρίας.

Προσδιορισμός της πηγής αιτήματος

Για να προσδιορίσετε από πού προήλθε το αίτημα, μπορείτε να χρησιμοποιήσετε τη λειτουργία αυτόματης προσθήκης κεφαλίδας με την πηγή. Χρήση μεταβλητής περιβάλλοντος NETRA_HTTP_X_SOURCE_HEADER_NAME Μπορείτε να καθορίσετε ένα όνομα κεφαλίδας που θα εγκατασταθεί αυτόματα. Με τη χρήση NETRA_HTTP_X_SOURCE_VALUE μπορείτε να ορίσετε την τιμή στην οποία θα οριστεί η κεφαλίδα X-Source για όλα τα εξερχόμενα αιτήματα.

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

Δρομολόγηση κυκλοφορίας και εσωτερικά Netramesh

Το Netramesh αποτελείται από δύο κύρια συστατικά. Το πρώτο, το netra-init, ορίζει κανόνες δικτύου για την παρακολούθηση της κυκλοφορίας. Χρησιμοποιεί Κανόνες ανακατεύθυνσης iptables να αναχαιτίσει το σύνολο ή μέρος της κυκλοφορίας στο πλαϊνό καρότσι, το οποίο είναι το δεύτερο κύριο στοιχείο του Netramesh. Μπορείτε να διαμορφώσετε ποιες θύρες πρέπει να υποκλαπούν για εισερχόμενες και εξερχόμενες συνεδρίες TCP: INBOUND_INTERCEPT_PORTS, OUTBOUND_INTERCEPT_PORTS.

Το εργαλείο έχει επίσης ένα ενδιαφέρον χαρακτηριστικό - πιθανολογική δρομολόγηση. Εάν χρησιμοποιείτε το Netramesh αποκλειστικά για τη συλλογή ανιχνεύσεων, τότε σε ένα περιβάλλον παραγωγής μπορείτε να εξοικονομήσετε πόρους και να ενεργοποιήσετε την πιθανολογική δρομολόγηση χρησιμοποιώντας μεταβλητές NETRA_INBOUND_PROBABILITY и NETRA_OUTBOUND_PROBABILITY (από 0 έως 1). Η προεπιλεγμένη τιμή είναι 1 (όλη η κίνηση παρεμποδίζεται).

Μετά την επιτυχή αναχαίτιση, το netra sidecar δέχεται τη νέα σύνδεση και χρησιμοποιεί SO_ORIGINAL_DST επιλογή υποδοχής για να λάβετε τον αρχικό προορισμό. Στη συνέχεια, η Netra ανοίγει μια νέα σύνδεση με την αρχική διεύθυνση IP και δημιουργεί αμφίδρομη επικοινωνία TCP μεταξύ των μερών, ακούγοντας όλη την κίνηση που διέρχεται. Εάν η θύρα ορίζεται ως HTTP, η Netra προσπαθεί να την αναλύσει και να την ανιχνεύσει. Εάν η ανάλυση HTTP αποτύχει, το Netra επιστρέφει στο TCP και μεταφέρει με διαφάνεια τα byte.

Δημιουργία γραφήματος εξάρτησης

Μετά τη λήψη μεγάλου όγκου πληροφοριών ανίχνευσης στο Jaeger, θέλω να λάβω ένα πλήρες γράφημα των αλληλεπιδράσεων στο σύστημα. Αλλά αν το σύστημά σας είναι αρκετά φορτωμένο και συσσωρεύονται δισεκατομμύρια διαστήματα ανίχνευσης ανά ημέρα, η συγκέντρωση τους δεν είναι τόσο εύκολη υπόθεση. Υπάρχει ένας επίσημος τρόπος για να γίνει αυτό: σπινθήρες-εξαρτήσεις. Ωστόσο, θα χρειαστούν ώρες για να δημιουργήσετε ένα πλήρες γράφημα και θα σας αναγκάσει να κατεβάσετε ολόκληρο το σύνολο δεδομένων από το Jaeger για τις τελευταίες XNUMX ώρες.

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

Netramesh - ελαφρύ πλέγμα εξυπηρέτησης

Πώς να χρησιμοποιήσετε το Netramesh

Το Netra μπορεί εύκολα να προστεθεί σε οποιαδήποτε υπηρεσία που εκτελεί οποιονδήποτε ενορχηστρωτή. Μπορείτε να δείτε ένα παράδειγμα εδώ.

Αυτή τη στιγμή, η Netra δεν έχει τη δυνατότητα αυτόματης υλοποίησης sidecars σε υπηρεσίες, αλλά υπάρχουν σχέδια για εφαρμογή.

Το μέλλον της Netramesh

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

Στο μέλλον, το Netramesh θα υποστηρίζει άλλα πρωτόκολλα επιπέδου εφαρμογής εκτός από το HTTP. Η δρομολόγηση L7 θα είναι διαθέσιμη στο εγγύς μέλλον.

Χρησιμοποιήστε το Netramesh εάν αντιμετωπίζετε παρόμοια προβλήματα και γράψτε μας με ερωτήσεις και προτάσεις.

Πηγή: www.habr.com

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