Практическая настройка производительности Linux-серверов под нагрузкой: CPU, память, диск и сеть | AdminWiki

Практическая настройка производительности Linux-серверов под нагрузкой: CPU, память, диск и сеть

31 августа 2026 19 мин. чтения
Содержание статьи

Что действительно влияет на производительность Linux-сервера

Производительность Linux-сервера улучшается после устранения конкретного узкого места. Сначала измеряют задержки и загрузку ресурсов, затем меняют одну связанную группу параметров: приоритеты процессов, лимиты, управление памятью, дисковую очередь, сетевые буферы или расписание фоновых задач.

Заметный эффект чаще дают корректно выбранные CPU- и I/O-приоритеты, достаточный лимит файловых дескрипторов, подходящая стратегия работы со swap и dirty pages, настройка очередей под тип накопителя и устранение конкуренции между основным сервисом и backup. Массовое копирование готового sysctl-рецепта без измерений часто не меняет результат или увеличивает задержки.

Профиль нагрузки определяет подход. Веб-сервис обычно упирается в число workers, backlog, файловые дескрипторы и сетевые задержки. База данных чувствительна к latency диска, fsync, памяти и блокировкам. Файловый сервер зависит от последовательной пропускной способности, page cache и очереди накопителя. Контейнерный хост требует контроля cgroups v2, CPU limits, memory pressure и конкуренции между контейнерами.

Тип нагрузкиЧто проверить первымНастройки, которые могут дать эффект
HTTP reverse proxy или APIp95/p99 latency, число workers, backlog, file descriptors, retransmitsLimitNOFILE, CPUWeight, somaxconn, qdisc, сетевые очереди
Реляционная база данныхawait, fsync latency, memory pressure, swap, lock waitpage cache, dirty pages, I/O priority, память, лимиты соединений
Файловое хранилищеthroughput, queue depth, await, cache hit rate, тип операцийread-ahead, scheduler, I/O weight, расписание backup
Контейнерный хостCPU steal, PSI, cgroup limits, memory.events, I/O waitCPUQuota, CPUWeight, MemoryMax, IOWeight, TasksMax

Версия ядра, systemd, драйвер накопителя, объем RAM, виртуализация и архитектура приложения меняют результат. Для отдельного тестового стенда можно использовать облачный сервер с управляемыми ресурсами, например VDS или VPS в Timeweb Cloud, но итоговую конфигурацию проверяют на том же типе оборудования и под тем же сценарием нагрузки, что используется в production.

Практические шаблоны sysctl и сценарии для веб-сервисов, контейнеров и баз данных собраны в руководстве по разгону Linux-серверов для DevOps. В этой статье акцент сделан на методике выбора параметров и проверке их фактического эффекта.

Диагностика: как найти узкое место до тюнинга

Любое изменение начинайте с baseline, то есть зафиксированного состояния системы. Снимите показатели в обычный период и во время реального пика. Одного запуска top недостаточно: он показывает моментальный срез, а причина задержек может проявляться только при заполнении очереди, росте swap или пересечении нескольких фоновых задач.

Какие метрики снять перед изменениями

Минимальный baseline должен связывать ресурсы операционной системы с метриками приложения. Запишите загрузку CPU по user, system, iowait и steal, load average, число runnable-задач, доступную память, активность swap, PSI для CPU, памяти и I/O, задержку диска, throughput, сетевые ошибки, retransmits, dropped packets, p95/p99 latency и error rate сервиса.

Команды для первичной проверки:

uptime
top
vmstat 1 10
free -h
swapon --show
pidstat -dur 1 10
iostat -xz 1 10
ss -s
ss -lnt
ip -s link
sysctl -a
systemctl show app.service
cat /proc/1234/limits
cat /proc/pressure/cpu
cat /proc/pressure/memory
cat /proc/pressure/io

uptime и load average показывают длину общей очереди задач, но не говорят, какой ресурс занят. Сравнивайте load average с числом логических CPU и выводом vmstat. Поле r указывает на очередь выполняемых задач, b помогает заметить процессы, ожидающие I/O.

В top ищите раздельно user, system, iowait и steal. Высокий steal на виртуальной машине указывает на конкуренцию за CPU на гипервизоре. Увеличение system может быть связано с сетью, большим количеством системных вызовов или контейнерной нагрузкой.

free -h используйте для оценки поля available, а не только free. Linux заполняет свободную RAM page cache, поэтому небольшое значение free само по себе не означает дефицит памяти. В vmstat поля si и so показывают движение страниц через swap. PSI показывает время, когда задачи ожидали освобождения ресурса, и помогает увидеть давление, которое не всегда заметно по средней загрузке.

iostat -xz дает значения await, r/s, w/s, aqu-sz и %util. Сопоставляйте их с p95/p99 приложения. Высокий throughput при приемлемой latency может быть нормальным режимом. Низкий throughput и растущий await чаще указывают на насыщение накопителя, неподходящий queue depth или конкуренцию процессов.

Для расширенного чек-листа по CPU, памяти, диску и сети используйте руководство по метрикам производительности Linux-сервера. Метрики приложения при этом остаются главным критерием: сервер может выглядеть свободным, пока запросы ждут блокировку, connection pool или медленный SQL.

Как отличить CPU-, memory-, I/O- и network-bound нагрузку

  • CPU-bound. Высокие user или system, заполненная очередь r в vmstat, низкий iowait и рост latency при увеличении числа запросов. Проверьте CPU utilization по ядрам, affinity, количество workers и CPU steal.
  • Memory-bound. Падает available, растут PSI memory, swap in/out и частота reclaim. Приложение может замедляться при формально невысокой средней загрузке CPU.
  • I/O-bound. Увеличиваются iowait, await и aqu-sz, процессы находятся в состоянии ожидания диска. Причиной может быть накопитель, контроллер, файловая система, fsync или фоновая запись dirty pages.
  • Network-bound. Растут retransmits, dropped packets, receive errors, очереди Recv-Q и Send-Q. Низкая скорость может быть связана с RTT, ограничением виртуального интерфейса, провайдером или qdisc.

Смешанная нагрузка встречается чаще чистой. Например, база данных может создавать очередь диска, после чего workers начинают занимать CPU в ожидании таймеров и повторных запросов. Если одна операция SQL стабильно медленная, connection pool исчерпан или контейнер получил жесткий CPU limit, изменение sysctl не устранит причину.

Безопасный цикл тюнинга Linux-сервера

Настройка должна быть воспроизводимым экспериментом. Определите гипотезу, сохраните исходные значения, измените один параметр или связанную группу, запустите одинаковую нагрузку, сравните метрики, проверьте перезапуск и подготовьте откат.

Временные и постоянные изменения

Временные параметры ядра можно проверить через sysctl -w. Они действуют до перезагрузки и подходят для контролируемого эксперимента:

sysctl -n vm.swappiness
sysctl -w vm.swappiness=10
sysctl -n net.core.somaxconn

Постоянные значения храните в отдельном файле, например /etc/sysctl.d/90-performance.conf, а затем применяйте командой sysctl --system. Сначала проверьте, что параметр существует в текущем ядре, и зафиксируйте фактическое значение после применения.

sysctl -a 2>/dev/null > /root/sysctl-before.txt
sysctl --system
sysctl -n vm.swappiness
systemctl show app.service -p CPUWeight -p IOWeight -p LimitNOFILE

Для systemd-сервиса создайте drop-in через systemctl edit app.service. Сервисные параметры могут потребовать перезапуска, а некоторые настройки ядра или драйвера требуют перезагрузки. Проверяйте итоговую конфигурацию через systemctl show, а не по содержимому только что измененного файла.

Откат выполняйте сохраненным значением. Для drop-in можно использовать systemctl revert app.service, после чего перезапустить сервис и проверить его состояние через systemctl status app.service. Runtime-изменения возвращайте отдельной командой sysctl -w.

Как доказать, что настройка помогла

Сравнивайте один и тот же сценарий, длительность теста, размер данных, число клиентов и режим прогрева кэша. Записывайте throughput, p95/p99 latency, error rate, CPU steal, iowait, await, сетевые потери и потребление памяти.

Настройка полезна, если целевая метрика улучшилась, а побочные показатели не вышли за допустимые пределы. Увеличение throughput ценой резкого роста p99 или swap не дает рабочего результата. Единичный удачный запуск тоже недостаточен: повторите тест несколько раз и проверьте поведение после перезапуска сервиса и хоста.

Проверяйте версию ядра, systemd, дистрибутива, драйвера накопителя и контейнерного runtime. Один и тот же параметр может иметь другую область действия или отсутствовать в другой версии.

Управление приоритетами процессов Linux

Приоритеты меняют распределение дефицитного ресурса между процессами. Они не создают дополнительные CPU-циклы, дисковую пропускную способность или память. Поэтому приоритеты помогают, когда критичный сервис конкурирует с backup, архивированием, компиляцией или batch-задачей.

nice и renice для CPU-нагрузки

Значение nice находится в диапазоне от -20 до 19. Чем меньше число, тем выше относительный приоритет планирования CPU. Значение 0 используется по умолчанию. Повышать приоритет, то есть уменьшать nice, обычно может root или процесс с нужным правом. Обычный пользователь может увеличить nice и снизить влияние своей задачи.

nice -n 10 /usr/local/bin/backup
renice 10 -p 1234
ps -o pid,ni,stat,cmd -p 1234

Для backup, архивирования и компиляции обычно начинают с положительного nice, например 10 или 15, и проверяют p95 основного сервиса. Критичному сервису не задавайте отрицательный nice без измерений: это может вытеснить системные процессы и ухудшить общую стабильность.

renice меняет значение уже запущенного процесса. Дочерние процессы могут получить отдельное значение, а supervisor или systemd способен перезаписать параметры при перезапуске. Поэтому ручная команда подходит для короткого эксперимента, а постоянную политику задавайте на уровне unit или контейнера.

ionice и приоритет дисковых операций

ionice управляет классом и приоритетом I/O. Класс idle передает дисковый ресурс процессу только при отсутствии конкуренции. Класс best-effort использует приоритет от 0 до 7, где меньшее значение дает больше предпочтения. Класс realtime применять осторожно: процесс может вытеснить критичные операции и увеличить latency.

ionice -c 3 /usr/local/bin/backup
ionice -c 3 -p 1234
ionice -c 2 -n 6 -p 1234
ionice -p 1234

На HDD эффект от разграничения I/O часто заметнее из-за ограниченной механики и длинной очереди. SSD и NVMe имеют меньшую задержку, но backup все равно способен занять пропускную способность и очередь устройства. На некоторых I/O-моделях, драйверах и файловых системах влияние ionice ограничено, поэтому проверяйте его через iostat и latency приложения.

Высокий await может сохраняться при низком приоритете процесса, если накопитель уже насыщен, контроллер выполняет сборку мусора или storage ограничивает IOPS. В таком случае ionice меняет очередность, но не устраняет аппаратное ограничение.

systemd и cgroups v2 для постоянных ограничений

Для сервисов удобнее задавать политику в systemd drop-in. В системах с cgroups v2 параметры CPU и I/O применяются ко всей группе процессов unit, включая дочерние процессы.

[Service]
CPUWeight=200
IOWeight=50
CPUQuota=200%
Nice=5

CPUWeight задает относительный вес при конкуренции за CPU. CPUQuota=200% ограничивает группу примерно двумя CPU, но точное поведение зависит от scheduler и нагрузки. IOWeight распределяет вес дискового ресурса, если контроллер I/O доступен и storage поддерживает нужную модель.

systemctl edit backup.service
systemctl daemon-reload
systemctl restart backup.service
systemctl show backup.service -p CPUWeight -p CPUQuotaPerSecUSec -p IOWeight
systemctl status backup.service

Для Docker используйте ограничения runtime, например --cpus, --cpu-shares или параметры Compose, поддерживаемые вашей версией. CPU shares в cgroups задают относительный вес, а CPU limit задает потолок. Проверьте итоговые значения внутри контейнера и на хосте: контейнер может показывать доступную квоту иначе, чем физическая машина.

Настройка лимитов в Linux

Ошибки с лимитами часто выглядят как внезапные отказы при свободных CPU и RAM. Сервис исчерпывает file descriptors, процессы, потоки или соединения, после чего начинает возвращать ошибки.

Почему ulimit не меняет лимит сервиса

ulimit показывает ограничения текущей shell-сессии. Сервис, запущенный через systemd, получает окружение unit и не обязан наследовать значение из интерактивного терминала. При запуске через PAM, Docker или другой supervisor действует отдельная цепочка ограничений.

ulimit -n
ulimit -u
systemctl show app.service -p LimitNOFILE -p LimitNPROC -p TasksMax
cat /proc/1234/limits

Для systemd задайте параметры в drop-in:

[Service]
LimitNOFILE=65536
LimitNPROC=8192
TasksMax=8192

/etc/security/limits.conf и файлы в /etc/security/limits.d работают через PAM. Они влияют на сессии, которые проходят через соответствующий PAM-модуль. Для systemd-unit этот файл часто не меняет фактическое значение. Проверяйте лимит у PID работающего сервиса в /proc/1234/limits.

В контейнере задавайте лимиты через runtime, например --ulimit nofile=65536:65536, и сверяйте их внутри контейнера. Ограничение cgroup TasksMax контролирует число задач группы и может остановить рост процессов даже при высоком LimitNPROC.

Как выбрать nofile и nproc без завышения

Для nofile посчитайте максимальное число клиентских соединений, upstream-сокетов, listening sockets, файлов журналов, временных файлов и внутренних дескрипторов. Добавьте запас, подтвержденный нагрузочным тестом. У веб-сервера значение часто зависит от числа workers и модели событий, поэтому копирование числа 100000 без расчета ничего не доказывает.

nproc учитывает процессы и потоки, которые видит выбранный механизм лимитов. Учитывайте workers, helper-процессы, потоки runtime и запас для аварийных операций. Большой лимит не ускоряет приложение и может позволить утечке процессов быстрее исчерпать CPU и память.

После изменения проверьте ошибки приложения, число открытых дескрипторов, число потоков и фактический отказ при достижении предела. Превышение лимита должно быть диагностируемым событием, а не поводом бесконечно увеличивать значение.

Оптимизация кэширования Linux и управление памятью

Linux использует свободную RAM для page cache. Кэш ускоряет повторное чтение файлов и снижает обращения к диску, поэтому большой buff/cache в free -h обычно означает эффективное использование памяти. Ориентир для дефицита, поле available, PSI memory, swap activity и поведение приложения.

Page cache, available memory и очистка кэша

Регулярная очистка page cache редко ускоряет сервер. Она удаляет полезные данные, после чего приложение снова читает их с диска. Это увеличивает I/O и может поднять latency.

free -h
cat /proc/meminfo
sync
echo 3 > /proc/sys/vm/drop_caches
free -h

drop_caches подходит для диагностического сравнения, когда нужно отделить эффект page cache от скорости накопителя. Запускать его по расписанию в production не следует. Перед тестом фиксируйте latency и прогревайте кэш одинаковым способом.

Swap, swappiness и OOM killer

Проверяйте swap через free -h, swapon --show, vmstat и PSI memory. Параметр vm.swappiness не означает процент заполнения RAM. Он влияет на относительную готовность ядра вытеснять анонимные страницы по сравнению с reclaim page cache.

sysctl vm.swappiness
free -h
swapon --show
vmstat 1 10
cat /proc/pressure/memory

Отключение swap не дает универсального ускорения. При кратком memory pressure swap может сохранить работающий сервис, а без него ядро быстрее придет к OOM killer. При чувствительности к latency полезно снизить активность swap, но значение проверяют на конкретном объеме RAM и профиле нагрузки.

OOM killer завершает процесс, когда ядро или memory cgroup не может удовлетворить запрос памяти. Ищите записи в журнале ядра, проверяйте memory limit контейнера и контролируйте PSI. Если OOM возникает из-за неверного лимита cgroup, изменение глобального vm.swappiness проблему не решит.

Dirty pages и задержки записи

Запись сначала попадает в page cache как dirty pages. Параметры vm.dirty_background_ratio или vm.dirty_background_bytes задают порог, после которого фоновые потоки начинают активнее сбрасывать данные на диск. vm.dirty_ratio или vm.dirty_bytes задают верхний порог, после которого процесс записи может ждать освобождения page cache.

Используйте либо ratios, либо bytes. Ratios зависят от объема RAM: на большой машине они способны создать слишком крупный burst записи. Bytes позволяют ограничить объем dirty pages более предсказуемо, но требуют учета скорости storage.

sysctl vm.dirty_background_ratio
sysctl vm.dirty_ratio
sysctl vm.dirty_background_bytes
sysctl vm.dirty_bytes
cat /proc/meminfo | grep Dirty
cat /proc/meminfo | grep Writeback

В качестве экспериментальной точки для хоста с большой RAM иногда проверяют vm.dirty_background_bytes=268435456 и vm.dirty_bytes=1073741824. Эти числа не подходят как универсальный рецепт: для медленного HDD верхний порог может создавать длинную паузу записи, а для быстрых NVMe слишком маленький порог снизит throughput. Сравнивайте await, p99 записи, fsync latency и объем dirty pages.

Тюнинг Linux-сервера для дисковой подсистемы

Диск настраивают под реальный профиль: случайное чтение, случайная запись, последовательный поток, синхронные операции или смешанная нагрузка. Планировщик и queue depth, которые полезны для HDD, могут увеличить задержки на NVMe. Синтетический тест без совпадения с профилем приложения дает ограниченную информацию.

I/O scheduler для HDD, SSD и NVMe

Проверьте доступные и текущие планировщики:

cat /sys/block/sda/queue/scheduler
cat /sys/block/nvme0n1/queue/scheduler

Название активного варианта обычно выделено квадратными скобками. На HDD часто сравнивают bfq и mq-deadline, если они доступны. Для SATA SSD и NVMe встречаются none и mq-deadline. Конкретный набор зависит от версии ядра, драйвера и устройства.

none передает запросы ниже по стеку с минимальной дополнительной обработкой. mq-deadline помогает ограничивать задержки отдельных запросов. bfq может быть полезен при конкуренции интерактивных и фоновых операций, но его поддержка и эффект зависят от устройства.

Временная смена выполняется через sysfs:

echo mq-deadline > /sys/block/sda/queue/scheduler
cat /sys/block/sda/queue/scheduler

После перезагрузки значение может вернуться. Для постоянного применения используйте механизм, принятый в вашем дистрибутиве, и проверяйте его после старта системы. Не меняйте scheduler на рабочем диске без окна наблюдения и плана возврата.

Очередь устройства, read-ahead и файловая система

Проверьте параметры очереди и read-ahead:

cat /sys/block/sda/queue/nr_requests
cat /sys/block/sda/queue/read_ahead_kb
blockdev --getra /dev/sda
findmnt -no TARGET,SOURCE,FSTYPE,OPTIONS

Большой read-ahead помогает последовательному чтению файлов и потоковой обработке. Для случайного доступа он может расходовать память и читать ненужные блоки. Увеличение nr_requests дает смысл при достаточной глубине очереди и пропускной способности storage, но способно повысить p99 latency.

Mount options выбирайте вместе с требованиями файловой системы и надежности данных. noatime может уменьшить лишние metadata writes, если приложению не нужен access time. Асинхронный discard подходит только при поддержке устройства и ядра. Отключение write barriers или изменение поведения fsync допустимо лишь при подтвержденной защите от потери питания и проверке восстановления.

Проверка через fio и iostat

Для безопасного теста используйте отдельный раздел, тестовый файл или стенд. Команда ниже создает нагрузку на уже подготовленный файл и подходит только для контролируемого окружения:

fio --name=read-test --filename=/srv/test/fio.data --rw=randread --bs=4k --size=4G --iodepth=32 --numjobs=4 --runtime=60 --time_based --direct=1

Параметры rw, bs, numjobs, iodepth и runtime должны соответствовать рабочей нагрузке. Сравнивайте random read, random write, sequential read и sequential write отдельными тестами. Для fsync используйте отдельный сценарий с пониманием риска нагрузки.

Не запускайте destructive-тест с записью на рабочий раздел: fio может перезаписать данные. Даже read-тест создает I/O и способен увеличить latency пользователей.

iostat -xz 1
pidstat -d 1
cat /sys/block/sda/queue/scheduler

Результаты fio сопоставляйте с iostat и метриками приложения. Высокий IOPS в fio не доказывает ускорение базы данных, если реальный workload использует другую глубину очереди, fsync и размер блока. Примеры настройки storage для разных профилей собраны в руководстве по глубокой настройке Linux-серверов.

Сетевые очереди и буферы Linux

Сетевой тюнинг начинают с потерь, очередей и задержки. Механическое увеличение всех net.core-буферов расходует память и маскирует проблему на NIC, виртуальном интерфейсе, провайдере или в приложении.

Очередь входящих соединений и somaxconn

Для TCP-сервиса нужно разделять backlog приложения, net.core.somaxconn и SYN backlog. Приложение передает значение backlog в listen, а ядро ограничивает его системным параметром. net.ipv4.tcp_max_syn_backlog относится к очереди полуоткрытых TCP-соединений.

sysctl net.core.somaxconn
sysctl net.ipv4.tcp_max_syn_backlog
ss -lnt
ss -s

В выводе ss -lnt поле Recv-Q у listening socket показывает текущую очередь ожидающих соединений, а Send-Q часто отражает установленный backlog. Рост очереди и отказы при всплеске подключений могут указывать на медленный accept, малое число workers или исчерпание file descriptors.

Проверяйте увеличение somaxconn только вместе с настройкой web-сервера и реальным тестом. Очередь сгладит короткий всплеск, но не исправит сервис, который обрабатывает соединения медленнее входящего потока.

TCP-буферы, retransmits и сетевые потери

Проверьте статистику интерфейса и сокетов:

ss -s
ip -s link
ethtool -S eth0
sysctl net.ipv4.tcp_rmem
sysctl net.ipv4.tcp_wmem
sysctl net.core.rmem_max
sysctl net.core.wmem_max

tcp_rmem и tcp_wmem задают минимальный, начальный и максимальный размер TCP-буфера. Автонастройка учитывает RTT, скорость канала и объем доступной памяти. Большой канал с высоким RTT требует большего окна, но на локальной сети с малым RTT увеличение буфера может не дать эффекта.

Если растут retransmits, receive errors или dropped packets, ищите причину в кабеле, NIC, драйвере, виртуальном свитче, MTU, перегрузке интерфейса и провайдере. Изменение TCP-буферов не исправляет физические потери. Не отключайте TCP timestamps и не меняйте congestion control без сравнения throughput, p95 latency и retransmits.

Когда нужен tc, а не sysctl

sysctl задает глобальные параметры сетевого стека. tc управляет очередью конкретного интерфейса, shaping и AQM.

tc qdisc show dev eth0
tc -s qdisc show dev eth0
ip -s link show dev eth0

fq подходит для многих серверных TCP-сценариев, а fq_codel помогает контролировать bufferbloat при заполнении очереди. Выбор проверяют по latency, drops, throughput и загрузке интерфейса. Для UDP, потоковой передачи и контейнерных сетей нужны отдельные тесты: одна qdisc не подходит всем протоколам и профилям.

Фоновые задачи: как освободить ресурсы в часы пик

Backup, индексация, сканирование, сжатие логов и batch-обработка часто создают предсказуемые пики. Найдите их расписание, сопоставьте с p95 сервиса и перенесите тяжелые операции в окно низкого трафика или на отдельный storage.

systemd timers и cron под контролем

systemctl list-timers --all
crontab -l
systemctl list-unit-files --type=timer
journalctl -u backup.service --since today

Для timer можно добавить случайную задержку, чтобы одинаковые задачи на группе серверов не стартовали одновременно:

[Timer]
RandomizedDelaySec=15min

Для фонового service задайте мягкий CPU- и I/O-профиль:

[Service]
Nice=10
IOSchedulingClass=idle
CPUQuota=50%
IOWeight=20
RuntimeMaxSec=2h

Ограничение длительности защищает от зависшей batch-задачи, но требует обработки частичного результата и повторного запуска. Проверьте журнал после изменения и убедитесь, что backup завершает работу до следующего окна.

Для cron оценивайте соседние задания в одном расписании. anacron может запустить пропущенную задачу после включения хоста, поэтому после простоя возможен неожиданный пик. На нескольких серверах добавляйте разнос по времени и контролируйте одновременное обращение к storage.

Логи, journald и ротация

Большой поток логов увеличивает запись на диск, количество системных вызовов и расходы на ротацию. Проверьте размер журнала и активные правила:

journalctl --disk-usage
journalctl --vacuum-size=2G
cat /etc/systemd/journald.conf
ls /etc/logrotate.d

Параметры journald задают в секции [Journal]:

[Journal]
SystemMaxUse=2G
RuntimeMaxUse=512M
RateLimitIntervalSec=30s
RateLimitBurst=1000

Ограничение размера защищает дисковое пространство, а rate limiting снижает шквал повторяющихся сообщений. Слишком жесткие значения усложнят расследование инцидента и могут скрыть важную ошибку. Сохраняйте критичные события в отдельном хранилище и согласуйте retention с требованиями эксплуатации.

Какие настройки обычно почти не помогают

Почему универсальные sysctl-рецепты дают непредсказуемый результат

Готовая конфигурация зависит от версии ядра, объема RAM, типа накопителя, сетевой карты, workload и приложения. Значение, полезное для сервера с NVMe и большим числом коротких HTTP-соединений, может ухудшить работу HDD-хранилища или базы данных с синхронной записью.

  • Массовое увеличение сетевых буферов. Оправдано при доказанном bandwidth-delay product и нехватке окна TCP. Нужны данные по RTT, throughput, retransmits и памяти.
  • Отключение swap. Допустимо для узкой системы с заранее рассчитанным запасом RAM и внешним контролем memory pressure. Нужны тесты OOM-сценария.
  • Регулярный drop_caches. Подходит для диагностического сравнения холодного и прогретого кэша. Для постоянной работы он увеличивает чтение с диска.
  • Безусловная смена I/O scheduler. Имеет смысл после сравнения на конкретном устройстве. Контролируйте await, p99 и пропускную способность.
  • Жесткое значение vm.swappiness. Выбирается по активности swap, PSI memory, latency и объему RAM, а не по шаблону.
  • Отключение защитных механизмов ядра. Не используйте такой прием ради непроверенного прироста. Сначала измерьте стоимость защиты и оцените риск.
  • Настройка без нагрузки. Параметр может выглядеть полезным в idle, но ухудшать поведение при заполнении очередей и росте конкуренции.

Проверяйте три вещи: параметр существует в текущей системе, значение фактически применилось, а целевая метрика изменилась в нужную сторону. Результат фиксируйте вместе с версией ядра, железом и сценарием нагрузки.

Когда проблема не в Linux

Остановите тюнинг ОС, если симптомы указывают на приложение, базу данных, storage или архитектуру:

  • один SQL-запрос занимает большую часть времени;
  • растет lock wait или очередь connection pool;
  • число workers не соответствует CPU и модели обработки запросов;
  • виртуальная машина получает высокий steal;
  • контейнер упирается в CPU или memory limit;
  • storage не дает нужные IOPS или throughput;
  • сеть ограничена провайдером, NIC или виртуальным свитчем.

После обновления отдельно сравните версию ядра, sysctl, конфигурацию Nginx, параметры Docker и драйверы. Для такого сценария полезен алгоритм восстановления производительности после обновлений. Возврат к старым значениям имеет смысл только после проверки совместимости и подтверждения, что именно они изменили поведение.

Итоговый чек-лист настройки производительности Linux-сервера

Минимальный набор команд для проверки

ЗадачаКомандыНа какой вопрос отвечают
CPU и очередь задачuptime, top, vmstat 1Есть ли нехватка CPU, высокий system, iowait, steal или run queue
Память и swapfree -h, vmstat 1, swapon --showСколько доступно RAM и идет ли обмен со swap
Процессыpidstat -dur 1, ps -eo pid,ni,stat,cmdКто потребляет CPU, I/O и какой nice применен
Дискiostat -xz 1, fioКаковы await, queue depth, util и реальная скорость
Сетьss -s, ss -lnt, ip -s linkЕсть ли backlog, drops, errors и retransmits
NIC и qdiscethtool -S eth0, tc -s qdisc show dev eth0Есть ли ошибки интерфейса и переполнение очереди
sysctlsysctl -n PARAMETER, sysctl --systemКаково фактическое значение и применился ли файл
systemdsystemctl show app.serviceКакие лимиты, веса и квоты получил сервис
Лимиты процессаcat /proc/1234/limitsКакие ограничения видит работающий процесс

Как автоматизировать проверенные настройки через Ansible

Храните sysctl, systemd drop-ins, limits и параметры контейнеров в системе контроля версий. Для каждой настройки фиксируйте назначение, поддерживаемые версии, исходную метрику, ожидаемый эффект и процедуру rollback.

Пример идемпотентного применения sysctl:

- name: Set swappiness
  ansible.posix.sysctl:
    name: vm.swappiness
    value: '10'
    state: present
    reload: true

- name: Set application open files limit
  ansible.builtin.copy:
    dest: /etc/systemd/system/app.service.d/limits.conf
    mode: '0644'
    content: |
      [Service]
      LimitNOFILE=65536
  notify: Restart application

В role добавьте проверку версии ОС и ядра, наличие параметра, сбор метрик до и после, проверку состояния сервиса и аварийный откат. Не автоматизируйте значение, эффект которого не подтвержден нагрузочным тестом.

Перед изменениями определите SLA и целевую метрику. Снимите baseline. Найдите bottleneck. Выберите одну группу параметров. Измените ее временно. Проверьте систему и сервис под нагрузкой. Сравните p95, p99, throughput и error rate. Закрепите результат в конфигурации. Добавьте мониторинг. Перезагрузите тестовый узел и сверяйте значения после старта.

Для группы серверов проверьте расхождения конфигураций и версий. Один и тот же Ansible-рецепт должен учитывать тип диска, объем RAM, роль узла и ограничения контейнерного runtime. Такой порядок снижает риск получить одинаковую настройку на системах с разными узкими местами.

Поделиться:
Сохранить гайд? В закладки браузера