Κορυφαίο fakapov Κυανό

Κορυφαίο fakapov Κυανό

Καλό για όλους! 

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

Προοίμιο

Πριν από πολύ καιρό, όταν το Cian αποτελούνταν από μονόλιθους και δεν υπήρχαν ακόμη υποδείξεις για μικροϋπηρεσίες, μετρήσαμε τη διαθεσιμότητα ενός πόρου ελέγχοντας 3-5 σελίδες. 

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

Οι κύριες σελίδες του ιστότοπου ή πώς καταλαβαίνουμε ότι έχουμε πιάσει πάτο

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

Ας πούμε ότι ανακαλύψαμε ότι υπάρχει μια σειρά από εξαιρετικά σημαντικές ενότητες του ιστότοπου που είναι υπεύθυνες για την κύρια υπηρεσία - αναζήτηση και υποβολή διαφημίσεων. Εάν ο αριθμός των αιτημάτων που αποτυγχάνουν υπερβαίνει το 1%, αυτό είναι ένα κρίσιμο περιστατικό. Εάν εντός 15 λεπτών κατά τη διάρκεια της υψηλής ώρας το ποσοστό σφάλματος ξεπεράσει το 0,1%, τότε αυτό θεωρείται επίσης κρίσιμο περιστατικό. Αυτά τα κριτήρια καλύπτουν τα περισσότερα περιστατικά· τα υπόλοιπα δεν εμπίπτουν στο πεδίο εφαρμογής αυτού του άρθρου.

Κορυφαίο fakapov Κυανό

Κορυφαία καλύτερα περιστατικά Cian

Έτσι, σίγουρα μάθαμε να προσδιορίζουμε το γεγονός ότι συνέβη ένα περιστατικό. 

Τώρα κάθε περιστατικό περιγράφεται λεπτομερώς και αντικατοπτρίζεται στο έπος Jira. Παρεμπιπτόντως: γι 'αυτό ξεκινήσαμε ένα ξεχωριστό έργο, το ονομάστηκε FAIL - μόνο έπη μπορούν να δημιουργηθούν σε αυτό. 

Εάν συγκεντρώσετε όλες τις αποτυχίες τα τελευταία χρόνια, οι ηγέτες είναι: 

  • συμβάντα που σχετίζονται με mssql.
  • περιστατικά που προκαλούνται από εξωτερικούς παράγοντες·
  • λάθη διαχειριστή.

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

Πέμπτη θέση - "Βάζοντας τα πράγματα σε τάξη στο DNS"

Ήταν μια θυελλώδης Τρίτη. Αποφασίσαμε να επαναφέρουμε την τάξη στο σύμπλεγμα DNS. 

Ήθελα να μεταφέρω εσωτερικούς διακομιστές DNS από bind σε powerdns, διαθέτοντας εντελώς ξεχωριστούς διακομιστές για αυτό, όπου δεν υπάρχει τίποτα εκτός από το DNS. 

Τοποθετήσαμε έναν διακομιστή DNS σε κάθε θέση των DC μας και ήρθε η στιγμή να μετακινήσουμε ζώνες από bind σε powerdns και να αλλάξουμε την υποδομή σε νέους διακομιστές. 

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

Συμπεράσματα:

Αν νωρίτερα παραμελούσαμε εξωτερικούς παράγοντες κατά την προετοιμασία για εργασία, τώρα περιλαμβάνονται επίσης στη λίστα με αυτά για τα οποία προετοιμαζόμαστε. Και τώρα προσπαθούμε να διασφαλίσουμε ότι όλα τα στοιχεία είναι δεσμευμένα n-2 και κατά τη διάρκεια της εργασίας μπορούμε να χαμηλώσουμε αυτό το επίπεδο στο n-1.

  • Κατά την κατάρτιση ενός σχεδίου δράσης, σημειώστε τα σημεία όπου η υπηρεσία θα μπορούσε να αποτύχει και σκεφτείτε ένα σενάριο όπου όλα πήγαν «από το κακό στο χειρότερο» εκ των προτέρων.
  • Διανομή εσωτερικών διακομιστών DNS σε διαφορετικές γεωγραφικές τοποθεσίες/κέντρα δεδομένων/ράφια/διακόπτες/εισόδους.
  • Σε κάθε διακομιστή, εγκαταστήστε έναν τοπικό διακομιστή DNS προσωρινής αποθήκευσης, ο οποίος ανακατευθύνει αιτήματα στους κύριους διακομιστές DNS και εάν δεν είναι διαθέσιμος, θα ανταποκρίνεται από τη μνήμη cache. 

Τέταρτη θέση - "Βάζοντας τα πράγματα σε τάξη στο Nginx"

Μια ωραία μέρα, η ομάδα μας αποφάσισε ότι "μας έφτανε αυτό" και ξεκίνησε η διαδικασία αναδιαμόρφωσης των ρυθμίσεων nginx. Ο κύριος στόχος είναι να φέρουμε τις ρυθμίσεις σε μια διαισθητική δομή. Προηγουμένως, όλα ήταν «ιστορικά καθιερωμένα» και δεν έφεραν καμία λογική. Τώρα κάθε όνομα_διακομιστή έχει μετακινηθεί σε ένα αρχείο με το ίδιο όνομα και όλες οι ρυθμίσεις παραμέτρων έχουν διανεμηθεί σε φακέλους. Παρεμπιπτόντως, το config περιέχει 253949 γραμμές ή 7836520 χαρακτήρες και καταλαμβάνει σχεδόν 7 megabyte. Ανώτερο επίπεδο δομής: 

Δομή Nginx

├── access
│   ├── allow.list
...
│   └── whitelist.conf
├── geobase
│   ├── exclude.conf
...
│   └── geo_ip_to_region_id.conf
├── geodb
│   ├── GeoIP.dat
│   ├── GeoIP2-Country.mmdb
│   └── GeoLiteCity.dat
├── inc
│   ├── error.inc
...
│   └── proxy.inc
├── lists.d
│   ├── bot.conf
...
│   ├── dynamic
│   └── geo.conf
├── lua
│   ├── cookie.lua
│   ├── log
│   │   └── log.lua
│   ├── logics
│   │   ├── include.lua
│   │   ├── ...
│   │   └── utils.lua
│   └── prom
│       ├── stats.lua
│       └── stats_prometheus.lua
├── map.d
│   ├── access.conf
│   ├── .. 
│   └── zones.conf
├── nginx.conf
├── robots.txt
├── server.d
│   ├── cian.ru
│   │   ├── cian.ru.conf
│   │   ├── ...
│   │   └── my.cian.ru.conf
├── service.d
│   ├── ...
│   └── status.conf
└── upstream.d
    ├── cian-mcs.conf
    ├── ...
    └── wafserver.conf

Έγινε πολύ καλύτερο, αλλά στη διαδικασία μετονομασίας και διανομής ρυθμίσεων, ορισμένες από αυτές είχαν λάθος επέκταση και δεν συμπεριλήφθηκαν στην οδηγία include *.conf. Ως αποτέλεσμα, ορισμένοι κεντρικοί υπολογιστές έγιναν μη διαθέσιμοι και επέστρεψαν το 301 στην κύρια σελίδα. Λόγω του γεγονότος ότι ο κωδικός απάντησης δεν ήταν 5xx/4xx, αυτό δεν έγινε αντιληπτό αμέσως, αλλά μόνο το πρωί. Μετά από αυτό, αρχίσαμε να γράφουμε δοκιμές για να ελέγξουμε τα στοιχεία της υποδομής.

Συμπεράσματα: 

  • Δομήστε σωστά τις ρυθμίσεις σας (όχι μόνο το nginx) και σκεφτείτε τη δομή σε αρχικό στάδιο του έργου. Έτσι θα τα κάνετε πιο κατανοητά στην ομάδα, κάτι που με τη σειρά του θα μειώσει το TTM.
  • Γράψτε δοκιμές για ορισμένα στοιχεία υποδομής. Για παράδειγμα: έλεγχος ότι όλα τα key server_names δίνουν τη σωστή κατάσταση + σώμα απάντησης. Θα αρκεί να έχετε μόνο μερικά σενάρια στη διάθεσή σας που ελέγχουν τις βασικές λειτουργίες του στοιχείου, ώστε να μην θυμάστε μανιωδώς στις 3 τα ξημερώματα τι άλλο πρέπει να ελέγξετε. 

Τρίτη θέση - "Ξαφνικά τελείωσε ο χώρος στην Κασσάνδρα"

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

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

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

Κορυφαίο fakapov Κυανό

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

Συμπεράσματα:

  • Σε όλους τους διακομιστές cassandra, δεν θα πρέπει να καταλαμβάνεται περισσότερο από το 60% του χώρου σε κάθε διαμέρισμα. 
  • Θα πρέπει να φορτώνονται σε όχι περισσότερο από 50% cpu.
  • Δεν πρέπει να ξεχνάτε τον προγραμματισμό χωρητικότητας και πρέπει να το σκεφτείτε καλά για κάθε στοιχείο, με βάση τις ιδιαιτερότητές του.
  • Όσο περισσότεροι κόμβοι στο σύμπλεγμα, τόσο το καλύτερο. Οι διακομιστές που περιέχουν μικρή ποσότητα δεδομένων υπερφορτώνονται πιο γρήγορα και ένα τέτοιο σύμπλεγμα είναι πιο εύκολο να αναβιώσει. 

Δεύτερη θέση - "Τα δεδομένα εξαφανίστηκαν από τον χώρο αποθήκευσης κλειδιού-τιμής του προξένου"

Για την ανακάλυψη της υπηρεσίας, εμείς, όπως πολλοί, χρησιμοποιούμε το consul. Αλλά χρησιμοποιούμε επίσης την τιμή-κλειδί του για την μπλε-πράσινη διάταξη του μονόλιθου. Αποθηκεύει πληροφορίες σχετικά με ενεργά και ανενεργά upstreams, τα οποία αλλάζουν θέσεις κατά την ανάπτυξη. Για το σκοπό αυτό, γράφτηκε μια υπηρεσία ανάπτυξης που αλληλεπιδρούσε με το KV. Κάποια στιγμή τα δεδομένα από το KV εξαφανίστηκαν. Έγινε επαναφορά από τη μνήμη, αλλά με πολλά λάθη. Ως αποτέλεσμα, κατά τη μεταφόρτωση, το φορτίο στα upstreams κατανεμήθηκε άνισα και λάβαμε πολλά σφάλματα 502 λόγω υπερφόρτωσης των backend στην CPU. Ως αποτέλεσμα, περάσαμε από το consul KV στο postgres, από όπου δεν είναι πλέον τόσο εύκολο να τα αφαιρέσουμε.  

Συμπεράσματα:

  • Οι υπηρεσίες χωρίς καμία εξουσιοδότηση δεν πρέπει να περιέχουν δεδομένα κρίσιμα για τη λειτουργία του ιστότοπου. Για παράδειγμα, εάν δεν έχετε εξουσιοδότηση στο ES, θα ήταν καλύτερα να αρνηθείτε την πρόσβαση σε επίπεδο δικτύου από παντού όπου δεν χρειάζεται, να αφήσετε μόνο τα απαραίτητα και επίσης να ορίσετε action.destructive_requires_name: true.
  • Εξασκηθείτε εκ των προτέρων στον μηχανισμό δημιουργίας αντιγράφων ασφαλείας και ανάκτησης. Για παράδειγμα, δημιουργήστε ένα σενάριο εκ των προτέρων (για παράδειγμα, σε python) που μπορεί να δημιουργήσει αντίγραφα ασφαλείας και να επαναφέρει.

Πρώτη θέση - "Captain Unobvious" 

Σε κάποιο σημείο, παρατηρήσαμε μια ανομοιόμορφη κατανομή του φόρτου στα upstreams του nginx σε περιπτώσεις όπου υπήρχαν 10+ διακομιστές στο backend. Λόγω του γεγονότος ότι το round-robin έστελνε αιτήματα από την 1η στην τελευταία ανάντη κατά σειρά, και κάθε επαναφόρτωση του nginx ξεκινούσε από την αρχή, τα πρώτα upstream λάμβαναν πάντα περισσότερα αιτήματα από τα υπόλοιπα. Ως αποτέλεσμα, δούλευαν πιο αργά και ολόκληρος ο ιστότοπος υπέφερε. Αυτό έγινε όλο και πιο αισθητό καθώς αυξανόταν η κίνηση. Η απλή ενημέρωση του nginx για την ενεργοποίηση του τυχαίου δεν λειτούργησε - πρέπει να επαναλάβουμε μια δέσμη κωδικών lua που δεν απογειώθηκαν στην έκδοση 1.15 (εκείνη τη στιγμή). Έπρεπε να επιδιορθώσουμε το nginx 1.14.2, εισάγοντας τυχαία υποστήριξη σε αυτό. Αυτό έλυσε το πρόβλημα. Αυτό το σφάλμα κερδίζει την κατηγορία "Captain Non-Obviousness".

Συμπεράσματα:

Ήταν πολύ ενδιαφέρον και συναρπαστικό να εξερευνήσω αυτό το σφάλμα). 

  • Οργανώστε την παρακολούθησή σας έτσι ώστε να σας βοηθά να εντοπίζετε γρήγορα τέτοιες διακυμάνσεις. Για παράδειγμα, μπορείτε να χρησιμοποιήσετε το ELK για να παρακολουθείτε τα rps σε κάθε backend κάθε upstream, να παρακολουθείτε τον χρόνο απόκρισής τους από την άποψη του nginx. Σε αυτήν την περίπτωση, αυτό μας βοήθησε να εντοπίσουμε το πρόβλημα. 

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

Πηγή: www.habr.com

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