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.




















