Και οι δύο φέρουσες υποθέσεις αυτής της σειράς είναι δοκιμάσιμες σήμερα, με μια managed υπηρεσία, μέσα σε ένα απόγευμα. Το AWS Fault Injection Service παρέχει ένα σενάριο με το όνομα "AZ Availability: Power Interruption" που σταματά κάθε tagged instance σε μία availability zone, τροφοδοτεί σφάλματα InsufficientInstanceCapacity στα Auto Scaling groups που προσπαθούν να τα αντικαταστήσουν, παγώνει το IO των EBS volumes, και κόβει την κίνηση του subnet, μετά αίρει τις βλάβες και ξαναξεκινά ό,τι σταμάτησε. Η υπόθεση για το control plane από το Μέρος 3 δεν έχει έτοιμη βλάβη, αλλά μια ειλικρινής προσέγγισή της χωράει σε ένα αρχείο JSON και ένα IAM deny. Σχεδόν κανείς δεν τρέχει κανένα από τα δύο, και ο λόγος δεν είναι τα εργαλεία, ο λόγος είναι ότι μια δοκιμή μπορεί να αποτύχει και μια υπόθεση δεν μπορεί.

Αυτό είναι το Μέρος 4 του Nothing Fails Alone, το τελευταίο. Το Μέρος 1 πήρε το συμβάν του Μαΐου στην us-east-1 και έδειξε το όριο ζώνης να αντέχει ενώ ένα quorum πέθαινε μέσα του. Το Μέρος 2 πήρε το συμβάν του Μαρτίου στην me-central-1 και έδειξε μία αιτία να φτάνει σε δύο ζώνες με διαφορά δεκαοκτώ ωρών, πέρα από κάθε εγγύηση απομόνωσης. Το Μέρος 3 πήρε τρία συμβάντα control plane σε δύο παρόχους και έδειξε σχέδια ανάκτησης να πεθαίνουν μαζί με το επίπεδο πάνω στο οποίο τρέχουν. Η ραχοκοκαλιά της σειράς, σε δύο προτάσεις: η διαθεσιμότητα που αγοράζετε τελειώνει στο όριο αυτού που υποσχέθηκε ο πάροχος, και οτιδήποτε πάνω από αυτή τη γραμμή είναι αρχιτεκτονική που σας ανήκει. Αυτό που σας ανήκει και δεν εξασκείτε ποτέ δεν είναι αρχιτεκτονική, είναι μια υπόθεση με το όνομά σας πάνω της. Αυτό το μέρος την εξασκεί, και μετά βαθμολογεί τη σειρά.

Η άσκηση AZ έρχεται έτοιμη

Το AZ Availability: Power Interruption της βιβλιοθήκης σεναρίων του FIS είναι ένα δημοσιευμένο experiment template που προκαλεί τα τεκμηριωμένα συμπτώματα της απώλειας μίας ζώνης, και το δημοσιευμένο JSON του κουβαλά οκτώ actions σε επτά τύπους βλάβης (το σταμάτημα των instances εμφανίζεται δύο φορές, μία για standalone instances και μία για τα ίδια τα Auto Scaling groups). Τα tagged running instances στη ζώνη-στόχο σταματούν και ξαναξεκινούν μετά την διαμορφωμένη διάρκεια. Τα αιτήματα εκκίνησης από tagged Auto Scaling groups παίρνουν InsufficientInstanceCapacity για όλη τη διάρκεια, το ίδιο και οι κλήσεις χωρητικότητας όποιων IAM roles ονομάσετε, επειδή, σύμφωνα με τη σελίδα του σεναρίου, "EC2 API calls made by the Auto Scaling control plane to recover lost capacity in the AZ will fail" κατά τη διάρκεια μιας πραγματικής διακοπής ρεύματος. Το IO των EBS volumes παγώνει. Η κίνηση του subnet απορρίπτεται με την αντικατάσταση από ένα κλωνοποιημένο network ACL γεμάτο κανόνες deny. Τα RDS clusters με έναν writer στη ζώνη κάνουν failover, και τα ElastiCache replication groups παίρνουν διακοπή ρεύματος στη ζώνη τους. Αυτό είναι το μεγαλύτερο μέρος αυτού που έκανε το συμβάν του Μαΐου στην use1-az4: η αστοχία που έριξε την Coinbase για ένα βράδυ είναι τώρα ένα αντικείμενο βιβλιοθήκης.

Να είμαστε ακριβείς για το τι δεν είναι. Τα instances σταματούν από την μπροστινή πόρτα, το API StopInstances: ένα ομαλό shutdown, όχι μια διακοπή ρεύματος, οπότε τίποτα σχετικό με τη crash consistency δεν δοκιμάζεται. Τα Fargate tasks δεν καλύπτονται. Τα RDS Multi-AZ clusters με δύο αναγνώσιμα standbys δεν υποστηρίζονται. Μια σημείωση απόκλισης: η σελίδα του σεναρίου περιγράφει μια action ανάκτησης, την aws:arc:start-zonal-autoshift, που το ίδιο του το JSON snapshot δεν περιέχει, η βιβλιοθήκη της κονσόλας κουβαλά την πιο πρόσφατη αναθεώρηση, και το lab ακολουθεί το δημοσιευμένο JSON.

Το lab είναι το 04-game-day στο repo της σειράς, και σπάει τον κανόνα read-only της σειράς για δεύτερη και τελευταία φορά: το --inject ξεκινά πραγματικά experiments απέναντι σε όποιον λογαριασμό φτάνουν τα credentials σας, οπότε ανήκει σε ένα sandbox, στραμμένο στο lab stack του Μέρους 3, και πουθενά κοντά στην παραγωγή.

Ονόματα, IDs, και μια stop condition που ήρθε άδεια

Το Μέρος 2 έκανε θέμα με τα ονόματα ζωνών έναντι των IDs ζωνών, και το game day είναι εκεί που το θέμα αποδίδει. Οι αναφορές συμβάντων μιλούν σε IDs: η αναφορά του Μαΐου είπε use1-az4, οι ενημερώσεις του Μαρτίου είπαν mec1-az2 και μετά mec1-az3. Ο λογαριασμός σας μιλά σε ονόματα, aliases που η AWS τυχαιοποιεί ανά λογαριασμό. Και το εργαλείο, ως επί το πλείστον, απαιτεί το όνομα. Οι στόχοι instance και subnet φιλτράρουν στο Placement.AvailabilityZone, που ταιριάζει με το τοπικό όνομα του λογαριασμού σας, και το δημοσιευμένο σενάριο γεμίζει τις παραμέτρους στόχου EBS, RDS και ElastiCache με το όνομα επίσης. Ακριβώς δύο actions δέχονται το φυσικό ID: το ζεύγος insufficient-capacity, aws:ec2:api-insufficient-instance-capacity-error και aws:ec2:asg-insufficient-instance-capacity-error, των οποίων η παράμετρος availabilityZoneIdentifiers είναι τεκμηριωμένο ότι δέχεται zone IDs καθώς και ονόματα. Ακόμα και εκεί, το δημοσιευμένο σενάριο γεμίζει το πεδίο με ένα όνομα, us-east-1a.

Ένα game day επομένως ξεκινά με το πρόβλημα μετάφρασης για το οποίο το Μέρος 2 παρέδωσε ένα lab. Ο runner το επιλύει μία φορά, στην κορυφή: το μόνο zone flag που δέχεται το run.py είναι το --az-id, η φυσική ζώνη, αυτό που ονοματίζει μια αναφορά συμβάντος. Επιλύει το τοπικό όνομα του λογαριασμού μέσω DescribeAvailabilityZones, τυπώνει και τα δύο, και γεμίζει κάθε placeholder με τη μορφή που απαιτεί ο καταναλωτής του. Προβάρετε την αστοχία με το όνομα που θα της έδινε μια αναφορά συμβάντος, και η πρόβα διαμορφώνεται στη διάλεκτο που τυχαίνει να μιλά ο λογαριασμός σας.

Το δεύτερο πράγμα που ο runner αρνείται να κληρονομήσει είναι πιο σιωπηλό. Το block stop-condition του δημοσιευμένου σεναρίου μοιάζει κάπως έτσι, κατά λέξη:

"stopConditions": [
    {
        "source": "aws:cloudwatch:alarm",
        "value": ""
    }
]

Το σχήμα ενός guardrail χωρίς τίποτα μέσα του, και η ενότητα περιορισμών της σελίδας λέει ότι οι stop conditions είναι δικές σας να τις προσθέσετε. Μια υπερασπίσιμη προεπιλογή, αφού η AWS δεν μπορεί να ξέρει το steady state σας, αλλά και μια φορτισμένη, επειδή το JSON κολλιέται καθαρά και μια άδεια συμβολοσειρά δεν μοιάζει με ένα σύστημα ασφαλείας που λείπει. Η θέση του lab: το run.py βγαίνει πριν δημιουργήσει οτιδήποτε αν δεν δοθεί το --alarm-arn, επειδή ένα experiment χωρίς μια ουσιαστική stop condition δεν είναι δοκιμή, είναι στοίχημα. Το steady state είναι ένας αριθμός στον οποίο δεσμεύεστε πριν από τη βλάβη, αλλιώς το game day δεν μπορεί να αποτύχει, και ένα game day που δεν μπορεί να αποτύχει δεν μπορεί να σας πει τίποτα.

Πώς μοιάζει ένα πέρασμα, μετρημένο

Τρέξτε το experiment απέναντι στο stack δύο διαδρομών του Μέρους 3, ρίχνοντας μία από τις δύο ζώνες του:

python3 run.py experiments/az-power-interruption.json \
  --az-id euw1-az1 \
  --fis-role-arn arn:aws:iam::111111111111:role/fis-game-day \
  --alarm-arn arn:aws:cloudwatch:eu-west-1:111111111111:alarm:game-day-abort \
  --target-group-arn ... \
  --inject

Χωρίς το --inject η ίδια εντολή είναι ένα dry run: τυπώνει το επιλυμένο template και δεν ξεκινά τίποτα. Με αυτό, ο runner δημιουργεί και ξεκινά το experiment, μετά κάνει poll μέχρι μια τερματική κατάσταση, καταγράφοντας την κατάσταση κάθε action και δειγματοληπτώντας τον υγιή αριθμό του target group ως τη μέτρηση. Αυτό το χρονοδιάγραμμα είναι το παραδοτέο, αυτό που ακολουθεί είναι το σχήμα ενός περάσματος, όχι ένα αποτέλεσμα που έχω πάρει, επειδή δεν έχω λογαριασμό σε μορφή παραγωγής για να το κερδίσω. Η Διαδρομή B, η στατικά σταθερή, δεν πέφτει ποτέ κάτω από την απαίτησή της μετά την αστοχία για δύο υγιείς στόχους, αφού η επιζήσασα ζώνη κουβαλά ήδη το φορτίο. Η Διαδρομή A πέφτει στο μισό και μένει εκεί για όλη τη διάρκεια της βλάβης, επειδή το ίδιο experiment που σταμάτησε τα instances της τροφοδοτεί τις εκκινήσεις αντικατάστασής της με InsufficientInstanceCapacity. Το script μέτρησης του Μέρους 3 χρονομέτρησε την ανάκτηση της Διαδρομής A απέναντι σε ένα συνεργάσιμο control plane, το game day δείχνει την ίδια διαδρομή απέναντι σε ένα μη συνεργάσιμο, και η διαφορά ανάμεσα σε αυτούς τους δύο αριθμούς είναι το μέγεθος της υπόθεσης που έκανε το σχέδιο DR σας.

Τέσσερις αριθμοί αξίζει να καταγραφούν. Ο χρόνος μέχρι την ανακτημένη χωρητικότητα, από τα δείγματα υγιών στόχων. Ο αριθμός των βημάτων του runbook που χρειάζονταν μια κλήση control plane που θα είχε αποτύχει, μετρημένος περπατώντας το runbook σας κατά το παράθυρο της βλάβης. Η διαφορά ανάμεσα στον συνεργάσιμο αριθμό του Μέρους 3 και τον μη συνεργάσιμο του game day. Και η μοίρα κάθε ευρήματος από τον ανιχνευτή του Μέρους 1, αφού κάθε γραμμή που τυπώνει είναι μια πρόβλεψη που το game day μπορεί να διευθετήσει: το Auto Scaling group μίας AZ όντως εγκλωβίζει τη χωρητικότητά του πίσω από ένα σφάλμα χωρητικότητας, το subnet της υγιούς ζώνης του οποίου η προεπιλεγμένη διαδρομή περνά στη ζώνη που αστόχησε όντως χάνει το egress. Ένα εύρημα ανιχνευτή είναι μια υπόθεση. Ένα game day είναι το πείραμα.

Η άσκηση control plane που το FIS δεν μπορεί να σας δώσει

Η υπόθεση του Μέρους 3 είναι δυσκολότερη, και εδώ η ειλικρινής πρόταση έρχεται πρώτη: το FIS δεν έχει action απώλειας control plane. Το πλήρες actions reference δεν περιέχει ποτέ τη φράση, και τίποτα μέσα του δεν αφαιρεί ένα control plane. Τα πλησιέστερα είναι εισαγωγές σφαλμάτων με εμβέλεια σε callers που ονομάζετε: το ζεύγος insufficient-capacity παραπάνω, και μια τριάδα γενικών actions σφάλματος API (internal, throttle, unavailable) που εισάγουν αστοχίες σε αιτήματα που κάνουν ονομασμένα IAM roles, μόνο για τα namespaces EC2 και Kinesis. Το plane μένει όρθιο, επιλεγμένοι callers παίρνουν άρνηση. Τίποτα που μπορείτε να νοικιάσετε δεν αναπαράγει την κονσόλα να σερβίρει 504 ενώ το STS αστοχεί τρεις ξεχωριστές φορές.

Έτσι το δεύτερο template του lab είναι μια προσέγγιση και επισημαίνεται ως τέτοια, σε ένα κλειδί approximation ανώτατου επιπέδου μέσα στο ίδιο το αρχείο, ώστε η ετικέτα να μην μπορεί να αποκλίνει από το πράγμα που επισημαίνει. Το μισό FIS εισάγει InsufficientInstanceCapacity στις εκκινήσεις των ASGs του workload και στις κλήσεις χωρητικότητας του deploy role, RunInstances, CreateFleet, StartInstances, CreateCapacityReservation, στη ζώνη που αστόχησε για είκοσι λεπτά. Το άλλο μισό δεν είναι καθόλου FIS: ένα χειροκίνητο, οριοθετημένο, χρονικά περιορισμένο IAM deny στα ec2:RunInstances, autoscaling:* και cloudformation:*, που είναι αυτό που μετατρέπει το βήμα του runbook "απλώς σπρώξε το emergency stack" στην αστοχία που θα ήταν τον Ιούνιο του 2023. Το run.py τυπώνει τις εντολές apply και remove και δεν τις εκτελεί ποτέ, το χρονικό όριο αποφασίζεται πριν συνδεθεί η πολιτική, και το deny δεν μπαίνει ποτέ στο role που θα χρειαστείτε για να το αφαιρέσετε. Αυτός ο τελευταίος κανόνας δεν είναι σχολαστικισμός, είναι η διαφορά ανάμεσα σε μια άσκηση και ένα συμβάν.

Τι δεν αναπαράγει η προσέγγιση, από τη δική της λίστα στο αρχείο: η πραγματική υποβάθμιση control plane είναι latency και brownout, σπάνια ένα καθαρό σφάλμα, υπηρεσίες που το αρχείο δεν ονοματίζει ποτέ, ELB, Route 53, το ίδιο το IAM, η κονσόλα, συνεχίζουν να δουλεύουν εδώ και μπορεί να μη δουλεύουν σε ένα πραγματικό συμβάν, οι αναγνώσεις συνεχίζουν να πετυχαίνουν, οπότε τα dashboards σας δείχνουν υγιέστερα από ό,τι θα ήταν, μη-σχετιζόμενες με χωρητικότητα μεταλλάξεις όπως TerminateInstances και αλλαγές διαμόρφωσης load balancer συνεχίζουν να πετυχαίνουν, οπότε αυτό αρνείται τη δημιουργία χωρητικότητας, όχι το control plane, και είναι η χωρητικότητα μίας ζώνης, ενώ ένα πραγματικό συμβάν μπορεί να είναι περιφερειακό. Μετρήστε ένα επιπλέον πράγμα σε αυτή την άσκηση: τον χρόνο μέχρι την ανίχνευση. Πόσο χρόνο χρειάστηκε ένας άνθρωπος για να παρατηρήσει ότι η διόρθωση δεν δούλευε; Αν κάποιος σας πει ότι προσομοίωσε την απώλεια control plane, ρωτήστε ποιο από αυτά τα πέντε κενά κάλυψε. Το δικό μου δεν καλύπτει κανένα από αυτά επίσης, καλύπτει τον στενότερο ισχυρισμό ότι η αρχιτεκτονική σας δεν χρειάζεται τις απορριφθείσες κλήσεις μέσα στην πρώτη ώρα.

Βαθμολογώντας τη σειρά

Τέσσερα συμβάντα, τέσσερα labs, μία ραχοκοκαλιά. Τι εδραίωσε η σειρά, κρατημένο στο δικό της πρότυπο: ένας ισχυρισμός μετρά μόνο αν στηρίζεται στα δημοσιευμένα λόγια του operator. Πρώτον, η απομόνωση ζωνών είναι πραγματική ενάντια στις βλάβες για τις οποίες είναι σχεδιασμένη: το thermal event του Μαΐου έμεινε μέσα στην use1-az4, και η αρχιτεκτονική που αστόχησε εκείνο το βράδυ αστόχησε κατά την ομολογία του ίδιου του postmortem της, όχι της AWS. Δεύτερον, οι αστοχίες ζωνών δεν είναι ανεξάρτητα γεγονότα: μία αιτία έφτασε στην mec1-az2 και την mec1-az3 με διαφορά δεκαοκτώ ωρών, και δύο χαμένες ζώνες πήγαν τις περιφερειακές υπηρεσίες πέρα από τη δηλωμένη ανοχή τους της μίας ζώνης. Τρίτον, το control plane αστοχεί ενώ το data plane συνεχίζει να τρέχει, σε περισσότερους από έναν πάροχο, και τα σχέδια ανάκτησης που είναι λειτουργίες control plane αστοχούν μαζί του: το 2023 και ο Οκτώβριος του 2025 στα ίδια τα post-event summaries της AWS, ο Φεβρουάριος του 2026 σε αυτό της Azure.

Τώρα η άλλη στήλη, επειδή μια αναδρομή που μετρά μόνο τις νίκες είναι μάρκετινγκ. Τι παραμένει υπόθεση: όλα τα ποσοτικά για εσάς. Ποτέ δεν έτρεξα αυτά τα labs απέναντι σε έναν στόλο παραγωγής, οπότε κάθε αριθμός στη σειρά είναι το σχήμα μιας εξόδου, ειλικρινά επισημασμένο αλλά και πάλι ένα σχήμα. Το κόστος thundering-herd του μαζικού failover, το "longer than usual provisioning times" της AWS, εμφανίζεται σε δύο συμβάντα και ποτέ δεν του δόθηκε αριθμός, ούτε από την AWS ούτε από εμένα. Το ασφάλιστρο static-stability του Μέρους 3 ήταν αριθμητική, όχι ένας λογαριασμός από έναν πραγματικό στόλο. Και το αν δουλεύει η διαδρομή break-glass σας είναι άγνωστο από εδώ.

Τι θα έκανα διαφορετικά: θα έτρεχα το game day πρώτο, όχι τελευταίο. Η σειρά διέταξε τα labs της παιδαγωγικά, ανίχνευσε, μετάφρασε, μέτρησε, εισήγαγε, και αυτή η σειρά είναι ανάποδη λειτουργικά: μία εκτέλεση injection παράγει τη λίστα ευρημάτων που ο ανιχνευτής μπορεί μόνο να προβλέψει. Και θα είχα δυσπιστήσει στις δευτερογενείς πηγές νωρίτερα. Ο κανόνας, παράθεσε μόνο από την ίδια τη σελίδα του operator, συνέχισε να αποδεικνύει την αξία του μέχρι το τέλος: έπιασε λάθος διάρκειες, μια χρονοσήμανση λάθος κατά μισή μέρα, και ισχυρισμούς των οποίων οι φαινομενικές πηγές, όταν ανακτήθηκαν, δεν τους περιείχαν. Μια σειρά για τις αδοκίμαστες υποθέσεις παραλίγο να παραδώσει αρκετές, που είναι περίπου η καθαρότερη επίδειξη της ίδιας της θέσης της που θα μπορούσα να είχα οργανώσει.

Και τα game days αστοχούν

Το όργανο αξίζει τον ίδιο σκεπτικισμό με το πράγμα που μετρά, οπότε ας τελειώσουμε με τους τρεις τρόπους που ένα game day σας λέει ψέματα.

  • Η δοκιμή που αποδεικνύει μόνο ότι η δοκιμή έτρεξε. Το FIS επιλύει στόχους με tag, και μια αναντιστοιχία tag δεν αποτυγχάνει το experiment: το σενάριο AZ παραλείπει actions των οποίων οι στόχοι επιλύονται στο τίποτα, και το lab κρατά αυτή τη συμπεριφορά (emptyTargetResolutionMode: skip) ώστε να μπορούν να τρέξουν μερικά stacks. Το τίμημα: ένα experiment μπορεί να φτάσει σε completed χωρίς να έχει σταματήσει τίποτα. Πράσινο αποτέλεσμα, μηδέν βλάβες εισηγμένες. Διαβάστε τον πίνακα ανά action, όχι τη γραμμή κατάστασης, το template του control plane θέτει fail αντ' αυτού, αφού εκεί ένας άδειος στόχος κάνει την εκτέλεση άσκοπη. Οι κωδικοί εξόδου συμφωνούν: το completed βγαίνει με 0, ένα stopped experiment βγαίνει με 1 παρόλο που το σταμάτημα σημαίνει ότι το alarm σας δούλεψε. Το άναμμα του guardrail είναι το guardrail που δουλεύει, και και πάλι δεν είναι πέρασμα.
  • Η stop condition που ενεργοποιείται πολύ νωρίς. Δέστε το alarm σε μια εσωτερική μετρική με ένα σφιχτό κατώφλι και το experiment σταματά στα δύο λεπτά, πριν την ενδιαφέρουσα αστοχία. Μαθαίνετε μόνο ότι το alarm ενεργοποιείται, και ο πειρασμός μετά είναι να το χαλαρώσετε ή να το αφαιρέσετε, που είναι πώς φτάνετε πάλι στην άδεια συμβολοσειρά του σεναρίου με επιλογή σας. Η διόρθωση δεν είναι λιγότερο guardrail, είναι το δέσιμο του alarm στη μετρική steady-state που βλέπει ο χρήστης, στο κατώφλι όπου θα θέλατε να σταματήσει ένα πραγματικό συμβάν.
  • Ο λογαριασμός που δεν είναι παραγωγή. Ένα πέρασμα σε sandbox αποδεικνύει τον μηχανισμό, όχι το αποτέλεσμα. Καμία κίνηση παραγωγής, καμία βαρύτητα δεδομένων, κανένας θορυβώδης γείτονας, κανένας operator ξυπνημένος στις 3 τα ξημερώματα. Προσθέστε τη δική της απαλότητα του injection, ομαλά shutdowns, καθαρά σφάλματα αντί για brownouts, και η ειλικρινής αλυσίδα αποδείξεων διαβάζεται ως εξής: ο ανιχνευτής προβλέπει, το game day στο sandbox δοκιμάζει τον μηχανισμό της πρόβλεψης, και η παραγωγή κληρονομεί μια επισημασμένη προεκβολή. Αυτό είναι πολύ καλύτερο από το τίποτα και πολύ λιγότερο από απόδειξη, και το να προσποιείσαι το αντίθετο είναι πώς το "κάναμε chaos engineering" γίνεται μία ακόμα αδοκίμαστη υπόθεση.

Εκεί τελειώνει η σειρά. Τίποτα δεν αστοχεί μόνο του: κάθε μέρος βρήκε την αστοχία μπλεγμένη με κάτι δίπλα της, ένα quorum με ένα κτίριο, μια ζώνη με έναν πόλεμο, μια διόρθωση με ένα control plane. Ούτε τίποτα περνά μόνο του. Κάθε πέρασμα είναι μπλεγμένο με το περιβάλλον που το παρήγαγε, και η ετικέτα που το λέει είναι η πιο φέρουσα γραμμή στην αναφορά.

Διαβάστε στη συνέχεια

  • Το Μέρος 3 αυτής της σειράς: The Fix Shares Fate With the Outage, τα συμβάντα control plane που προσεγγίζει το δεύτερο experiment αυτού του μέρους.
  • Το Μέρος 1 αυτής της σειράς: AZ Isolation Held. Your Architecture Didn't., όπου ο ανιχνευτής παρήγαγε τις προβλέψεις που το game day αυτού του μέρους υπάρχει για να διευθετήσει. Ο κύκλος κλείνει.
  • Evals Before Agents: You Can't Ship What You Can't Score στο ercan.ai: η ίδια πειθαρχία σε άλλον τομέα, ορίστε τη συνθήκη επιτυχίας και τη βαθμολογία πριν τρέξει το σύστημα, επειδή το "ένιωθε μια χαρά" δεν είναι μέτρηση ούτε εκεί.
  • Το συνοδευτικό repo: nothing-fails-alone, και τα τέσσερα labs, αυτό εισάγει πραγματικές βλάβες και το δηλώνει στην κορυφή.

Για συμβουλευτική σε AWS, cloud αρχιτεκτονική, επισκοπήσεις ανθεκτικότητας, και platform δουλειά, ξεκινήστε από το ercanermis.com.

Αναφορές