Въпросът звучи почти винаги еднакво: през нощта сайтът отговаряше по двайсет секунди, а до сутринта всичко се оправи само. Няма какво повече да се гледа — top отговаря за текущата секунда, а питането е за три часа през нощта. По-долу е какво наистина означават числата на натоварването, кои от тях трябва да се четат по двойки и защо еднократното измерване подвежда по-често, отколкото помага.

Load average: три числа и едно често недоразумение

uptime
cat /proc/loadavg
nproc

Трите числа са средни стойности за една, пет и петнайсет минути. Сравняват се не с нула, а с броя ядра, който показва nproc. Стойност 8 на машина с осем ядра е пълно, но здравословно натоварване: работата е точно толкова, колкото сървърът може да свърши. Стойност 2 на VPS с едно ядро е опашка два пъти по-дълга от възможностите и всяка заявка чака своя ред.

Съотношението между трите числа показва посоката. Едноминутното значително над петнайсетминутното означава, че натоварването расте точно сега. Обратното означава, че пикът вече е минал и се вижда само опашката му.

Сега за недоразумението, заради което тези числа най-често се разбират погрешно. Load average в Linux не е „натоварване на процесора“. За разлика от други Unix системи, Linux брои в него не само процесите, които се изпълняват или са готови за изпълнение, но и онези в състояние D — непрекъсваем сън. Тоест чакащите диска или мрежова файлова система. Оттам идва сървърът с load 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 ГБ дневници за две денонощия. Натоварването при това се изразяваше не в зает процесор, а именно в I/O wait: системата пишеше непрекъснато, а всичко останало чакаше на опашка зад нея. Лекува се не с по-голям план, а с по-кратък списък от типове събития и настроена ротация.

Обратният случай, чисто процесорен и доста по-малко очевиден. Уеб страница извикваше apt от името на потребителя, под който работи PHP-FPM. Root държи двоичен кеш в /var/cache/apt/pkgcache.bin — на хост с десетина хранилища това са 70 МБ — и го прикачва в паметта безплатно. Обикновеният потребител няма право да пише в тази директория и преизгражда кеша при всяко извикване. Измерено на една и съща машина: 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, е класическата картина на копач, а не на пораснал сайт. Скок на входящия трафик заедно с растеж на записите в дневниците е текуща атака срещу пароли. Рязко нараснал обем на дневниците обикновено е буря от фалшиви сработвания на някой филтър.

Отделна категория са самите защитни инструменти. На един от нашите сървъри load се държеше около три при пълна липса на посетители, а начело на ps по натрупано процесорно време стояха не сайтът и не базата, а CrowdSec, fail2ban, Falco и Suricata. Това не е авария и не е повод да бъдат изключвани, но цената на защитата е полезно да се знае в числа: на слаб VPS тя се усеща.

Смисълът на наблюдението

Всичко изброено отговаря на въпроса „какво се случва сега“. Сутрешното „какво е било в три през нощта“ тези команди не покриват: данни за отминалата нощ няма, ако никой не ги е записал. А да се разгръща Prometheus с Grafana заради един VPS е съмнително — наблюдаващият стек излиза по-тежък от наблюдавания сървър.

Достатъчен е ред в базата на всеки пет минути и една страница, която рисува по него последното денонощие: load average, натоварване на процесора и отделно I/O wait, памет и swap, четене и запис на диска, запълване на дяла, inode-и, файлови дескриптори, връзки. В един времеви мащаб двойките се четат с просто око: високо wa при спокоен процесор, swap, който не се е върнал до нулата, дескриптори, доближили лимита — бъдещата грешка too many open files се вижда часове преди да се случи. Как изглежда всичко това събрано, показва демо страницата по-долу.