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

Load average: τρεις αριθμοί και μια συνηθισμένη παρανόηση

uptime
cat /proc/loadavg
nproc

Οι τρεις αριθμοί είναι μέσοι όροι ενός, πέντε και δεκαπέντε λεπτών. Δεν συγκρίνονται με το μηδέν αλλά με το πλήθος των πυρήνων που δίνει η nproc. Η τιμή 8 σε μηχάνημα με οκτώ πυρήνες είναι πλήρης αλλά υγιής φόρτος: υπάρχει ακριβώς τόση δουλειά όση προλαβαίνει ο διακομιστής. Η τιμή 2 σε VPS με έναν πυρήνα είναι ουρά διπλάσια από τη χωρητικότητα, και κάθε αίτημα περιμένει τη σειρά του.

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

Και τώρα η παρανόηση που χαλάει την ανάγνωση αυτών των αριθμών περισσότερο από κάθε άλλη. Στο Linux το load average δεν είναι «αξιοποίηση επεξεργαστή». Σε αντίθεση με άλλα συστήματα Unix, το Linux μετρά εκεί όχι μόνο τις διεργασίες που εκτελούνται ή είναι έτοιμες να εκτελεστούν, αλλά και όσες βρίσκονται σε κατάσταση D — σε αδιάκοπο ύπνο. Δηλαδή περιμένουν τον δίσκο ή ένα δικτυακό σύστημα αρχείων. Από εκεί προκύπτει ο διακομιστής με φόρτο 12 και σχεδόν αδρανή επεξεργαστή: η δουλειά δεν προχωρά, όλοι περιμένουν στην ουρά.

Επεξεργαστής ή δίσκος

Ο διαχωρισμός αυτών των δύο περιπτώσεων είναι το πρώτο πράγμα που αξίζει να γίνει:

vmstat 1 5
iostat -x 1 3

Στην έξοδο της vmstat μετράνε τρεις στήλες. Η r δείχνει πόσες διεργασίες περιμένουν στην ουρά για τον επεξεργαστή, η b πόσες είναι μπλοκαρισμένες περιμένοντας είσοδο-έξοδο και η wa το ποσοστό του χρόνου που ο επεξεργαστής έμεινε αδρανής περιμένοντας τον δίσκο. Ένα wa σταθερά πάνω από 10–15 % με μέτρια us και sy σημαίνει ότι ο διακομιστής περιορίζεται από τον δίσκο: η προσθήκη πυρήνων δεν ωφελεί, όσοι υπάρχουν είναι ήδη ελεύθεροι.

Ποιες διεργασίες περιμένουν μπορεί να καταγραφεί ονομαστικά:

ps -eo state,pid,comm,wchan:30 | awk '$1 ~ /^D/'

Ένα παράδειγμα από τη δική μας πρακτική. Με την προεπιλεγμένη διαμόρφωση, η Suricata γράφει περίπου τριάντα τύπους συμβάντων και δεν ρυθμίζει καμία εναλλαγή αρχείων γι’ αυτούς — σε διακομιστή σε παραγωγή αυτό έδωσε 15 GB αρχείων καταγραφής σε δύο ημέρες. Ο φόρτος δεν εκδηλωνόταν ως απασχολημένος επεξεργαστής αλλά ακριβώς ως I/O wait: το σύστημα έγραφε ασταμάτητα και όλα τα υπόλοιπα περίμεναν πίσω του. Η λύση δεν είναι μεγαλύτερο πακέτο, αλλά μικρότερη λίστα τύπων συμβάντων και ρυθμισμένη εναλλαγή.

Η αντίστροφη περίπτωση, καθαρά επεξεργαστική και πολύ λιγότερο προφανής. Μια ιστοσελίδα καλούσε το apt με τον χρήστη υπό τον οποίο τρέχει το PHP-FPM. Ο root διατηρεί μια δυαδική κρυφή μνήμη στο /var/cache/apt/pkgcache.bin — 70 MB σε μηχάνημα με μια ντουζίνα αποθετήρια — και τη χαρτογραφεί στη μνήμη χωρίς κόστος. Ένας απλός χρήστης δεν μπορεί να γράψει σε αυτόν τον κατάλογο και ξαναχτίζει την κρυφή μνήμη σε κάθε κλήση. Μετρήθηκε στο ίδιο ακριβώς μηχάνημα: 0,01 δευτερόλεπτα χρόνου επεξεργαστή ως root έναντι 4,2 δευτερολέπτων ως χρήστης χωρίς προνόμια. Η ίδια εντολή, διαφορά τετρακόσιες φορές, πολλαπλασιασμένη με κάθε άνοιγμα της σελίδας.

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

Μνήμη: η free δεν δείχνει αυτό που φαίνεται

free -h

Η στήλη used από μόνη της λέει ελάχιστα, ενώ η στήλη free είναι κατευθείαν παραπλανητική: το Linux δίνει την αχρησιμοποίητη μνήμη στην κρυφή μνήμη σελίδων και την επιστρέφει στις εφαρμογές με το πρώτο αίτημα. Η στήλη που διαβάζεται είναι η available — πόση μνήμη μπορεί να καταληφθεί χωρίς να χρειαστεί swap. Ένα μεγάλο buff/cache δεν είναι πρόβλημα αλλά ένδειξη συστήματος που λειτουργεί όπως πρέπει.

Στο swap δεν μετράει η τρέχουσα τιμή αλλά το σχήμα. Ανέβηκε και επέστρεψε στο μηδέν: υπήρξε σύντομη κορύφωση. Ανέβηκε μία φορά και έμεινε εκεί: η κορύφωση έχει ήδη συμβεί, σελίδες εκτοπίστηκαν και κανείς δεν τις επαναφέρει — ο διακομιστής φαίνεται ήρεμος, αν και κάποια στιγμή η μνήμη δεν του έφτασε. Αν η ανταλλαγή γίνεται αυτή τη στιγμή, το δείχνουν οι στήλες si και so στη vmstat· τιμές διάφορες του μηδενός εκεί είναι η μορφή επιβράδυνσης που οι χρήστες αντιλαμβάνονται περισσότερο.

Αν κατά τη νυχτερινή πτώση μια διεργασία απλώς εξαφανίστηκε, η εξήγηση βρίσκεται συνήθως εδώ:

journalctl -k --since yesterday | grep -i "out of memory"
dmesg -T | grep -i "killed process"

Μια γραμμή της μορφής Out of memory: Killed process 1234 (mysqld) κλείνει το ζήτημα καλύτερα από κάθε γράφημα: η βάση δεδομένων δεν «έπεσε μόνη της», την σταμάτησε ο πυρήνας επειδή τελείωσε η μνήμη.

Ποιος το προκαλεί

ps aux --sort=-%cpu | head -10
ps aux --sort=-%mem | head -10

Μια επιφύλαξη: το %CPU της ps είναι μέσος όρος για όλη τη ζωή της διεργασίας, οπότε μια σύντομη έξαρση χάνεται σε αυτή τη λίστα. Γι’ αυτήν χρειάζονται η top ή η pidstat 1 5, που μετρούν σε διάστημα.

Πότε ο φόρτος γίνεται ζήτημα ασφάλειας

Σταθερό 100 % επεξεργαστή τη νύχτα, με διεργασία που έχει όνομα χωρίς νόημα και κατάλογο εργασίας στο /tmp ή στο /dev/shm, είναι η κλασική εικόνα ενός εξορύκτη και όχι ενός ιστότοπου που μεγάλωσε. Αιχμή στην εισερχόμενη κίνηση μαζί με αύξηση των εγγραφών στα αρχεία καταγραφής είναι επίθεση σε κωδικούς που βρίσκεται σε εξέλιξη. Απότομη αύξηση του όγκου των αρχείων καταγραφής είναι κατά κανόνα καταιγίδα ψευδών συναγερμών κάποιου φίλτρου.

Ξεχωριστή κατηγορία αποτελούν τα ίδια τα εργαλεία προστασίας. Σε έναν από τους διακομιστές μας ο φόρτος κρατιόταν γύρω στο τρία χωρίς κανέναν επισκέπτη, και στην κορυφή της ps κατά συσσωρευμένο χρόνο επεξεργαστή δεν βρίσκονταν ούτε ο ιστότοπος ούτε η βάση, αλλά τα CrowdSec, fail2ban, Falco και Suricata. Δεν είναι βλάβη ούτε λόγος να απενεργοποιηθούν, αλλά το κόστος της προστασίας αξίζει να το ξέρει κανείς σε αριθμούς: σε μικρό VPS γίνεται αισθητό.

Σε τι χρησιμεύει η παρακολούθηση

Όλα τα παραπάνω απαντούν στο ερώτημα «τι συμβαίνει τώρα». Το πρωινό ερώτημα — τι έγινε στις τρεις τα ξημερώματα — δεν καλύπτεται από αυτές τις εντολές: για τη νύχτα που πέρασε δεν υπάρχουν δεδομένα αν δεν τα κατέγραψε κανείς. Και το να στηθεί Prometheus με Grafana για έναν μόνο VPS είναι αμφίβολο, καθώς η στοίβα που παρακολουθεί βγαίνει βαρύτερη από τον διακομιστή που παρακολουθείται.

Αρκεί μια γραμμή σε μια βάση δεδομένων κάθε πέντε λεπτά και μία σελίδα που σχεδιάζει από αυτήν το τελευταίο εικοσιτετράωρο: load average, αξιοποίηση επεξεργαστή και ξεχωριστά I/O wait, μνήμη και swap, ανάγνωση και εγγραφή δίσκου, πλήρωση του διαμερίσματος, inodes, περιγραφείς αρχείων, συνδέσεις. Σε έναν κοινό άξονα χρόνου τα ζεύγη διαβάζονται με γυμνό μάτι: υψηλό wa με ήρεμο επεξεργαστή, swap που δεν επέστρεψε ποτέ στο μηδέν, περιγραφείς που πλησιάζουν το όριο — το επερχόμενο σφάλμα too many open files γίνεται ορατό ώρες πριν συμβεί. Πώς φαίνονται όλα αυτά συγκεντρωμένα το δείχνει η σελίδα επίδειξης παρακάτω.