Параметры ядра через sysctl
Ядро открывает тысячи параметров через /proc/sys. sysctl -w устанавливает их в рантайме (теряются при перезагрузке); /etc/sysctl.d/*.conf делает их постоянными. Ключевые параметры: vm.swappiness, net.ipv4.ip_forward (нужен для маршрутизации и контейнеров), fs.file-max.
Разработчик выкатывает сервис, открывающий тысячи постоянных соединений. В 02:00 хост начинает отказывать в новых подключениях. Исправление — одна строка: sysctl -w net.core.somaxconn=4096, — но найти её можно только зная, что ядро открывает свои настраиваемые параметры через виртуальную файловую систему в /proc/sys, и что каждая директория в этом дереве соответствует параметру с именем через точку. Тот же механизм управляет тем, пересылает ли хост пакеты (критично для контейнеров и VPN), насколько агрессивно ядро выгружает память на диск и максимальным числом открытых файловых дескрипторов. Перекомпилировать ядро для этого не нужно — достаточно записать в нужный файл или вызвать sysctl. Главное — понимать: изменение в рантайме исчезнет при следующей перезагрузке, если не сделать его постоянным.
После этого урока ты сможешь перечислять и читать параметры ядра через sysctl -a, устанавливать их в рантайме командой sysctl -w, делать их постоянными через /etc/sysctl.d/*.conf и sysctl --system, а также объяснять назначение vm.swappiness, net.ipv4.ip_forward и fs.file-max.
Дерево /proc/sys: как ядро открывает параметры. Каждый параметр, видимый через sysctl, существует в виде файла в /proc/sys. Иерархия директорий напрямую соответствует имени с точками: net.ipv4.ip_forward — это /proc/sys/net/ipv4/ip_forward. Файлы можно читать и записывать напрямую через cat и echo, но sysctl — правильный инструмент: он проверяет значения и форматирует ошибки.
# Список всех параметров с текущими значениями (несколько тысяч строк):
sysctl -a
# Фильтрация по подсистеме:
sysctl -a | grep vm.
# Чтение одного параметра:
sysctl vm.swappiness
# vm.swappiness = 60
# Чтение напрямую из /proc/sys (то же значение, менее удобно):
cat /proc/sys/vm/swappiness
# 60
# Чтение сетевого параметра:
cat /proc/sys/net/ipv4/ip_forward
# 0Большинство параметров — целые числа. Некоторые принимают разделённые запятыми списки. Значение 0 обычно означает «выключено», 1 — «включено», но перед изменением чего-либо в продакшне всегда читай man-страницу.
Изменения в рантайме через sysctl -w. Изменение в рантайме вступает в силу немедленно и действует до следующей перезагрузки. Именно это нужно при разборе инцидентов — можно настраивать, наблюдать, и если настройка ухудшила ситуацию, перезагрузить хост для возврата к прежнему состоянию.
# Включить IP-форвардинг (нужен для маршрутизации и контейнеров):
sudo sysctl -w net.ipv4.ip_forward=1
# net.ipv4.ip_forward = 1
# Проверить:
sysctl net.ipv4.ip_forward
# net.ipv4.ip_forward = 1
# Снизить swappiness (ядро будет хранить больше данных в RAM):
sudo sysctl -w vm.swappiness=10
# vm.swappiness = 10
# Поднять системный лимит на открытые файлы:
sudo sysctl -w fs.file-max=2097152
# fs.file-max = 2097152
# ЛОВУШКА: при перезагрузке это значение теряется
# После следующей перезагрузки:
sysctl vm.swappiness
# vm.swappiness = 60 ← вернулось к умолчаниюЛовушка — самая частая операционная ошибка. Инженер применяет sysctl -w во время инцидента, фиксирует в тикете — и изменение исчезает при следующей плановой перезагрузке. Для постоянства нужен отдельный шаг.
Постоянные настройки через /etc/sysctl.d. Директории конфигурации sysctl читаются ядром при загрузке, а командой sysctl --system — в любое время. Создавай .conf-файл в /etc/sysctl.d/ — не редактируй /etc/sysctl.conf напрямую (обновления пакетов могут его сбросить).
# Создать файл настроек для конкретного проекта:
sudo tee /etc/sysctl.d/99-myapp.conf << 'EOF'
# Разрешить хосту пересылать пакеты (нужно для Docker, WireGuard и т.д.)
net.ipv4.ip_forward = 1
# Низкий swappiness для сервиса, критичного к задержке
vm.swappiness = 10
# Системный лимит на открытые файлы для сервиса с большим числом соединений
fs.file-max = 2097152
EOF
# Применить ВСЕ файлы /etc/sysctl.d/*.conf без перезагрузки:
sudo sysctl --system
# Applying /etc/sysctl.d/10-console-messages.conf ...
# Applying /etc/sysctl.d/99-myapp.conf ...
# net.ipv4.ip_forward = 1
# vm.swappiness = 10
# fs.file-max = 2097152
# Убедиться, что конкретный параметр теперь постоянный:
cat /etc/sysctl.d/99-myapp.conf | grep ip_forward
# net.ipv4.ip_forward = 1Файлы обрабатываются в лексикографическом порядке. Префикс 99- гарантирует, что твой файл применяется последним и перекрывает умолчания дистрибутива (которые используют префиксы 10- или 60-). Параметр из более позднего файла всегда перекрывает параметр из более раннего.
Три параметра, которые должен знать каждый fullstack-инженер.
# 1. vm.swappiness (по умолчанию: 60)
# Управляет агрессивностью выгрузки страниц на диск.
# 0 = своп только при полном исчерпании RAM
# 60 = умолчание, подходит для десктопов
# 10 = серверы, критичные к задержке (базы данных, app-серверы)
# 100 = максимальная агрессивность свопа (редко нужно)
sysctl vm.swappiness
# 2. net.ipv4.ip_forward (по умолчанию: 0)
# При значении 0 ядро СБРАСЫВАЕТ пакеты, адресованные другому хосту.
# Это ломает: Docker bridge networking, WireGuard VPN, любой NAT.
# Без ip_forward=1 контейнер в другой подсети не может выйти в интернет.
# Docker устанавливает это при старте, но без sysctl.d значение сбрасывается.
sysctl net.ipv4.ip_forward
# 3. fs.file-max (по умолчанию: varies, often ~100000)
# Системный лимит на открытые файловые дескрипторы (для всех процессов суммарно).
# Каждый сетевой сокет, открытый файл и пайп стоит один дескриптор.
# Нагруженный веб-сервер или база данных легко упирается в этот лимит.
# Примечание: на уровне процесса лимит управляется через ulimit / /etc/security/limits.conf
sysctl fs.file-maxПараметр ip_forward чаще всего создаёт проблемы в контейнерном или VPN-контексте: контейнеры стартуют, но не имеют интернет-доступа, потому что хост был перезагружен без постоянного sysctl. Всегда делай ip_forward постоянным через sysctl.d.
Загрузка и проверка полной конфигурации. После любого изменения в /etc/sysctl.d/ используй sysctl --system для применения без перезагрузки. После перезагрузки те же файлы применяются автоматически через systemd-sysctl.service.
# Посмотреть, какие файлы будет обрабатывать sysctl --system и в каком порядке:
ls -la /etc/sysctl.d/ /usr/lib/sysctl.d/ /run/sysctl.d/ 2>/dev/null
# Применить все файлы и увидеть, что изменилось:
sudo sysctl --system
# Подтвердить, что конкретное значение применено из твоего файла:
sysctl net.ipv4.ip_forward
# net.ipv4.ip_forward = 1
# Проверить юнит systemd, применяющий sysctl при загрузке:
systemctl status systemd-sysctl.service
# Loaded: loaded (/lib/systemd/system/systemd-sysctl.service; static)
# Active: inactive (dead)
# (inactive — норма: запускается один раз при загрузке и завершается)
# Если нужно применить только один новый файл (не все):
sudo sysctl -p /etc/sysctl.d/99-myapp.conf
# net.ipv4.ip_forward = 1
# vm.swappiness = 10
# fs.file-max = 2097152Сценарий: контейнерный хост постоянно теряет ip_forward после перезагрузок.
При каждой перезагрузке хоста контейнеры теряют интернет-доступ на несколько минут, и дежурный инженер вручную запускает sysctl -w net.ipv4.ip_forward=1 до срабатывания алертов. Проблема повторилась шесть раз.
# Шаг 1: подтвердить проблему
sysctl net.ipv4.ip_forward
# net.ipv4.ip_forward = 0 ← Docker ещё не стартовал или проиграл гонку
# Шаг 2: проверить, есть ли уже файл sysctl.d для этого:
grep -r ip_forward /etc/sysctl.d/ /etc/sysctl.conf 2>/dev/null
# (нет вывода — ничто это не сохраняет)
# Шаг 3: Docker устанавливает ip_forward при собственном старте, но конкурирует
# с другими ранними сервисами. Проверить текущее состояние:
cat /proc/sys/net/ipv4/ip_forward
# 0 ← Docker ещё не стартовал на этой стадии загрузки
# Шаг 4: создать постоянное переопределение:
sudo tee /etc/sysctl.d/99-docker-forwarding.conf << 'EOF'
# Нужно для сетевого взаимодействия Docker и интернет-доступа контейнеров
net.ipv4.ip_forward = 1
EOF
# Шаг 5: применить сейчас (не ждать перезагрузки):
sudo sysctl --system | grep ip_forward
# net.ipv4.ip_forward = 1
# Шаг 6: убедиться, что юнит, применяющий настройки, всегда включён:
systemctl is-enabled systemd-sysctl.service
# static ← всегда запускается, отключить нельзя
# Шаг 7: проверить после перезагрузки:
sysctl net.ipv4.ip_forward
# net.ipv4.ip_forward = 1Первопричина: Docker включает ip_forward при старте, но sysctl существует только в рамках жизни демона. Отсутствие записи в /etc/sysctl.d/ означает, что каждый холодный старт начинается с отключённым форвардингом. Исправление: один conf-файл, один вызов sysctl --system — больше не трогать.
▸Частая ошибка
Редактировать /etc/sysctl.conf напрямую. Файл /etc/sysctl.conf — это устаревшее расположение, которое обрабатывается первым. Однако обновления пакетов (ядро, procps) могут его перезаписать или сбросить. Правильный паттерн — создавать файл в /etc/sysctl.d/ с высоким числовым префиксом (например, 99-), чтобы твои настройки применялись последними и побеждали. Думай о нём так же, как о /etc/cron.d/ вместо редактирования root-crontab — паттерн drop-in директории переживает обновления и поддаётся аудиту.
▸Почему это работает
На macOS нет /proc/sys. macOS использует ядро, производное от BSD, с собственным интерфейсом sysctl: sysctl -a работает, но пространства имён параметров совершенно другие (kern.maxfiles вместо fs.file-max, net.inet.ip.forwarding вместо net.ipv4.ip_forward). Виртуальной файловой системы /proc/sys нет. При локальной разработке на macOS параметры, которые ты настраиваешь на Mac, не переносятся на Linux. Docker Desktop на macOS запускает полноценную Linux VM, и значения sysctl нужно устанавливать внутри этой VM, а не на хосте Mac.
Ты запускаешь `sudo sysctl -w net.ipv4.ip_forward=1` на продакшн-хосте и подтверждаешь работу. На следующий день после планового перезапуска сеть контейнеров снова не работает. Какое правильное исправление?
Ядро открывает тысячи параметров рантайма через виртуальную файловую систему /proc/sys, каждый доступен по имени с точками через sysctl. Читай с помощью sysctl -a (все) или sysctl <name> (один). Устанавливай в рантайме через sysctl -w name=value — вступает в силу немедленно, теряется при перезагрузке. Сохраняй в .conf-файле в /etc/sysctl.d/ (используй префикс 99- для победы над умолчаниями), затем запускай sudo sysctl --system для применения без перезагрузки; systemd-sysctl.service применяет те же файлы автоматически при каждой загрузке. Три параметра, которые должен знать каждый fullstack-инженер: vm.swappiness (агрессивность свопа; снижай для сервисов, критичных к задержке), net.ipv4.ip_forward (должен быть 1 для контейнеров и VPN; забытое постоянство — самая частая ошибка в сети контейнеров) и fs.file-max (системный лимит дескрипторов для сервисов с большим числом соединений).
Практика
Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.