Увеличение файла подкачки в GitHub Actions

Увеличение файла подкачки в GitHub Actions может потребоваться для ресурсоемких задач, когда доступных 7Гб на раннерах не хватает. Например это может быть сборка Java-приложений. Если с оптимизацией использования ресурсов возникли проблемы, а переход на платную подписку не входит в ваши планы, то эта статья именно для вас.

Увеличение файла подкачки в GitHub Actions

Если лень читать, то вот быстрое решение, которое ничуть не отличается от логики расширения файла подкачки на любых других серверах под управлением Ubuntu 1:

Примечание: обратите внимание на путь до файла подкачки – на раннерах GitHub Actions это /mnt/swapfile.

Этот скрипт будет работать на стандартных раннерах без каких-либо оболочек, например Docker. А теперь давайте разберем сценарий сложнее.

Задача

Нам нужно запустить пайплайн внутри контейнера Docker. Это стандартный сценарий, который к тому же полностью поддерживается со стороны GitHub Actions. Делается это следующим образом:

Примечание: подробнее об использовании контейнеров в GitHub Actions читайте в официальной документации, например в статье Running jobs in a container или Workflow syntax for GitHub Actions.

Динамика использования оперативной памяти на раннере GitHub выглядит следующим образом:

Примечание: график выше действительно отображает метрики от node_exporter, взятые со штатного раннера GitHub. Если вам интересно как настроить их мониторинг, то в скором времени будет об этом статья.

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

Проблема

Все задачи пайплайна выполняются внутри контейнера, а файл подкачки находится на хостовой машине. Запустить команды на хосте в контексте отдельных шагов не получится, а значит надо искать обходной вариант.

Каким образом можно изменить настройки хоста изнутри контейнера и вообще возможно ли это? Да, но нужно подготовиться.

Решение

Сначала нам потребуется запускать контейнеры на хостовой машине. Делать это придется все также изнутри основного контейнера. Это не проблема, поскольку в GitHub Actions docker.sock по умолчанию пробрасывается в запущенные контейнеры. Все, что нам нужно, это установить докер-демон внутри контейнера. Таким образом мы реализуем один из двух вариантов концепции Docker in Docker.

Примечание: подробнее о нюансах запуска Docker внутри Docker читайте в статье How To Run Docker in Docker.

Зачем это нужно? Запустив на хосте контейнер с повышенными привилегиями и сменив корневой каталог 2, мы можем выполнять изнутри него команды для перенастройки файла подкачки на хостовой машине.

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

А теперь посмотрим как это будет выглядеть на практике.

Реализация

С помощью системных механизмов (namespaces, cgroups) докер добивается изоляции контейнерных процессов. Тем не менее есть возможность пробросить хостовые неймспейсы внутрь контейнера. Попробуем запустить простой контейнер с максимально возможными правами и привилегиями:

Если запустите docker ps, то увидите контейнер с именем busybox. Далее нужно запустить команды в контексте хостовой машины, для этого изменим корневой каталог:

Примечание: в каталог /host внутрь контейнера мы ранее примонтировали корень хостовой файловой системы (см. –volume /:/host ).

Теперь остается перезапустить билд с новой версией пайплайна и посмотреть что мониторинг покажет на этот раз:

Как видно на скриншоте, файл подкачки перешагнул доступный по умолчанию максимум в 4ГБ и дошел вплоть до 5,5Гб, при этом билд завершился без ошибок.

Пользуйтесь лайфхаком. Ну а если вдруг с чем-то не справитесь, обращайтесь. А у меня на этом все!

Яндекс.Метрика