Доступно в редакциях: Open/CE, BE, SE, SE+, Ultimate/EE, Core, Certified Core/CSE Lite (1.73), Certified Pro/CSE Pro (1.73)
Входит в расширения: Продвинутая защита инфраструктуры, Биллинг
Стадия жизненного цикла модуля: Preview
Модуль используется для управления путями загрузки образов контейнеров компонентов Deckhouse Platform (DP) и образов из дополнительных хранилищ (вендоров или ваших собственных).
Ниже описана текущая и предыдущая реализации модуля.
Кластер, в котором предыдущая реализация этого модуля никогда не работала, сразу использует текущую. Кластер, в котором работала предыдущая реализация модуля, использует предыдущую до перевода её в состояние Unmanaged, после чего миграция завершается сама. Процесс описан в разделе «Как устроена миграция на модуль registry».
Текущая реализация
Режимы работы
Модуль может работать в одном из следующих режимов (для выбора режима используется параметр mode):
Unmanaged(режим по умолчанию). В этом режиме модуль не управляет путями загрузки компонентов DP. Приmode: Unmanagedкластер продолжает загружать образы из того хранилища образов контейнеров, с которым был установлен (задаётся при бутстрапе кластера в параметреdeckhouseв InitConfiguration). Никакие компоненты модуля при этом не создаются.-
Managed. В этом режиме модуль управляет путями загрузки образов контейнеров. Управление путём загрузки передаётся модулю при включении администратором кластера параметраmode: Managed.При работе в этом режиме (когда модуль управляет путями загрузки) используются следующие независимые настройки:
primary.upstream— хранилище образов контейнеров, откуда загружаются образы. Если параметр не задан, кластер считается изолированным (air-gap): единственным источником становится внутрикластерный кеш, который наполняется командойd8 mirror push.storage.cache— управление внутрикластерным кешем на master-узлах. Если параметр указан, на master-узлах создаётся хранилище образов контейнеров. Все узлы получают образы из него, а upstream остаётся резервным путём, пока кеш наполняется.
Включение и выключение кеша, смена хранилище образов контейнеров, смена учётных данных — каждое из этих действий обычная перенастройка, возможная в любой момент и в любом порядке. Условие привязано ровно к одному изменению: при удалении upstream’а для перехода в air-gap модуль ожидает, пока во внутрикластерном кеше появится весь ожидаемый набор образов: только после этого образы перестанут загружаться из хранилища образов, которое было указано в
primary.upstream. При этом появляется алертD8RegistryAirGapTransitionHeld. Если бы переключение на внутрикластерный кеш происходило сразу после удаления upstream’а, все узлы могли бы остаться без источника образов.Кеш освобождает свой диск сам. Больше ничто и никогда ничего из него не удаляет данные — каждый релиз добавляет срез репозитория, — поэтому ночная сборка удаляет срезы релизов, которые кластер прошёл, сохраняя развёрнутый релиз и предыдущий. На время работы одна реплика переходит в режим read-only, поэтому по умолчанию сборка назначается на ночной час. Подробности — в описании параметра
storage.garbageCollectionи в разделе FAQ «Кеш растёт. Что его чистит».
Параметры primary.upstream и storage.cache вместе покрывают все поддерживаемые конфигурации:
primary.upstream |
storage.cache |
Что делает кластер |
|---|---|---|
| задан | false |
Узлы загружают образы напрямую из upstream’а. На master-узлах ничего не разворачивается |
| задан | true |
Кеш на проход: наполняется из upstream’а по запросу и заранее |
| не задан | true |
Air-gap. Кеш — единственный источник, путь внутрь — d8 mirror push |
| не задан | false |
Конфигурация отвергается: узлам было бы неоткуда загружать образы |
Дополнительные хранилища образов контейнеров
primary.upstream намеренно единственное хранилище образов контейнеров, настраиваемое в конфигурации модуля. Оно используется для образов компонентов DP. Дополнительные хранилища образов контейнеров (вендоров, нужные какому-то модулю, или ваши собственные) объявляются отдельным ресурсом RegistryUpstream. Пример:
apiVersion: deckhouse.io/v1alpha1
kind: RegistryUpstream
metadata:
name: virtualization-images
spec:
match: images.virtualization.example.com
upstream:
host: vendor.example.com
path: /virtualization
auth:
username: robot
password: <PASSWORD>
Подход с объявлением дополнительного хранилища образов выбран из-за того, что модуль или пользователь, добавляющий своё хранилище образов, не должен для этого править ModuleConfig, которым он не владеет. Такие хранилища образов всегда транзитные: они маршрутизируются через агент на узле, чтобы учётные данные и удостоверяющие центры лежали в одном месте, но никогда не кешируются.
Архитектура
Агент на узле
На каждом узле кластера в виде статического пода разворачивается агент (registry-agent). Container runtime направляется на него (127.0.0.1:5001, через каталог-фолбэк _default в containerd) и получает через него доступ к хранилищам образов контейнеров, передавая в запросе исходное имя хранилища.
Благодаря этому достигается следующее:
- Конфигурация узла статична. Добавление хранилища образов контейнеров, включение внутрикластерного кеша, смена учётных данных — ничего из этого не приводит к смене конфигурации ни на одном узле, т.к. container runtime обращается к хранилищу образов через агента.
- Учётные данные хранилища образов контейнеров не попадают в конфигурационные файлы runtime. Они хранятся на агенте и подставляются в каждый запрос.
- Учётные данные не хранятся в ресурсах модуля. RegistryNode, RegistryStorage и запись о действующем upstream указывают ключ в одном секрете, а не содержат сам ключ доступа. Это ресурсы кластерного уровня, и право читать их выдано каждому узлу, поэтому ключ внутри любого из них был бы доступен через API kubelet’у всего кластера. Доступ каждого компонента сужен до этого одного секрета по имени, а разрешённый ключ компонент хранит вместе со своей копией маршрутизации.
- Загрузка образов работает, когда API-сервер недоступен. Агент хранит копию своей маршрутизации на диске и переходит на неё, потому что среди образов, которые он отдаёт, есть и те, что нужны для восстановления сломанного control plane. Узел, который не смог получить доступ к API, использует маршрутизацию, с которой был установлен.
Ненастроенное хранилище образов контейнеров проксируется без изменений, вместе с теми учётными данными, которые уже были в запросе, — поэтому обычный imagePullSecret для стороннего хранилища продолжает работать, и объявлять для этого ничего не нужно.
Внутрикластерный кеш
При включённом storage.cache на каждом master-узле работает хранилище образов. Оно хранит блобы (файлы, из которых состоит образ) в директории /opt/deckhouse/registry. Один master-узел держит lease и наполняется из upstream’а. Остальные реплицируют данные из главной реплики (которая держит lease) заранее — чтобы потеря лидера не означала наполнение с нуля. Подробнее о выборе главной реплики — в разделе «Механизм выбора главной реплики».
Агенты обращаются к реплике по адресу узла, а не по имени сервиса registry.d8-system.svc:5001.
registry.d8-system.svc:5001 — это то, из чего строится каждая ссылка на образ в кластере, и то, с чем сопоставляется запрос. Но агент работает в сетевом пространстве хоста, где имя cluster DNS не разрешается.
Этот адрес (по которому агенты обращаются к реплике) вступает в силу в два шага, и порядок здесь важен. Узлы получают его сразу, как
только модуль начинает управлять путём загрузки образов, — тем же прогоном bashible, который
устанавливает агента. Ссылки на образы собственных компонентов платформы переезжают только
после того, как агент на каждом узле применил выданную ему конфигурацию: этот адрес не
разрешается ничем, кроме агента, поэтому перерендер кластера на него раньше указал бы каждой
нагрузке на то, что пока невозможно загрузить. До этого ссылки продолжают указывать на
хранилище образов, с которого кластер был установлен, — туда же они возвращаются, если модулю задать
Unmanaged или выключить его. Произошёл ли этот шаг, видно по наличию ConfigMap
registry-image-address в d8-system.
Через того же агента загружает образы и сам deckhouse-controller — по адресу 127.0.0.1:5001,
свой канал обновлений и принадлежащие ему источники модулей. Адрес другой, а агент тот же:
контроллер — это процесс, и ему нужно установить соединение, тогда как ссылка на образ
разрешается container runtime, которого drop-in перенаправляет на агента, поэтому она может
называть сервис, к которому никто не подключается. Именно это делает смену хранилища образов контейнеров одним
изменением: конфигурация правится в одном месте, агенты переконфигурируются, и за ними следуют
и то, что загружают узлы, и то, что загружает контроллер, — при этом ни один адрес хранилища образов контейнеров для
контроллера нигде не записан, а значит и не может остаться указывающим на прежний.
Используйте отдельные диски для данных кеша (/opt/deckhouse/registry) и для данных etcd. Общий диск приводит к деградации etcd во время наполнения кеша.
Механизм выбора главной реплики
Стать лидером может только та реплика, у которой уже есть весь ожидаемый набор образов. Реплика, которая держит lease в данный момент, уступает, когда ожидаемый набор появляется у другой. Реплика, не содержащая полного ожидаемого набора образов, не может стать лидером.
За счет этого исключаются проблемы при переходе кластера в air-gap. Если бы реплика, не содержащая полного ожидаемого набора образов, могла стать лидером, изолированный кластер мог бы застрять. Запрос при выполнении команды d8 mirror push попадал бы на неё (т.к. её выбрал ingress) и при этом:
- остальные реплики не могли бы реплицировать ожидаемый набор образов (так как на лидере его нет);
- лидер не мог бы получить полный набор образов (так как кластер изолирован).
Изолированные кластеры
Если в параметре primary.upstream не задан upstream, внутрикластерный кеш — единственный источник образов, а d8 mirror push — единственный путь
внутрь хранилища образов. Он приходит через эндпоинт публикации, который, помимо учётных данных, требует
клиентский сертификат от ingress. Это единственный путь, по которому образ можно заменить, и
утёкшего пароля не должно быть достаточно, чтобы им воспользоваться.
Этот эндпоинт существует только в изолированном кластере. Кластер, в котором включено кеширование образов, и который не изолирован, не получает доступной извне точки записи в хранилище образов, о которой не просил.
Требования к использованию модуля
Перед включением управления путями загрузки образов контейнеров с помощью модуля registry проверьте, что кластер соответствует следующим требованиям:
- На узлах используется containerd или containerd v2 — задаётся параметром
defaultCRIв ClusterConfiguration. - Кластер полностью управляется DP. В Managed Kubernetes модуль не работает.
- Внутрикластерный кеш использует диски master-узлов и поддерживается на статических кластерах.
Предыдущая реализация
Далее описана предыдущая реализация модуля, от которой в будущем планируется отказаться. Предыдущая реализация сохранена, потому что на ней всё ещё работают кластеры, и переход на новую конфигурацию — работа администратора, которую надо выполнить до обновления кластера, а не после.
Подготовьте кластер ДО обновления на этот релиз: обновление заблокировано, пока в кластере используется предыдущая реализация и модуль работает в режиме Proxy, Local, либо в режиме Direct без настроенного ModuleConfig registry.
При установке DP или обновлении на этот релиз не создаются объекты предыдущей реализации модуля. Переключение режимов предыдущей реализации модуля выполняет код предыдущего релиза — поэтому вся подготовка выполняется перед переходом на этот релиз. Подготовка имеет следующие особенности:
- Если в кластере используется модуль
registryв предыдущей реализации, работающий в режимеProxy, необходимо перевести его в режимUnmanaged. - Если кластер с модулем
registryв предыдущей реализации изолирован (модуль работает в режимеLocal), перевод сразу на режимUnmanagedне подходит. Для изолированных кластеров есть отдельная процедура, описанная в разделе «Как мигрировать изолированный кластер из режима Local». - Если в кластере используется модуль
registryв предыдущей реализации, работающий в режимеDirect, переключение режима не нужно — только конфигурация этого модуля, записанная до обновления. Его объекты сохраняются намеренно — предыдущий релиз помечает их так, чтобы они пережили его собственное удаление, — и продолжают обслуживать внутрикластерный адрес, через который загружают образы узлы, пока этот адрес не примет агент модуля. Порядок действий описан в разделе «Как мигрировать из режима Direct».
В предыдущей реализации модуля работа с хранилищем образов контейнеров настраивается не через настройки самого модуля, а через ModuleConfig deckhouse, и работает как конечный автомат с четырьмя режимами:
Direct— прямой доступ к внешнему хранилищу образов контейнеров по фиксированному адресуregistry.d8-system.svc:5001/system/deckhouse. Фиксированный адрес — это то, что позволяет избежать повторного скачивания образов Deckhouse и перезапуска компонентов при смене параметров хранилища образов контейнеров.Proxy— внутренний кеширующий прокси-registry на master-узлах, доступный по тому же фиксированному адресу; сокращает количество запросов к внешнему хранилищу образов контейнеров.Local— полная локальная копия хранилища образов контейнеров внутри кластера, для изолированных окружений.Unmanaged— без внутреннего хранилища образов контейнеров; кластер обращается к внешнему напрямую. Существует в настраиваемой форме, управляемой через ModuleConfigdeckhouse, и в устаревшей ненастраиваемой, задаваемой при установке.
Из перечисленных выше четырёх режимов предыдущей реализации модуля обновление на этот релиз переживают два, и по разным причинам. Unmanaged —
режим, объекты которого и так ничего не обслуживали, поэтому их удаление ничего не забирает, и
передача происходит сама. Direct переживает потому, что адрес, через который загружают образы
его узлы, обслуживает и модуль registry: предыдущий релиз помечает стоящие за этим адресом объекты
так, чтобы они пережили его собственное удаление, и они продолжают его обслуживать, пока адрес не
примет агент, — то есть такому кластеру нужна конфигурация этого модуля, а не переключение
режима. Оба пути описаны в разделе «Как устроена миграция на модуль registry». Обе
реализации никогда не управляют кластером одновременно: то, какая из них активна, определяет, что
вообще создаётся, поэтому состояния, в котором обе настраивают один узел, не существует.
Режимы Proxy и Local создают на узлах такое состояние, которое модуль в этом релизе не умеет корректно учитывать и переносить. Поэтому при использовании предыдущей реализации модуля в этих режимах его переводят в режим Unmanaged. А переключиться в него можно только на той версии DP, которая ещё содержит старую реализацию registry — то есть до обновления на версию, где этой реализации уже нет. Та же проверка, выполняемая изнутри кластера, при невозможности миграции вызывает появление алерта D8RegistryMigrationPreflightBlocked.
Ограничения переключения режимов
Ограничения по переключению режимов в предыдущей реализации модуля следующие:
- Смена параметров хранилища образов контейнеров и переключение режимов доступны только после полного завершения bootstrap-фазы.
- Для первого переключения выполните миграцию пользовательских конфигураций хранилища образов контейнеров — процедура описана в FAQ.
- Переключение в неконфигурируемый режим
Unmanagedдоступно только изUnmanaged. - Переключение между
LocalиProxyвозможно только через промежуточныйDirectилиUnmanaged. Например:Local→Direct→Proxy. - Bootstrap в режимах
LocalиProxyподдерживается только на статических кластерах.
Архитектура режима Direct
В режиме Direct запросы к хранилищу образов контейнеров обрабатываются без промежуточного кеширования. Запросы
CRI перенаправляются на основании конфигурации containerd. Компоненты, обращающиеся к хранилищу образов контейнеров
напрямую — operator-trivy, image-availability-exporter, deckhouse-controller и другие, —
идут через внутрикластерный прокси на master-узлах.

Архитектура режима Proxy
Рекомендуется использовать отдельные диски для хранения данных хранилища образов контейнеров (/opt/deckhouse/registry) и данных etcd. Использование одного диска может привести к деградации производительности etcd во время работы хранилища образов контейнеров.
Кеширующий прокси-registry запускается статическими подами на master-узлах и хранит кешируемые
данные в /opt/deckhouse/registry. Перед ним на каждом узле стоит балансировщик, и
конфигурация containerd указывает на этот балансировщик. Компоненты, обращающиеся к хранилищу образов контейнеров
напрямую, идут через кеширующий прокси-registry.

Архитектура режима Local
Рекомендуется использовать отдельные диски для хранения данных хранилища образов контейнеров (/opt/deckhouse/registry) и данных etcd. Использование одного диска может привести к деградации производительности etcd во время работы хранилища образов контейнеров.
Режим Local держит полную копию хранилища образов контейнеров внутри кластера, синхронизированную между репликами
на master-узлах и наполняемую утилитой
d8 командами
d8 mirror push/d8 mirror pull. В остальном работает так же, как кеширующий прокси.
