Operating Systems
«У нас Kubernetes, ядро — это магия» — позиция, которая работает, пока инцидент не зазвучит как «под жив, но не отвечает», «контейнер убит по памяти при свободной оперативке», «странный таймаут TCP, который не воспроизводится в staging». В этот момент инженер без знания операционной системы становится заложником симптомов. Я регулярно вижу команды, которые держатся на пятерых старших с хорошим Linux-бэкграундом, и эти пятеро превращаются в единственную точку отказа для любого «странного» инцидента. Операционная система — это не хобби по чтению исходников ядра, а слой между процессом и железом, который надо понимать, чтобы отлаживать прод. Пространства имён и cgroups — то, на чём стоят Docker и k8s. Системные вызовы — то, что процесс на самом деле просит у ядра. Страничный кеш — причина, по которой free почти ничего не говорит о памяти. Сетевой стек — место, где между приложением и сетью теряется пакет. eBPF за прошлое десятилетие превратился из нишевой технологии в обязательный слой наблюдаемости, но без понимания ОС он остаётся фокусом, а с ним — рабочим инструментом.
Граница: Networking — про сетевой стек как отдельный домен; здесь — про ОС целиком, включая сетевой стек ядра как частный случай. Performance & Profiling — как мерить; здесь — что мерить и почему именно так. Shell & CLI Craft — интерфейс к системе через терминал; здесь — то, что лежит под этим интерфейсом.
Что должен уметь
Заголовок раздела «Что должен уметь»Главный навык на уровне L4 — читать /proc как настоящий источник истины о процессе: /proc/[pid]/status, /proc/[pid]/maps, /proc/[pid]/limits, /proc/[pid]/fd/. По моим наблюдениям, в отладке ситуации «процесс жив, но с ним что-то не так» вся разница между инженерами — знает ли человек, что лежит в /proc, или пользуется только top и ps. Под стрессом инцидента первый сразу лезет в /proc, второй стучится в интерфейс кластера. Один день на man 5 proc заметно меняет качество всех будущих дежурств.
L3
- Понимает процессы и потоки,
forkиexec; разбирается в кодах возврата и сигналах (SIGKILLпротивSIGTERM); читает выводps,top,htop,pgrep,kill. - Знает базовые вещи про файловые системы: inode, жёсткая ссылка против символьной, точки монтирования, права (
chmod,chown); читаетdf,du,lsof.
L4
- Различает виртуальную память, резидентную и рабочее множество; знает, что показывают колонки
VIRT,RESиSHRвtopи почемуfreeсчитает «занято» не так, как подсказывает интуиция. Понимает страничный кеш и то, что высокое «занято» — обычно норма. - Пользуется
straceдля разбора системных вызовов:strace -f -e trace=network nginx,strace -p PID. Понимает, во что это обходится по производительности, и в проде применяет осторожно. - Понимает пространства имён и cgroups: контейнер Docker или k8s — это процесс со своими пространствами монтирования, сети и PID плюс ограничения cgroup, а не виртуальная машина. Знает, как читать
/proc/[pid]/cgroupи/sys/fs/cgroup/. - Различает сигналы:
SIGTERM(мягкое завершение),SIGKILL(убийство ядром),SIGSEGV(ошибка в коде); знает, что OOM-killer выбирает жертву не случайно, и умеет читатьdmesgпосле инцидента.
L5
- Применяет eBPF и bpftrace в проде:
execsnoop,tcplife,runqlat,biolatency. Понимает, что это не магия, а скомпилированный байт-код в песочнице ядра. - Знает основы планировщика: CFS, очередь готовых процессов, задержка планирования, привязка к NUMA, эффекты гипертрединга.
- Отлаживает контейнеры без
docker exec:nsenterв нужное пространство имён, чтение/proc/[pid]/...целевого процесса, подход к зависшему контейнеру средствами ядра.
L6+
- Настраивает систему под нагрузку: базовый набор
sysctl(net.core.somaxconn,vm.swappiness,fs.file-max), обоснование каждого параметра, ревизия после обновления ядра. - Реагирует на новые уязвимости и возможности ядра со знанием контекста: Spectre и Meltdown, Dirty Pipe (CVE-2022-0847), развитие io_uring, модель безопасности eBPF.
Материалы
Заголовок раздела «Материалы»- Brendan Gregg — Systems Performance: Enterprise and the Cloud (Addison-Wesley, 2-е изд., 2020). Не только про производительность, а целая картина того, как устроен Linux. Главы с третьей по седьмую — наблюдаемая сторона системы. Если выбирать одну книгу для SRE — эту.
- Brendan Gregg — BPF Performance Tools (Addison-Wesley, 2019). eBPF как новый класс наблюдаемости плюс готовые инструменты (bcc-tools, bpftrace), которые работают в проде.
- W. Richard Stevens, Stephen A. Rago — Advanced Programming in the UNIX Environment (Addison-Wesley, 3-е изд., 2013). Канон по слою системных вызовов, сигналам и межпроцессному взаимодействию. Читается не подряд, а главами по теме.
- Robert Love — Linux Kernel Development (Addison-Wesley, 3-е изд., 2010). Введение в архитектуру ядра: планировщик, управление памятью, виртуальная файловая система. Не для того, чтобы писать код ядра, а чтобы понимать, что происходит там, внутри.
- Liz Rice — Container Security (O’Reilly, 2020). Несмотря на название — лучшее краткое введение в пространства имён, cgroups, capabilities и seccomp с точки зрения «как вообще устроен контейнер». Отдельно полезны главы о том, чем контейнер отличается от виртуальной машины.
Статьи и доклады
Заголовок раздела «Статьи и доклады»- Brendan Gregg — Linux Performance. Живая страница, которую он обновляет годами: инструменты, методики, ссылки в одном месте. Главный публичный кейс — см. ниже.
- Julia Evans — Wizard Zines. Серия коротких зинов (Bite Size Linux, Bite Size Networking, How Containers Work) — лучший вход во внутренности Linux для тех, кто отскакивает от тысячестраничных книг. По моим наблюдениям, командная беглость в Linux чаще всего растёт именно через её материалы.
- Liz Rice — Why Container Security Matters (KubeCon). Полчаса: пространства имён, cgroups и capabilities в живой демонстрации с
unshareиnsenter. - Michael Kerrisk — The Linux Programming Interface. Если Stevens и Rago кажутся слишком плотными, это современная альтернатива того же охвата. Частично доступна онлайн.
- Мой разбор — Что происходит, когда ты открываешь сайт (jtprog.ru, июль 2026). К этой компетенции относится серверная половина текста: аппаратное прерывание и DMA, обработчик прерывания и переход в ядро, NAPI и softirq вместо прерывания на каждый пакет, распределение по ядрам через RPS и RFS, путь кадра вверх по стеку до сокета. Собирал её потому, что, по моим наблюдениям, сетевой стек ядра объясняют либо на уровне
tcpdump, либо на уровне исходников, а середины почти нет.
Инструменты
Заголовок раздела «Инструменты»/proc,/sys— главные источники истины. Каждый живой процесс отдаёт наружу огромную поверхность через/proc/[pid]/. По моим наблюдениям, беглость в системе отличает не количество прочитанных книг, а привычка начинать отладку сcat /proc/....strace/ltrace— трассировка системных и библиотечных вызовов.straceдорого обходится под нагрузкой, поэтому в проде осторожно, а в staging это обязательный инструмент ответа на вопрос «что процесс делает на самом деле».perf— профилирование CPU, аппаратные счётчики, события планировщика. Часть ядра, в современных дистрибутивах ставить отдельно почти не приходится.- bcc-tools / bpftrace — инструменты поверх eBPF:
execsnoop,opensnoop,biolatency,tcplife,runqlat. Наблюдение без изменений и без перезапуска сервиса. nsenter— войти в пространство имён нужного процесса.nsenter -t [pid] -n ss -tnlpпокажет слушающие сокеты внутри контейнера безdocker exec.dmesg/journalctl— кольцевой буфер ядра и логи systemd. Сообщения OOM-killer, паники ядра, проблемы драйверов живут здесь.sysstat(sar,iostat,mpstat,vmstat) — классика системного мониторинга. Старые, зато на них держится базовая картина нормы.- Анти-инструмент: «для отладки контейнера всегда
docker exec». Он запускает в контейнере новый shell, и контекст у этого shell отличается от контекста целевого процесса;nsenterпоказывает то, что видит сам процесс.
Best practices
Заголовок раздела «Best practices»Главный публичный кейс — работа Brendan Gregg над производительностью Linux в Netflix и его публикации. Он на десятилетие сделал eBPF, perf и flame graphs стандартом индустрии — не продуктом, а показом: серия постов, где каждый разбор начинается с реального продового случая, идёт через профиль и заканчивается находкой и исправлением. Канонический вход — «Linux Performance Analysis in 60,000 Milliseconds» в блоге Netflix: десяток команд, которые надо выполнить в первую минуту на незнакомой машине. Я регулярно вижу команды, которые знают слова «eBPF» и «flame graph», но не применяют их, потому что ни разу не видели, как это делают руками. Час на эту статью окупается на каждом «странном» инциденте.
Три вещи, которые я повторяю чаще всего. Операционная система — слой между процессом и железом, а не расходный материал: позиция «у нас всё в k8s, ОС не важна» работает до первого нетривиального инцидента, потому что ядро на узле одно на все поды и настройка одного узла прилетает соседям. При «странном» инциденте первыми открываются /proc и dmesg — до дашбордов, до Grafana, до чужих графиков; cat /proc/[pid]/... и dmesg | tail -50 часто показывают причину сразу. И ни один sysctl не меняется «потому что так в гайде»: без записанного обоснования в коммите или runbook через год никто не вспомнит, что и зачем.
Контейнер — не виртуальная машина, и от этого зависит вся отладка. Когда его считают облегчённой виртуалкой, от него ждут изоляции того же уровня и удивляются, что один контейнер выжирает ресурсы ядра на всём хосте: файловые дескрипторы, таблицу conntrack, эфемерные порты. Здоровая модель другая: процесс в пространствах имён и cgroups, ядро общее, ресурсы делятся в неочевидных местах. Инциденты вида «под вылетел, рестарт не помог» я вижу регулярно, и почти всегда причина одна — исчерпан ресурс хоста, так что любой новый под на этом узле попадёт в ту же яму.
OOM-killer выбирает жертву по oom_score, а не по фактическому потреблению. Отсюда классическое недоумение: «у нас 32 гигабайта, а контейнер убили на двух, ядро сошло с ума». Ядро не сходило с ума. В cgroup стоял лимит в два гигабайта, ядро его и соблюдало, а подробности лежат в dmesg — там же видно, что выбор жертвы детерминирован и читается через /proc/[pid]/oom_score. Команды, которые после такого убийства не смотрят dmesg, обычно и остаются в убеждении, что это лотерея.
eBPF — не магия, а скомпилированный байт-код в песочнице ядра. Впечатление «bpftrace что-то показывает, работает быстро, значит колдовство» держится ровно до момента, когда разбираешь цепочку: скрипт компилируется в байт-код, верификатор проверяет его на безопасность, JIT собирает в нативный код, и всё это исполняется в контексте ядра. Понимание этой цепочки снимает главный страх — «вдруг eBPF положит узел». В зрелых инструментах вроде bcc и bpftrace верификатор гарантирует ограниченные циклы, отсутствие неограниченной памяти и возврат за конечное время.
Настройка ядра без базовых замеров — риск без выгоды. Пример из самых частых. Я регулярно вижу, как в прод переносят тридцать строк sysctl, скопированных из поста на форуме 2014 года. Часть значений давно стала умолчанием ядра, часть противоречит сегодняшней нагрузке, часть чинит проблемы, которых уже нет. Рабочий порядок скучный: изменение обосновано профилем или наблюдаемой метрикой, проверено в staging, положено в коммит с объяснением и пересмотрено после очередного обновления ядра. Без этого sysctl превращается в карго-культ.
Чтение proc(5) окупается годами. Один вечер. man 5 proc описывает формат каждого файла в /proc, а их на процесс больше двухсот, и большинство инженеров знает от силы пяток. Один вечер — и в отладке появляется арсенал: /proc/[pid]/status с состоянием, потоками и масками сигналов, /proc/[pid]/maps с картой памяти и загруженными библиотеками, /proc/[pid]/io с прочитанными и записанными байтами, /proc/[pid]/wchan с точкой, где процесс уснул в ядре. По моим наблюдениям, беглость в /proc и отличает того, кто в инциденте идёт к причине, от того, кто ходит по дашбордам.
Связанные листья
Заголовок раздела «Связанные листья»- Networking — сетевой стек ядра — частный случай внутренностей системы; TCP, сокеты, netfilter и пространства имён — общая зона.
- Performance & Profiling —
perfи eBPF работают на уровне системы; глубокая работа с производительностью без знания ОС невозможна. - Shell & CLI Craft — shell — основной интерфейс к системе; беглость в одном требует беглости в другом.
- Programming Languages — среда исполнения языка стоит на ОС; паузы сборщика мусора, поведение планировщика, характер системных вызовов — это стык.
- Capacity Planning — индикаторы насыщения (длина очереди готовых процессов, ожидание диска, отказы страниц) берутся на уровне системы.
- Resilience Patterns — проверки здоровья на уровне системы: слушает ли порт, жив ли процесс, не кончились ли файловые дескрипторы.
- Containerization & Orchestration — контейнер — процесс в пространствах имён и cgroups; отладка пода и есть отладка системы.
- Incident Response — нетривиальный инцидент часто упирается в системный уровень; первая минута —
dmesg,/proc,nsenter.
Открытые вопросы
Заголовок раздела «Открытые вопросы»- Containerization & Orchestration — вынесено в отдельный лист; знание ОС остаётся предусловием для отладки подов.
- Service Mesh — тоже отдельный лист; прокси рядом с сервисом общается с сетевым стеком через iptables, так что системная отладка применима и там.
- macOS и Windows как среда разработки — большая часть знаний переносится на прод в Linux линейно, но часть тонкостей (семантика файловой системы, обработка сигналов) отличается.
- eBPF в проде (TBD) — как писать свои программы, а не только пользоваться готовыми: ограничения верификатора, совместимость с версиями ядра.
- Настройка узлов k8s (TBD) — типовой набор
sysctlдля рабочих узлов с обоснованием, а не в режиме карго-культа.
Отдельно у меня нет ответа на вопрос про минимальную глубину знаний об ОС для дежурства в кластере, который держит провайдер: EKS, GKE, AKS. Где-то там проходит разумный пол, ниже которого дежурный превращается в передатчика симптомов, но нащупать его я пока не смог. Если у вас этот пол сформулирован, расскажите через PR.