Возможно, вы уже активно используете CRI-O и Podman, а может только смотрите на альтернативы Docker с осторожностью. Но, как бы там ни было, альтернативные решения создают конкуренцию монополисту Docker и предлагают новые и востребованные улучшения. Одна из таких особенностей, это исключение Docker Hub как корневого и основного источника образов контейнеров. Таким образом, снимается привязка к поставщику и появляются новые возможности, а одной из таких мы и поговорим.

Это инструкция по выбору решения и настройке прозрачного кеширования множества реестров контейнеров для CRI-O, Podman, Buildah, Skopeo и прочих инструментов, работающих с образами контейнеров OCI и использующих общую конфигурацию containers/common.

Для чего нужен прокси?

Если у вас есть несколько экземпляров CRI-O или Podman, работающих в вашей инфраструктуре, например: кластер Kubernetes, сборочные агенты, физические или виртуальные машины на которых работают контейнеризированные приложения. Каждый такой узел при запуске контейнера обращается к реестру контейнеров и пытается скачать образ контейнера, если он остутствует локально в кеше или найдена новая версия. Мы развернем и настроим кеширующий прокси сервер, для получения образов контейнеров из быстрого локального источника, тем самым:

  • Обойдем ограничения на скачивание;

  • Увеличим скорость запуска контейнеров, единожды запрошеный контейнер осядет в кеш и все последующие запросы будут отработаны гораздо быстрее, особенно актуально для узких интернет каналов;

  • Увеличим доступность и стабильность. Аптайма 100% не существует, и в самый ответственный момент публичный реестр контейнеров может оказаться недоступным, по разным причинам, имя кеш мы с большей вероятностью, по-прежнему сможем запускать контейнеры, а в случае недоступности кеша контейнер будет получен на прямую;

  • Сэкономим трафик (если это еще кому-то актуально);

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

А самое главное, это будет прозрачный кеш, т.е. людям работающим в этих окружениях не нужно будет даже знать или как-то дополнительно заботится о том, что есть прокси сервер и его нужно использовать. Это просто будет работать и даже в закрытом контуре.

Проксирование будем настраивать для семи популярных реестров контейнеров:

  • docker.io

  • quay.io

  • gcr.io

  • k8s.gcr.io

  • ghcr.io

  • mcr.microsoft.com

  • registry.gitlab.com

Этот список может быть расширен любыми другими реестрами контейнеров, к примеру вы можете добавить ваш личный реестр или запроксировать только определенную группу (namespace, организацию).

Отличие использования зеркал

Docker - позволяет указать список registry-mirrors только для основного зеркала (library), это означает, что только Docker Hub будет проксироваться прозрачно, для прочих реестров контейнеров будет необходимо использовать измененный адрес контейнера proxy.host.tld/registry.host.tld/namespace/image:tag. Есть конечно обходной путь с использованием HTTPS_PROXY, но этот метод также не лишен недостатков.

CRI-O и Podman - предоставляет возможность настроить перечень реестров контейнеров и зеркал для каждого реестра персонально, чем мы непременно воспользуемся.

Конфигурация registries.conf

‎Все настройки мы будем выполнять в конфигурационных файлах из проекта containers/image. Здесь вы можете найти документацию к файлу registries.conf.

А еще, для большего удобства, вы можете хранить конфигурацию в отдельных файлах в каталоге /etc/containers/registries.conf.d/ или использовать персональные настройки в пользовательском каталоге $HOME/.config/containers/registries.conf

А это пример конфигурации реестров и их зеркал:

unqualified-search-registries = ["my-registry.tld"]

[[registry]]
prefix = "my-registry.tld/namespace"
location = "internal-registry.tld/project-one"

[[registry.mirror]]
location = "container-mirror.local/namespace"

[[registry.mirror]]
location = "container-mirror-2.local/mirrors/namespace"
insecure = true

Пример того как будет обработан запрос скачивания образа  namespace/image:tag

  1. Сначала будет попытка найти алиас [aliases] из registries.conf для образа namespace/image, пример имеющихся алиасов вы найдете в файле
    /etc/containers/registries.conf.d/000-shortnames.conf

  2. Далее будет попытка найти образ на предложенном из списка unqualified-search-registries узле, так как указан всего один узел, поиск произойдет автоматически на my-registry.tld

  3. Первая попытка получения образа произойдет по адресу
    container-mirror.local/namespace/image:tag

  4. Иначе, будет запрошен адрес
    container-mirror-2.local/mirrors/namespace/image:tag
    игнорируя проверку сертификата

  5. Иначе, обратимся в оригинальный источник
    internal-registry.tld/project-one/image:tag

Выбор решения

Существует несколько решений, позволяющих развернуть локально кеширующий прокси сервер для образов контейнеров, рассмотрим некоторые популярные решения:

  • Собственная реализация - можно реализовать что-то своё взяв библиотеку distribution или сконфигурировать Nginx, Squid или другой подходящий прокси. Но мы не первопроходцы в этом деле, и можно обратить внимание на проект Docker Registry Proxy реализованный на Nginx или Docker Registry Cache основанный на Squid. Это самое гибкое и легковесное решение позволяющее проксировать любое количество репозиториев, а при помощи Lua или njs возможно реализовать почти любые идеи, но это потребует дополнительных компетенций и добавит сложности в обслуживании. Врят ли это то, что вы искали.

  • Distribution - стандартное решение для запуска реестра контейнеров с открытым исходным кодом, совместимо со спецификацией OCI, библиотека используется в реализации таких проектов как: Docker Hub, GitHub Container Registry, GitLab Container Registry, VMware Harbor Registry и прочих. Помимо хранения ваших контейнеров также поддерживает проксирование одного репозитория, для проксирования нескольких репозиториев, придется запустить по экземпляру приложения на каждый репозиторий.

  • Harbor - зрелое решение для запуска реестра контейнеров от VMware с открытым исходным кодом. Имеет web-интерфейс, ролевой контроль доступа, интеграцию c AD и OIDC, аудит, сканирование уязвимостей и прочие возможности. Позволяет создать прокси-репозиторий на каждый реестр контейнеров. GitHub.

  • Quay и Project Quay - коммерческий и свободно распространяемый реестр контейнеров от Red Hat. По функциональности схож с Harbor но имеет более гибкие возможности по разграничению прав доступа, основным отличием для нас является зеркалирование удаленного реестра контейнеров. Здесь это именно зеркалирование в отличии от прозрачного кеширования, что может оказаться избыточным и не подходящим при решении нашей задачи. ProjectQuay GitHub.

  • Sonatype Nexus - коммерческий и свободно распространяемый реестр артефактов от Sonatype. Это настоящий комбайн для хранения и проксирования артефактов для огромного множества поддерживаемых репозиториев, таких как: Nuget, NPM, Maven, APT, YUM, Conan, Docker и прочих. Как рестр образов контейнеров, Nexus уступает Quay и Harbor по обилию возможностей, но вполне успешно справляется с проксированием нескольких реестров и позволяет объединить их в группы. Прекрасно подойдет вам, если в вашем окружении выполняются сборочные пайплайны, вы сомжете собрать весь необходимый кеш артефактов через единый сервис. Nexus OSS GitHub.

  • JFrog Artifactory - коммерческое решение схожее по функциональности с Sonatype Nexus. Решения довольно похожи, можно посмотреть сравнение решений от Sonatype, и от JFrog. Также имеется бесплатная версия предназначеная только для хранения образов контейнеров и helm чартов.

Реализация класса "Стяжки и синяя изолента"

Изобретать свой велосипед мы с вами не будем, а пожалуй воспользуемся уже готовым Docker Registry Proxy, для демонстрации возможностей этого решения будет достаточно. Тем не менее, изучив образ контейнера Docker Registry Proxy, вы сможете реализовать своё решение под ваши нужды.

Запустим контейнер:

mkdir -p ./containers-registry-proxy/cache
mkdir -p ./containers-registry-proxy/certs

podman run --rm --detach --name containers-registry-proxy \
  --publish 0.0.0.0:3128:3128 \
  --env ENABLE_MANIFEST_CACHE=true \
  --env REGISTRIES="quay.io gcr.io k8s.gcr.io ghcr.io mcr.microsoft.com registry.gitlab.com" \
  --volume "$(pwd)/containers-registry-proxy/cache":/docker_mirror_cache \
  --volume "$(pwd)/containers-registry-proxy/certs":/ca \
  rpardini/docker-registry-proxy:0.6.4

Вот и всё, прокси запущен, в отличии от прочих решений, данный пример работает как HTTP прокси, и требует указания адреса прокси сервера в переменных HTTP_PROXY и HTTPS_PROXY. Для более тонкой настройки обратитесь к документации проекта.

⚠️ Будьте готовы встретить проблемы и необходимость искать ошибки и дорабатывать решение под свои потребности.

Оценка решения:

  • ???? Минимальное потребление ресурсов;

  • ???? Решение подходит для прозрачного проксирования образов для Docker;

  • ???? Это только кешируйщий прокси, вы не можете публиковать здесь свои образы контейнеров;

  • ???? Возможность кешировать другие типы репозиториев, но потребует доработки, дополнительных знаний и времени;

  • ???? Отсутствует веб-интерфейс для администрирования;

  • ???? Работает как HTTP прокси, при других реализациях требует подмены DNS или публикации нескольких экземпляров на разных портах;

  • ???? Сложная отладка и кастомизация.

Реализация класса "Нативный инструмент"

Для реализации будем использовать немного сложный и при этом гибкий вариант, мы запустим несколько экземпляров Distribution. Воспользуемся официальным образом контейнера.

Давайте запустим наш первый прокси для Docker Hub:

mkdir -p ./containers-registry-proxy/docker.io

podman run --rm --detach --name registry \
  --publish 5000:5000 \
  --env REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/cache \
  --env REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io \
  --volume "$(pwd)/containers-registry-proxy/docker.io":/cache \
  registry:2

Добавим наше зеркало Docker Hub в конфигурационный файл registries.conf

[[registry]]
prefix = "docker.io"

[[registry.mirror]]
prefix = "docker.io"
location = "0.0.0.0:5000"
insecure = true

И проверим, что все работает:

podman --log-level debug pull docker.io/alpine

В отладочных сообщениях мы увидим, что все запросы ушли на http://0.0.0.0:5000, а в ниже приведенных каталогах, появились данные:

  • ./containers-registry-proxy/docker.io/docker/registry/v2/repositories/library/

  • ./containers-registry-proxy/docker.io/docker/registry/v2/blobs/sha256/

Подробности по конфигурированию Distribution можно найти на странице документации. При развертывании продуктового решения не забудьте про TLS, а также обратите внимание на наличие Promethues метрик и поддерживаемые бэкенды хранения, к примеру S3.

Для реализации нашей задачи по прозрачному проксированию нескольких реестров контейнеров, всю рутину по созданию и запуску множества экземпляров Distribution и созданию конфигурационных файлов, мы можем автоматизировать, к примеру при помощи bash скрипта.

Скрипт для запуска нескольких копий Distribution

В скрипте также используется запуск Redis для кеширования метаданных и более быстрого доступа к ним.

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

Пример конфигурации registries.conf полученный из скрипта
unqualified-search-registries = [
  "docker.io",
  "quay.io",
  "gcr.io",
  "k8s.gcr.io",
  "ghcr.io",
  "mcr.microsoft.com",
  "registry.gitlab.com",
]

[[registry]]
prefix = "docker.io"
[[registry.mirror]]
prefix = "docker.io"
location = "0.0.0.0:5000"
insecure = true

[[registry]]
prefix = "quay.io"
[[registry.mirror]]
prefix = "quay.io"
location = "0.0.0.0:5001"
insecure = true

[[registry]]
prefix = "gcr.io"
[[registry.mirror]]
prefix = "gcr.io"
location = "0.0.0.0:5002"
insecure = true

[[registry]]
prefix = "k8s.gcr.io"
[[registry.mirror]]
prefix = "k8s.gcr.io"
location = "0.0.0.0:5003"
insecure = true

[[registry]]
prefix = "ghcr.io"
[[registry.mirror]]
prefix = "ghcr.io"
location = "0.0.0.0:5004"
insecure = true

[[registry]]
prefix = "mcr.microsoft.com"
[[registry.mirror]]
prefix = "mcr.microsoft.com"
location = "0.0.0.0:5005"
insecure = true

[[registry]]
prefix = "registry.gitlab.com"
[[registry.mirror]]
prefix = "registry.gitlab.com"
location = "0.0.0.0:5006"
insecure = true

Оценка решения:

  • ???? Нативное решение;

  • ???? Минимальное потребление ресурсов;

  • ???? Вы можете публиковать сюда свои образы контейнеров запустив еще один экземпляр Distribution;

  • ???? Горизонтально и вертикально масштабируется;

  • ???? Сравнительно более сложное в обслуживании решение;

  • ???? Отсутствует веб-интерфейс для администрирования (возможное решение).

Реализация класса "Коробочное решение"

Для реализации будем использовать Harbor. Минимально для запуска потребуется выделить 2 CPU и 4 Gb ОЗУ, для нормальной работы необходимо вдвое больше ресурсов. Установку выполним при помощи официального инсталятора и выполним настройку согласно документации.

Выполнив базовую настройку, перейдем в интерфейс и на каждый проксируемй репозиторий создадим по одноименному проекту в соответствии с примером из документации.

Теперь можем добавить конфигурацию в файл registries.conf, где каждому репозиторию указан в качестве зеркала отдельный проект в рамках Harbor.

Пример конфигурации registries.conf
[[registry]]
prefix = "docker.io"
[[registry.mirror]]
prefix = "docker.io"
location = "harbor.host.tld/docker"

[[registry]]
prefix = "quay.io"
[[registry.mirror]]
prefix = "quay.io"
location = "harbor.host.tld/quay"

[[registry]]
prefix = "gcr.io"
[[registry.mirror]]
prefix = "gcr.io"
location = "harbor.host.tld/gcr"

[[registry]]
prefix = "k8s.gcr.io"
[[registry.mirror]]
prefix = "k8s.gcr.io"
location = "harbor.host.tld/k8s-gcr"

[[registry]]
prefix = "ghcr.io"
[[registry.mirror]]
prefix = "ghcr.io"
location = "harbor.host.tld/ghcr"

[[registry]]
prefix = "mcr.microsoft.com"
[[registry.mirror]]
prefix = "mcr.microsoft.com"
location = "harbor.host.tld/mcr"

[[registry]]
prefix = "registry.gitlab.com"
[[registry.mirror]]
prefix = "registry.gitlab.com"
location = "harbor.host.tld/gitlab"

Можем проверить получение образа, после чего в интерфейсе Harbor увидим осевшие в кеше образы и слои.

Оценка примера:

  • ???? Вы можете публиковать сюда свои образы контейнеров;

  • ???? Наличие веб-интерфейса для администрирования и управления;

  • ???? Имеет сканирование безопасности и ролевые политики;

  • ???? Умеренное потребление ресурсов;

  • ???? Избыточность для решения задачи кеширующего прокси.

Реализация класса "Звёздный разрушитель типа Венатор"

Рассмотрим пример запуска Sonatype Nexus OSS, бесплатной версии решения. Для коммерческой версии настройки будут такими же, а для JFrog Artifactory настройка будет похожей и описана в официальной документации.

Установим Nexus согласно официальной документации, для запуска нам понадобится выделить 4 CPU и 8 Gb ОЗУ, но при активном использовании готовтесь отдать около 32 Gb ОЗУ.

Завершив установку, перейдем в интерфейс администратора и выполним настройку проксирования репозиториев, в отличии от Harbor, где мы публиковали зеркала на разных маршрутах, здесь как в Distribution, каждый репозиторий может быть опубликован на собственном порту. Но для удобства существует возможность объединения нескольких репозиториев в группы.

Для каждого реестра контейнеров создадим по новому репозиторию формата docker (proxy) в соответствии с документацией.

Пример создания docker (proxy) репозитория в Nexus для ghcr.io
Пример создания docker (proxy) репозитория в Nexus для ghcr.io

Для разнообразия конфигурирования, создадим новый репозиторий с типом docker (group) и объеденим все наши прокси в общую группу:

Пример групировки docker (proxy) репозиториев в общую групповой репозиторий docker (group)
Пример групировки docker (proxy) репозиториев в общую групповой репозиторий docker (group)

Теперь можем добавить конфигурацию в файл registries.conf, где каждому репозиторию указан в качестве зеркала один и тот же адрес группового репозитория.

Пример конфигурации registries.conf
[[registry]]
prefix = "docker.io"
[[registry.mirror]]
prefix = "docker.io"
location = "nexus.host.tld:8082"

[[registry]]
prefix = "quay.io"
[[registry.mirror]]
prefix = "quay.io"
location = "nexus.host.tld:8082"

[[registry]]
prefix = "gcr.io"
[[registry.mirror]]
prefix = "gcr.io"
location = "nexus.host.tld:8082"

[[registry]]
prefix = "k8s.gcr.io"
[[registry.mirror]]
prefix = "k8s.gcr.io"
location = "nexus.host.tld:8082"

[[registry]]
prefix = "ghcr.io"
[[registry.mirror]]
prefix = "ghcr.io"
location = "nexus.host.tld:8082"

[[registry]]
prefix = "mcr.microsoft.com"
[[registry.mirror]]
prefix = "mcr.microsoft.com"
location = "nexus.host.tld:8082"

[[registry]]
prefix = "registry.gitlab.com"
[[registry.mirror]]
prefix = "registry.gitlab.com"
location = "nexus.host.tld:8082"

Оценка примера:

  • ???? Вы можете публиковать сюда свои образы контейнеров

  • ???? Наличие веб-интерфейса для администрирования и управления

  • ???? Возможность проксировать другие типы репозиториев

  • ???? Имеет сканирование безопасности и ролевые политики

  • ???? Избыточность для решения задачи кеширующего прокси образов контейнеров

  • ???? Возможно потребует денег

  • ???? Сравнительно большое потребление ресурсов

  • ???? По неопытности можно вызвать коллизи с контейнерами для групповых репозиториев.

Отладка

Для отладки на стороне клиента запросим образ с уровнем логирования debug:

podman --log-level debug pull docker.io/alpine:3.12

А вот и пример проблемы отсутсвующего TLS:

DEBU[0000] Trying to access "0.0.0.0:3128/library/alpine:3.12" 
DEBU[0000] No credentials for 0.0.0.0:3128 found        
DEBU[0000] Using registries.d directory /etc/containers/registries.d for sigstore configuration 
DEBU[0000]  Using "default-docker" configuration        
DEBU[0000]  No signature storage configuration found for 0.0.0.0:3128/library/alpine:3.12, using built-in default file:///home/woozymasta/.local/share/containers/sigstore 
DEBU[0000] Looking for TLS certificates and private keys in /etc/docker/certs.d/0.0.0.0:3128 
DEBU[0000] GET https://0.0.0.0:3128/v2/                 
DEBU[0000] Ping https://0.0.0.0:3128/v2/ err Get "https://0.0.0.0:3128/v2/": http: server gave HTTP response to HTTPS client (&url.Error{Op:"Get", URL:"https://0.0.0.0:3128/v2/", Err:(*errors.errorString)(0xc000422e60)}) 
DEBU[0000] GET https://0.0.0.0:3128/v1/_ping            
DEBU[0000] Ping https://0.0.0.0:3128/v1/_ping err Get "https://0.0.0.0:3128/v1/_ping": http: server gave HTTP response to HTTPS client (&url.Error{Op:"Get", URL:"https://0.0.0.0:3128/v1/_ping", Err:(*errors.errorString)(0xc000423050)}) 
DEBU[0000] Accessing "0.0.0.0:3128/library/alpine:3.12" failed: error pinging docker registry 0.0.0.0:3128: Get "https://0.0.0.0:3128/v2/": http: server gave HTTP response to HTTPS client 
DEBU[0000] Trying to access "docker.io/library/alpine:3.12" 

Рекомендации

Лучше всего, всегда использовать полностью определенные имена образов, включая имя сервера реестра контейнеров, пространство имен, имя образа и тег, например:

  • ghcr.io/woozymasta/archimate-ci:4.9.1-1.0.2

  • quay.io/woozymasta/archimate-ci:4.9.1-1.0.2

  • docker.io/woozymasta/archimate-ci:4.9.1-1.0.2

DockerHub это не единственный источник правды, а в конфигурации у пользователся может быть настроено что-то не стандартное, могут быть заданы какие-то персональные алиасы, по этому даже для DockerHub лучше указывать абсолютный адрес начинающийся с docker.io

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

Старайтесь выполнять анализ уязвимостей для хранимых у вас образов в ваших реестрах контейнеров, будь это прокси или собственные репозитории. Рекомендую обратить внимание на утилиту Clair которая без проблем интегрируется в Harbor и Quay, и при небольшом усили в Distribution.

Выводы

Какое из решений использовать?

На практике для проксирования образов контейнеров, я использую все из перечисленных решений кроме самоделок на nginx, всё зависит от контекста. К примеру:

  • При развертывании On-Premise серверов предназначенных для запуска контейнеризированных приложений и кластеров Kubernetes, я использую Distribution размещенный на специально отведенный под это узел или в кластере Kubernetes, за частую используя Minio как хранилище.

  • Harbor или Project Quay подходит для небольших команд, где планируется разработка и построение CI пайплайнов. Также это может быть встроенный реестр контейнеров GitLab который также позволяет проксировать образы. Тут всё зависит от конкретной ситуации.

  • Для больших команд разработки при построении процессов CI и CD, зачастую использую Sonatype Nexus OSS как прокси для всего, что только можно кешировать. Но стараюсь не использовать как целевое хранилище контейнеров, вопреки: довольно слабой ролевой модели, отсутсвии OIDC в OSS версии и уступающему удобству и функцоналу в сравнении с Harbor или Project Quay.


На этом всё

Благодарю за ваше время и внимание! Стабильных и высокодоступных окружений вам.

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

Комментарии (12)


  1. chemtech
    25.12.2021 07:50
    +1

    Отличный пост!

    Кстати, есть чат по Nexus https://t.me/ru_nexus_sonatype


    1. gecube
      27.12.2021 14:07

      А еще есть чат по артифактори :-)

      https://t.me/ru_artifactory

      А еще.... а еще... а еще есть slack по всем cncf продуктам (включая vmware harbor)


  1. gecube
    25.12.2021 14:57
    +1

    Очень жаль, что не рассмотрен containerd. CRI-O решение неплохое, но гораздо менее популярное, конечно.

    Что еще мне не понравилось в конфигурации CRI - то, что это нужен полный доступ к узлам. А если дело происходит в облаке и нет возможности менять конфиги на узлах кубернетес кластера?

    Еще вариант (идею) - дарю - можно написать mutation webhook, который будет переписывать поле image: во всех pod'ах - в этом случае можно вообще не пользоваться прокси-репо, а попросту переложить все образа к себе.

    И еще фактор, который мне в прокси не нравится - он не ускоряет дистрибьюцию образов по узлам (для этого надо использовать решения вроде https://github.com/uber/kraken но я сильно тему не изучал) и второй момент - если образ удалили или подменили в удаленном регистри (например, на докерхабе это достаточно частая проблема), то кэш тут может не помочь...


    1. gecube
      25.12.2021 20:25
      +1

      Еще что добавить хочу - не обязательно покупать платный Artifactory. Разработчики предлагают бесплатную версию на той же кодовой базе, но с ограниченным функционалом ТОЛЬКО для докер образов - https://jfrog.com/container-registry/ Странно, что этот продукт не рассмотрен в обзоре. По идее у него настройка такая же, как у полного JFrog Artifactory, но не нужно выкладывать сотни нефти :-)

      А еще меня удивила стрелочка на диаграмме от Flux/Argo к podman. Если в случае kubernetes/openshift + cri-o я понимаю, почему она там есть, то в случае podman не очень, потому что эти решения напрямую не интегрируются. Что я упустил?  


      1. WoozyMasta Автор
        27.12.2021 11:54

        https://jfrog.com/container-registry/ Странно, что этот продукт не рассмотрен в обзоре.

        Спасибо, ссылку на бесплатный container-registry в статью добавил, а вот рассматривать Artifactory не стал, также как и Quay, я посчитал, что это будет избыточно, достаточно упоминания в сравнении и ссылки на руководство.

        для JFrog Artifactory настройка будет похожей и описана в официальной документации


      1. WoozyMasta Автор
        27.12.2021 11:57

        А еще меня удивила стрелочка на диаграмме от Flux/Argo к podman.

        А вы внимательный :)

        Даже не знаю как она там оказалась, видимо это всё мои мечты под впечатлением новости, что podman теперь умеет не только Pod запускать но и Deployment.


    1. WoozyMasta Автор
      27.12.2021 12:09

      Что еще мне не понравилось в конфигурации CRI - то, что это нужен полный
      доступ к узлам. А если дело происходит в облаке и нет возможности
      менять конфиги на узлах кубернетес кластера?

      Подскажите, а как вы изменяете конфиги containerd на узлах где нет возможности их изменять?


      1. gecube
        27.12.2021 12:15
        +1

        Небольшой дисклеймер - когда я пишу "CRI", то я имею в виду и cri-o, и containerd , и любой другой контейнерный движок.

        В случае облака - если нет возможности, то нет возможности. Приходится придумывать обходные пути.

        Какие плюс-минус рабочие варианты знаю:

        1. Если есть поддержка своих шаблонов воркеров - можно конфиг вшить туда

        2. Если такого нет, но очень хочется - можно попробовать раскатать daemonset с hostpath, чтобы заменить на узлах файлы конфигурации. Но это уже не так надежно, т.к. влезаешь в логику работы платформы

        3. Если и этого нет, тогда похоже все ) и нужно искать альтернативные способы получить желаемое (не через конфиг)


        1. WoozyMasta Автор
          27.12.2021 12:41

          Небольшой дисклеймер - когда я пишу "CRI", то я имею в виду и cri-o, и containerd , и любой другой контейнерный движок.

          И в правду, скорее моя невнимательность.

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


    1. WoozyMasta Автор
      27.12.2021 12:37

      Не спорю, что в статье приведено нишевое решение, если абстрагироваться от облаков, в случае on-premise решений, особенно в совокупности таких факторов как: закрытый контур, строгая политика ИБ и медленный интернет канал, проксирование очень даже упрощает и ускоряет дистрибьюцию.

      если образ удалили или подменили в удаленном регистри, то кэш тут может не помочь

      Если подменили, то всё будет хорошо, прокси в первую очередь валидирует метаданные, сверяет их с удаленным реестром контейнеров, и только если изменений нет (или сервер не ответил) мы получим данные из кеша. Касаемо удаления, это вопрос хороший, в Nexus знаю есть отдельная опция для обработки и кеширования 404, а в Distrubution кеш для удаленного образа, скорее всего продолжит своё существование. В любом случае, для кеша полезно делать отдельную задачу в планировщике, для удаления старых и неиспользуемых образов, что от части решает вопрос удаления.

      можно написать mutation webhook

      А можно не писать, используя CRI-O/Podman и конфигурацию registries.conf :)

      Мне кажется идея с mutation webhook для image может нарушить работу keel.sh и подобных решений, но это не точно, нужно проверять на практике.


      1. gecube
        27.12.2021 13:20

        Если подменили, то всё будет хорошо, прокси в первую очередь валидирует метаданные, сверяет их с удаленным реестром контейнеров, и только если изменений нет (или сервер не ответил) мы получим данные из кеша. Касаемо удаления, это вопрос хороший, в Nexus знаю есть отдельная опция для обработки и кеширования 404, а в Distrubution кеш для удаленного образа, скорее всего продолжит своё существование. В любом случае, для кеша полезно делать отдельную задачу в планировщике, для удаления старых и неиспользуемых образов, что от части решает вопрос удаления.

        как раз не хорошо.

        Потому что если образ с докерхаба удалили, а мы им пользуемся, то если он исчезнет из кэша - мы получим неработоспособную систему (образа-то нет!)

        В случае, если кто-то образ обновил - тоже большой вопрос - хотим ли мы, чтобы софт обновился (например, мы намеренно указали :latest на dev-стенде), но для прода это попросту недоступимо, потому что мы рассчитываем на то, что то, что мы задеплоили, то и будет крутиться, пока мы явно не обновим тег-версию.

        Мне кажется идея с mutation webhook для image может нарушить работу keel.sh и подобных решений, но это не точно, нужно проверять на практике.

        может быть, но можно это сделать аккуратно :-)


        1. WoozyMasta Автор
          27.12.2021 14:19

          Потому что если образ с докерхаба удалили, а мы им пользуемся, то если он исчезнет из кэша - мы получим неработоспособную систему (образа-то нет!)

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

          Касаемо latest, мне кажется это выбор каждого, и если мы указали postgres:13.5-bullseye за место postgres:13 , значит мы пошли на это осознанно, и кешем стандартный механиз поставки не нарушаем. Иначе могут возникнуть вопросы - "а почему мой latest не latest?".

          Для жёсткой фиксации на версии, всегда можно указать конкретный манифест:

          postgres:13.5-bullseye@sha256:3f34db7403050a89aecb3e17d3f22c771b76120565d113d5462f673e229c5472