Чистка GitLab Registry для Kubernetes админов

В наше время в каждом доме по кластеру kubernetes, выкатка приложений в кластер осуществляется по тегу. Образ выкатываемого приложения отправляется тегом в репозиторий проекта Registry GitLab, которое постепенно распухает до невероятных размеров.

Существующие решения

  • Решение из коробки

    Идем в проект Settings → CI/CD → CleanUp policy for tags. Тут можно создать некий шаблон, который под капотом использует Bulk Delete и, в принципе, все не плохо ЕСЛИ у вас куча тегов ссылающихся на один и тот же образ. Но если у вас идет активная разработка и каждый второй тег - это новый образ, этот способ не поможет.

  • Решения от community

    1. "Сжечь и перевыкатить"

    2. Ручная либо полу ручная сортировка образов и тегов.

Данные решения мне не понравились, а значит:

Подготовка

Любая разумная деятельность должна начинаться со сбора информации. Поэтому, первым делом, сканим или проводим опрос всех, до кого можем дотянуться - не хранит ли кто-нибудь в проектах образы, которые не работают в постоянном режиме (образы от Job, CronJob или просто склад полезных образов). Внимательно записываем в книжечку проекты, которые лучше не трогать.

Настраиваем сборщик мусора GitLab

Теги в GitLab registry ссылаются на образы, а образы используют слои. Если почистить только теги, сильного прироста свободного места мы не получим.

Поэтому рекомендую вставить в расписание сron команду для удаления образов, не имеющих тегов

sudo gitlab-ctl registry-garbage-collect

Можно освободить еще больше места удалив не используемые слои образов

sudo gitlab-ctl registry-garbage-collect -m

ВНИМАНИЕ: Во время чистки мусора останавливается служба registry, как следствие пользователи не смогут делать push, pull.

Опытные джедаи могут сократить время простоя путем временного перевода registry в режим readonly.

sudo vi /etc/gitlab/gitlab.rb
registry['storage'] = {
    'maintenance' => {
      'readonly' => {
        'enabled' => true
      }
    }
  }
sudo gitlab-ctl reconfigure

По окончанию работ устанавливаем enabled в false и снова sudo gitlab-ctl reconfigure.

Алгоритм чистки

GitLab

Для работы с GitLab нам понадобится GitLab API и токен с правами api + если хотим проверять и чистить приватные репозитории - понадобится read_repository и write_registry.

Для получения образов, хранимых в registry GitLab, нужны id проекта и id репозитория в registry.

GitLab pagination

GitLab выдает информацию страницами, размер страницы про умолчанию 20 элементов, максимальный размер страницы 100 элементов. Также в заголовке передается поле X-Total, а в нем общее количество элементов его можно использовать для того, чтобы сразу генерировать список страниц и опрашивать их параллельно.

  1. Забираем информацию о проектах через /api/v4/projects. Endpoint возвращает список объектов. Полей много, но нас интересует поле id.

  2. Фильтруем проекты, которые необходимо исключить.

  3. Зная project[id] собираем информацию о репозиториях через /api/v4/projects/{project[id]}/registry/repositories. Тут мы получим список объектов, из которых заберем id репозиториев.

  4. И, наконец, собираем теги /api/v4/projects/{repo['project_id']}/registry/repositories/{repo['id']}/tags

На выходе получаем список объектов. Вот пример одного из них:

{
    "location": "mygitlab.abc.ru:3000/dev/my-awsome-app/base:deploy_123",
    "name": "deploy_123",
    "path": "dev/my-awsome-app/base:deploy_123"
  }

В объект я сразу вбрасываю поле del_url. Как можно догадаться - в нем URL для удаления данного образа.

Итог - список всех тегов с образами и ссылками на удаление тега, за исключением тех проектов которые мы изначально решили не трогать.

Kubernetes

Для взаимодействия с Kubernetes используется модуль kubernetes. Если вы, также как и я, хотите заново изобрести велосипед - список пользовательских библиотек для разных языков лежит здесь.

Kubernetes хранит историю всех работающих в нем приложений. Ее можно посмотреть командой kubectl rollout history <указание на объект>, либо собрать ReplicaSetы и по номеру ревизии определить кто за кем идет. Я использовал второй вариант. Он также позволит нам забирать любые интересующие нас поля. Из полученной информации я забирал образ, номер ревизии и идентификатор. В качестве идентификатора приложения, к которому принадлежит данный replicaset, я использовал имя namespace + label app, либо для служебных приложений - replica_set.spec.template.spec.service_account. Получаем объект: поля - идентификаторы приложения, содержимое - образы с ревизиями. Дальше все просто. Оставляем по каждому приложению N образов из последних ревизий и оставшиеся образы сбрасываем в одну кучу.

Итог - список образов из Kubernetes. Если эти образы есть в GitLab их теги чистить не нужно.

ВНИМАНИЕ: В список не попадут Job и CronJob, так как они не имеют ReplicaSet. Чтобы их сохранить - можно ручками внести проекты в исключения, либо автоматически отфильтровать.

Унифицированного подхода я не придумал, а наша реализация этой фичи останется секретом фирмы :)

"Отделяем зерна от плевел" точнее наоборот...

Из множества образов GitLab вычитаем множество Кубернячих образов и получаем то, что можно удалить. Ниже картинка для наглядности.

Для полной автоматизации все это можно запихнуть в контейнер и создать на это дело CronJob или Job. Только не забудьте добавить этот проект в исключения.

Автоматизация написана на python, но это не столь принципиально. Можно значительно сократить размер кода и затраты памяти, если чуть чуть подумать.

Комментарии 5

    0
    А регулярки работают вообще в настройке очистки образов?
    Такое ощущение, что там только шаблоны.
    По крайней мере у меня не получилось сохранять только образы вида: 0.3.12_123
      0
      Если вопрос про API, то используя Bulk Delete можно удалять теги внутри одного репозитория и там можно использовать регулярки, но я не пробовал. В основном теги находящиеся в работе такие-же как и те что протухли.
      +1

      это есть из коробки в werf, советую попробовать. Запушенные в kubernetes образы он также не чистит.

        +2
        Естественно я слежу за деятельностью коллег из Флант, но мне показалось внедрять Werf только ради чистки Registry чересчур расточительным, тем не менее спасибо за совет.
          0
          В этой статье мы весьма подробно рассказывали о самой проблеме и нашем (в werf) подходе к её комплексному решению.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое