GitHub применил eBPF для поиска циклических зависимостей

GitHub рассказал, как использует технологию eBPF в Linux для обнаружения и предотвращения циклических зависимостей в системе деплоя собственного продукта.

Вся кодовая база GitHub хранится на github.com, а компания разворачивает изменения с помощью тех же инструментов, что и клиенты. Это создаёт риск: при недоступности github.com инженеры не могут получить исходный код для деплоя исправлений. Для снижения этого риска GitHub поддерживает зеркала репозиториев и готовые артефакты для отката, однако часть зависимостей в процессах деплоя раньше оставалась незамеченной.

В инцидентах типа отказа MySQL может потребоваться срочно применить конфигурационные изменения через скрипты деплоя на состояние узлах. Если такой скрипт в процессе выполнения запрашивает данные или бинарные файлы с github.com или внутренних сервисов, которые в этот момент недоступны, возникает новая циклическая зависимость и восстановление затягивается.

Ранее ответственность за поиск таких зависимостей лежала на командах, у которых есть stateful-хосты. По факту многие проблемы выявлялись только во время инцидентов. Простое решение вроде полного блокирования доступа к github.com на продакшн-хостах неприемлемо: эти машины продолжают обслуживать клиентов даже во время rolling-деплоев и рестартов.

GitHub начал использовать eBPF, который позволяет загружать пользовательские программы в ядро Linux и подключаться к базовым механизмам системы, включая сеть. Команда выбрала тип программы BPF_PROG_TYPE_CGROUP_SKB, который даёт возможность контролировать сетевой исходящий трафик для конкретной cGroup.

cGroup в Linux задаёт ограничения ресурсов и изоляцию для групп процессов. Команда GitHub создала отдельную cGroup, поместила в неё только скрипты деплоя и настроила eBPF-программы так, чтобы ограничивать сетевые подключения именно для этих процессов, не затрагивая остальную нагрузку.

Для прототипа использовалась библиотека cilium/ebpf и ebpf-go — реализация на Go для чтения, модификации и загрузки eBPF-программ в ядро и привязки их к нужным хукам. Это упростило сборку: достаточно выполнить обычный go build, а генерация кода для eBPF и структуры bpfObjects происходит автоматически.

Однако программа CGROUP_SKB работает с IP-адресами, а поддерживать актуальный список IP для блокировки при масштабе GitHub оказалось сложно. Поэтому GitHub дополнил подход DNS-фильтрацией также на базе eBPF, используя тип программы BPF_PROG_TYPE_CGROUP_SOCK_ADDR, перехватывающий системные вызовы создания сокетов и изменения адреса назначения.

DNS-запросы от скриптов деплоя перенаправляются на локальный DNS-прокси в пользовательском пространстве. Этот прокси сверяет запрашиваемые домены со списком блокировки и через eBPF Maps передаёт в CGROUP_SKB-программу решение — разрешить или запретить соединение.

Чтобы упростить отладку и устранение проблем, команда добавила возможность связывать заблокированные DNS-запросы с конкретными процессами и командами. В программе CGROUP_SKB используется структура skb_buff: из неё извлекается идентификатор DNS-транзакции и PID процесса. Эти данные попадают в eBPF Map с соответствием «ID транзакции – PID».

Поскольку все DNS-запросы проходят через пользовательский DNS-прокси, он считывает идентификатор транзакции, находит домен, а затем по eBPF Map определяет, какой процесс сделал запрос. Чтение /proc/{PID}/cmdline позволяет получить полную команду, после чего в лог записывается строка с детальной информацией для команды-разработчика.

Новый процесс обнаружения циклических зависимостей был развёрнут в продакшене в течение шести месяцев и сейчас работает в GitHub. Если команда случайно добавляет проблемную зависимость или внешний бинарный инструмент вводит новую, система автоматически фиксирует факт обращения и сообщает об этом разработчикам.

По оценке GitHub, это привело к более стабильной работе платформы и более быстрому восстановлению после инцидентов, поскольку скрытые циклические зависимости в сценариях деплоя выявляются заранее и устраняются без влияния на клиентов.

GitHub отмечает, что eBPF открывает дополнительные сценарии наблюдаемости и контроля, и компания планирует развивать инструмент по мере обнаружения новых типов проблем. В качестве отправной точки для инженеров GitHub рекомендует примеры в репозитории cilium/ebpf, документацию на docs.ebpf.io, а также готовые open source-инструменты на базе eBPF, такие как bpftrace для глубокой трассировки и ptcpdump для получения TCP-дампов с учётом контейнерных метаданных.

Источник: инженерный блог GitHub.

Читать новости ИИ и технологий в Telegram.


Оцените статью
Gimal-Ai