Πίνακας Περιεχομένων
Στις 2 Ιουλίου 2019, η Cloudflare ανέπτυξε έναν νέο κανόνα στο Web Application Firewall της, ένα σύστημα σχεδιασμένο για να προστατεύει ιστοσελίδες από κακόβουλη κίνηση. Ο κανόνας περιείχε ένα προβληματικό regular expression, ή regex, δηλαδή ένα μοτίβο που χρησιμοποιείται από το software για την αναγνώριση συγκεκριμένων ακολουθιών χαρακτήρων. Λίγο μετά το deployment, η χρήση CPU στο δίκτυο της Cloudflare άρχισε να ανεβαίνει γρήγορα προς το 100%, προκαλώντας εκτεταμένα 502 errors σε ιστοσελίδες και online υπηρεσίες που βασίζονταν στην υποδομή της. Η διακοπή διήρκεσε περίπου 27 λεπτά, μετατρέποντας ένα πολύ μικρό κομμάτι κώδικα σε ένα παγκόσμιο software incident.
Τι πήγε λάθος;
Τα regular expressions χρησιμοποιούνται ευρέως στο software για αναζήτηση κειμένου, έλεγχο δεδομένων, αναγνώριση μοτίβων και φιλτράρισμα πληροφοριών. Στη συγκεκριμένη περίπτωση, όμως, το expression προκάλεσε υπερβολικό backtracking, με αποτέλεσμα το σύστημα να εξετάζει επανειλημμένα διαφορετικούς πιθανούς τρόπους αντιστοίχισης του ίδιου input. Αυτό αύξησε δραματικά την απαιτούμενη υπολογιστική ισχύ. Ένας φαινομενικά απλός κανόνας κατέληξε να καταναλώνει αρκετούς πόρους ώστε να υπερφορτώσει επεξεργαστές σε όλο το δίκτυο της Cloudflare. Η αλυσίδα ήταν απλή: ένα προβληματικό regex προκάλεσε excessive backtracking, το backtracking οδήγησε σε CPU exhaustion και η εξάντληση των πόρων κατέληξε σε εκτεταμένη διακοπή υπηρεσιών.

Το πιο ενδιαφέρον σημείο δεν ήταν το regex
Είναι εύκολο να δει κανείς ένα τέτοιο περιστατικό και να συμπεράνει ότι ένα μόνο λάθος στον κώδικα προκάλεσε ολόκληρη τη διακοπή. Η σημαντικότερη ιστορία, όμως, βρίσκεται σε όσα συνέβησαν γύρω από αυτό το λάθος. Τα μεγάλα software systems βασίζονται συνήθως σε πολλαπλά επίπεδα προστασίας, όπως testing, code review, διαδικασίες deployment, monitoring και μηχανισμούς rollback. Στο δικό της postmortem, η Cloudflare δεν εξέτασε μόνο το προβληματικό regex, αλλά και τις διαδικασίες που επέτρεψαν στην αλλαγή να φτάσει σε production και να επηρεάσει τόσο μεγάλο μέρος του δικτύου. Το regex ήταν το trigger, αλλά το μέγεθος του προβλήματος καθορίστηκε από το ευρύτερο σύστημα μέσα στο οποίο έγινε το deployment.
Όταν μικρές αδυναμίες συνδυάζονται
Τα μεγάλα software failures σπάνια ξεκινούν από ένα εντυπωσιακό τεχνικό λάθος. Πιο συχνά, προκύπτουν όταν πολλές μικρές αδυναμίες συμπέσουν την ίδια στιγμή. Ένα test μπορεί να μην καλύπτει ένα συγκεκριμένο σενάριο, ένα deployment μπορεί να επεκταθεί πολύ γρήγορα σε μεγάλο μέρος της υποδομής, το monitoring μπορεί να εντοπίσει το πρόβλημα με καθυστέρηση ή η διαδικασία rollback να μην είναι αρκετά άμεση. Καθεμία από αυτές τις αδυναμίες μπορεί να φαίνεται διαχειρίσιμη από μόνη της. Όταν όμως συνδυαστούν, ένα μικρό τεχνικό ζήτημα μπορεί να μετατραπεί σε περιστατικό που επηρεάζει χιλιάδες ή ακόμη και εκατομμύρια χρήστες.
Σχεδιάζοντας για την αποτυχία, όχι για την τελειότητα
Το μάθημα δεν είναι ότι οι developers πρέπει να καταφέρουν να εξαλείψουν κάθε πιθανό bug. Σε σύνθετα software systems, κάτι τέτοιο δεν είναι ρεαλιστικό. Μια πιο ώριμη προσέγγιση θεωρεί δεδομένο ότι κάποια στιγμή θα υπάρξει απρόβλεπτη συμπεριφορά και επικεντρώνεται στον περιορισμό των συνεπειών της. Οι καλές software ομάδες δεν εξετάζουν μόνο αν ο κώδικας λειτουργεί σωστά υπό κανονικές συνθήκες. Αναρωτιούνται επίσης τι θα συμβεί αν κάτι πάει λάθος, πόσο γρήγορα μπορεί να εντοπιστεί το πρόβλημα, αν μια αλλαγή μπορεί να κυκλοφορήσει σταδιακά και πόσο εύκολα μπορεί να αναστραφεί.

Γιατί έχει σημασία η στρατηγική του deployment
Πρακτικές όπως automated testing, canary releases, progressive rollouts, observability και rapid rollback υπάρχουν ακριβώς επειδή ακόμη και μια μικρή αλλαγή μπορεί να προκαλέσει απρόβλεπτες συνέπειες. Ένα staged deployment, για παράδειγμα, επιτρέπει σε μια νέα αλλαγή να εφαρμοστεί αρχικά σε ένα μικρό ποσοστό της κίνησης πριν επεκταθεί σε ολόκληρη την υποδομή. Το σωστό monitoring μπορεί να εντοπίσει ασυνήθιστη χρήση CPU μέσα σε λίγα δευτερόλεπτα, ενώ μια αποτελεσματική διαδικασία rollback μπορεί να επαναφέρει γρήγορα την προηγούμενη έκδοση. Αυτοί οι μηχανισμοί δημιουργούν ένα ουσιαστικό επίπεδο προστασίας ανάμεσα σε ένα software error και ένα business-critical outage.
Το καλοκαιρινό μάθημα
Το καλοκαίρι μπορεί να μοιάζει με πιο ήρεμη περίοδο για πολλές επιχειρήσεις, όμως τα software systems σπάνια σταματούν να λειτουργούν. Οι πλατφόρμες κρατήσεων συνεχίζουν να επεξεργάζονται reservations, τα payment systems διαχειρίζονται συναλλαγές, τα APIs ανταλλάσσουν δεδομένα και οι ψηφιακές υπηρεσίες παραμένουν διαθέσιμες όλο το εικοσιτετράωρο. Αυτό κάνει την αξιοπιστία ακόμη πιο σημαντική σε περιόδους όπου οι ομάδες μπορεί να είναι μικρότερες, η ζήτηση να αυξάνεται ξαφνικά ή οι συνήθεις επιχειρησιακοί ρυθμοί να αλλάζουν. Το περιστατικό της Cloudflare υπενθυμίζει ότι ακόμη και μια μικρή τεχνική αλλαγή μπορεί να έχει τεράστια επίδραση όταν το software λειτουργεί σε παγκόσμια κλίμακα.
Το μεγαλύτερο μάθημα για το software
Το σημαντικότερο συμπέρασμα από το συγκεκριμένο περιστατικό δεν είναι απλώς ότι τα regular expressions μπορούν να γίνουν επικίνδυνα. Είναι ότι το ανθεκτικό software εξαρτάται από τις δικλείδες ασφαλείας που περιβάλλουν κάθε αλλαγή. Τα μεγάλα failures εμφανίζονται συχνά όταν πολλές μικρές γραμμές άμυνας αποτυγχάνουν ταυτόχρονα, επιτρέποντας σε ένα απλό τεχνικό πρόβλημα να εξαπλωθεί πολύ περισσότερο από όσο αναμενόταν. Η καλή software engineering δεν βασίζεται στην προσδοκία ότι κάθε γραμμή κώδικα θα είναι τέλεια. Βασίζεται στη δημιουργία συστημάτων που μπορούν να εντοπίζουν τα λάθη γρήγορα, να περιορίζουν τον αντίκτυπό τους και να επανέρχονται πριν ένα μικρό πρόβλημα εξελιχθεί σε μεγάλο.


