open atlas
↑ К треку
Linux: операционная система LIN · 12 · 01

Параметры ядра через sysctl

Ядро открывает тысячи параметров через /proc/sys. sysctl -w устанавливает их в рантайме (теряются при перезагрузке); /etc/sysctl.d/*.conf делает их постоянными. Ключевые параметры: vm.swappiness, net.ipv4.ip_forward (нужен для маршрутизации и контейнеров), fs.file-max.

LIN Middle ◷ 20 min
Уровень
ОсновыJuniorMiddleSenior

Разработчик выкатывает сервис, открывающий тысячи постоянных соединений. В 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.

1

Дерево /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-страницу.

2

Изменения в рантайме через 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 во время инцидента, фиксирует в тикете — и изменение исчезает при следующей плановой перезагрузке. Для постоянства нужен отдельный шаг.

3

Постоянные настройки через /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-). Параметр из более позднего файла всегда перекрывает параметр из более раннего.

4

Три параметра, которые должен знать каждый 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.

5

Загрузка и проверка полной конфигурации. После любого изменения в /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-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 4 завершено

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.