Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Ни для кого уже не новость, что начиная с 2 ноября 2020 года Docker Hub ввел ограничения на скачивание образов: для анонимных пользователей он будет равен одной сотне за шесть часов, а для авторизованных пользователей будет зависеть от уровня подписки.
В компании GitLab мы очень внимательно следили за этими изменениями, так как они затрагивали практически всех наших пользователей и клиентов. Сегодня я хотел бы рассказать о том, какие изменения мы внесли и как адаптировались к новым правилам.
Что же произошло?
Публичный регистр контейнеров Docker Hub очень широко и часто используется сообществом DevOps для достижения разнообразных целей: запуска CI/CD задач, стандартизации процессов, выката контейнерных приложений как в sandbox, так и в production. Как только мы узнали о введении новых ограничения по количеству запросов, мы начали анализ новых правил, чтобы понять, как они повлияют на работу наших пользователей, и как мы можем почем решить возможные проблемы.
Согласно новым правилам после 100 запросов за 6 часов с одного клиентского IP адреса каждый новый docker pull
вернет ошибку 429 - too many requests
, что несомненно приведет к сломанным CI/CD конвейерам, невозможности выкатить приложения и целому букету ошибок в ваших Kubernetes кластерах. Вполне понятно, что этот лимит может быть очень быстро достигнут, особенно если все задачи выполняются с одного и того же GitLab Runner агента, или если команда из нескольких инженеров работает с одного и того же публичного адреса.
Аутсорсинг Dependency Proxy
Как отметил мой коллега Tim Rizzi "Нам следует срочно всем рассказать о Dependency Proxy", который изначально создавался для проксирования и кэширования образов Docker Hub. Этот функционал существует в GitLab уже довольнейший давно (начиная с версии 11.11), но до сегодняшнего дня был доступен только для пользователей Enterprise подписки уровня Premium. Перед продуктовой командой встал вполне резонный вопрос: "Стоит ли нам вынести Dependency Proxy в open source версию продукта, помогая таким образом широкому сообществу пользователей минимизировать проблемы из-за новых ограничений Docker Hub?"
Не вдаваясь в подробности, ответ на этот вопрос был ДА. При принятии решения, в какой уровень подписки должен попадать тот или иной функционал продуктовая команда GitLab всегда руководствуется вопросом "Кто является целевым пользователем?". Согласно этому принципу те возможности, которые чаще всего запрашивает индивидуальный участник или разработчик, попадают в Core или Open Source версию продукта. Скачивание образов с Docker Hub вполне соответсвует этому описанию. Более того аутсорсинг Dependency Proxy поможет большому количеству разработчиков повысить надежность и производительность их CI/CD конвейеров.
Как результат, начиная с версии 13.6 вышедшей 22 ноября 2020 года, проксирование и кэширование образов в GitLab стало абсолютно бесплатным для всех наших пользователей!
Что дальше?
К сожалению, идеальные решения не появляются мгновенно. Мы как никто другой знаем, что нашему продукты есть куда расти, поэтому активно работаем над улучшением функционала Dependency Proxy и уже в ближайших релизах планируем добавить новые возможности / решить имеющиеся проблемы:
13.7 (22 декабря, 2020)
gitlab-#11582 сделает возможным использование Dependency Proxy для приватных групп в GitLab (сегодня работает только для публичных проектов)
gitlab-#241639 позволит использовать закэшированный образ даже если Docker Hub недоступен. На сегодня это невозможно, так как даже при наличии закэшированного образа, его манифест всегда скачивается из конечного регистра
gitlab-#21619 добавит новый параметр
pull_policy
в YAML описании CI/CD задач, позволяющий разработчикам самим указывать политику скачивания контейнера (always, if-not-present, never) вместо того, чтобы полагаться на настройки GitLab Runnergitlab-runner-#26558 позволит конфигурировать GitLab Runner с набором политик для скачивания образов (always, if-not-present)
Мониторинг ограничений
Решения обозначенные выше, а также в блог посте моего коллеги Steve Azzopardi, помогут упростить работу с новыми ограничениями, но не избавят от них на все 100%. Поэтому мы также выработали набор советов и инструментов, цель которых - помочь широкому сообществу адаптироваться к новым лимитам за счет их мониторинга.
Как проверить текущее значение лимита?
Документация Docker рекомендует использовать HTTP запрос для проверки текущего значения ограничений запросов в Docker Hub.
Начнем с определения образа, для которого мы хотим получить текущее ограничение и получения токена для авторизации:
$ IMAGE="ratelimitpreview/test"
$ TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$IMAGE:pull" | jq -r .token)
$ echo $TOKEN
Следующий шаг - симуляция запроса docker pull
. Вместо использования метода GET
отправляем HEAD
запрос (он не учитывается при подсчете ограничений). Ответ на этот запрос содержит параметры RateLimit-Limit
и RateLimit-Remaining
.
$ curl --head -H "Authorization: Bearer $TOKEN" https://registry-1.docker.io/v2/$IMAGE/manifests/latest
В примере ниже количество запросов ограничено 2500
, из которых 2495
еще доступны. 21600
определяет шестичасовой период (в секундах)
RateLimit-Limit: 2500;w=21600
RateLimit-Remaining: 2495;w=21600
Автоматизация проверки лимитов
Michael Friedrich, один из евангелистов GitLab, поделился готовым решением на Python для проверки ограничений. Проект включает подробную документацию по установке и использованию
$ python check_docker_hub_limit.py --help
usage: check_docker_hub_limit.py [-h] [-w WARNING] [-c CRITICAL] [-v] [-t TIMEOUT]
Version: 2.0.0
optional arguments:
-h, --help show this help message and exit
-w WARNING, --warning WARNING
warning threshold for remaining
-c CRITICAL, --critical CRITICAL
critical threshold for remaining
-v, --verbose increase output verbosity
-t TIMEOUT, --timeout TIMEOUT
Timeout in seconds (default 10s)
Скрипт возвращает следующие exit коды в зависимости от указанных параметров
0
- OK1
- WARNING2
- CRITICAL
$ python3 check_docker_hub_limit.py
OK - Docker Hub: Limit is 5000 remaining 4997|'limit'=5000 'remaining'=4997
$ echo $?
0
$ python3 check_docker_hub_limit.py -w 10000 -c 3000
WARNING - Docker Hub: Limit is 5000 remaining 4999|'limit'=5000 'remaining'=4999
$ echo $?
1
$ python3 check_docker_hub_limit.py -w 10000 -c 5000
CRITICAL - Docker Hub: Limit is 5000 remaining 4998|'limit'=5000 'remaining'=4998
$ echo $?
2
Экспортер Prometheus
Кроме этого мы подготовили и выпустили экспортер для Prometheus, который позволит экспортировать метрики ограничений и реализовать их полноценный мониторинг.
Репозиторий проекта включает демо контейнер, включающий себе экспортер, Prometheus, Grafana, и docker-compose
инструкции для его выката
$ cd example/docker-compose
$ docker-compose up -d
Перейдите по адресу http://localhost:3000
для доступа к дэшборду Grafana
Надеюсь, наш опыт и рекомендации окажутся для вас полезными!