Как подключить приватный registry

Для использования образов из приватного registry необходимо настроить аутентификацию. Доступно три варианта:

  1. Через конфигурацию узлов (NCI) — рекомендуемый способ для кластера: один объект NodeConfigItem (NCI) с разделом Container Runtime задаёт реестры контейнеров (и при необходимости учётные данные) для выбранных узлов. Оператор shturval-node-config применяет настройки на узлы без ручного входа по SSH. Подробнее о NCI — Конфигурация узлов (NCI).
  2. Ручное изменение конфигурации ContainerD на каждом узле — подходит при разовой настройке или когда NCI недоступен.
  3. ImagePullSecrets в неймспейсе — удобно с точки зрения безопасности и для разграничения по неймспейсам.

Сравнение способов аутентификации

Критерий Через NCI (Конфигурация узлов) Ручная правка ContainerD ImagePullSecrets
Кто настраивает Администратор кластера (один NCI) Администратор (на каждом узле по SSH) Администратор неймспейса или кластера
Область действия Все поды на выбранных узлах (по селектору NCI) Все поды на узле Только поды, использующие секрет
Сложность Один NCI на все узлы, применение оператором Правка конфига и перезапуск containerd на каждом узле Секрет в каждом неймспейсе
Безопасность Учётные данные в NCI (в кластере) Учётные данные в открытом виде в конфиге на узле Секрет хранится в Kubernetes (Secret)
Изменения Правка NCI, оператор обновит узлы Правка конфига и перезапуск на всех узлах Обновление Secret в нужных неймспейсах

Настройка через конфигурацию узлов (NCI)

Этот способ не требует входа на каждый узел: оператор конфигурации узлов (shturval-node-config) применит настройки Container Runtime к узлам по селектору из NCI.

  1. Откройте АдминистрированиеКонфигурация узловДобавить NCI (или импортируйте манифест через Импорт манифестов).
  2. Задайте название, приоритет и селектор узлов (например, kubernetes.io/os: linux для всех Linux-узлов или node-role.kubernetes.io/control-plane для Control Plane). Подробнее о селекторах — Конфигурация узлов (NCI).
  3. В списке разделов выберите Container Runtime.
  4. В блоке Container Runtime нажмите + и настройте реестр контейнеров:

Если вы используете зеркалирование r.shturval.tech:

  • Адрес внешнего репозитория - это адрес, который необходимо зеркалировать (к примеру, r.shturval.tech).
  • Адрес локального репозитория - это адрес корпоративного зеркала, откуда будут стягиваться образы (registry.corp.ltd).
  • Возможности (capabilities) — укажите resolve и pull для загрузки образов;
  • при необходимости укажите ключ авторизации в локальном репозитории (учётные данные для доступа к registry) в формате base64.
Пример подключения реестра образов с зеркалированием r.shturval.tech с помощью NCI
apiVersion: node.shturval.tech/v1beta2
kind: NodeConfigItem
metadata:
  name: private-registry
spec:
  nodeconfigselector:
    kubernetes.io/os: linux
  priority: 100
  runtimecfg:
    registries:
    - capabilities:
      - resolve
      - pull
      license: Basic YWRtaW46c2VjcmV0MTIz
      host: https://my-registry.corp:443
      name: r.shturval.tech

Если вы используете ваш реестр образов, в который требуется basic авторизация:

Пример подключения реестра образов с basic-авторизацией с помощью NCI
apiVersion: node.shturval.tech/v1beta2
kind: NodeConfigItem
metadata:
  name: private-registry
spec:
  nodeconfigselector:
    kubernetes.io/os: linux
  priority: 100
  runtimecfg:
    registries:
    - capabilities:
      - resolve
      - pull
      license: Basic YWRtaW46c2VjcmV0MTIz
      name: myprivateregistry.domain.ltd

Если вы используете ваш реестр образов, в который требуется авторизация с именем и паролем: На форме пропустите заполнение блока Конфигурация реестров контейнеров и добавьте плагин:

  • в поле путь введите полный путь к аутентификации реестра в формате containerd, например, “plugins.“io.containerd.grpc.v1.cri”.registry.configs.“myprivateregistry.domain.ltd”.auth”
  • добавьте параметры имени и пароля.
Пример подключения вашего реестра образов с помощью NCI
apiVersion: node.shturval.tech/v1beta2
kind: NodeConfigItem
metadata:
  name: private-registry
spec:
  nodeconfigselector:
    kubernetes.io/os: linux
  priority: 100
  runtimecfg:
    configSections:
      - exist: true
        params:
          - exist: true
            key: username
            value: myLogin
          - exist: true
            key: password
            value: myPassword
        path: plugins."io.containerd.grpc.v1.cri".registry.configs."myprivateregistry.domain.ltd".auth

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

  1. Нажмите Добавить, заполните остальные шаги и Завершить.

NCI будет применён к выбранным узлам оператором. Перезапуск containerd на узлах выполняется автоматически при применении конфигурации.

Учётные данные (логин/пароль) при необходимости задаются в форме NCI в блоке Container Runtime — поле «Авторизация для репозитория». Для применения этого NCI создайте объект через интерфейс Конфигурация узлов или добавьте в манифест соответствующие поля по документации API NodeConfigItem.

После создания или изменения NCI проверьте применение на узлах: Узлы → выберите узел → вкладка Конфигурация узла (список применённых NCI и статус).

Настройка через конфигурацию ContainerD вручную

На каждом узле кластера нужно отредактировать конфиг ContainerD (обычно путь /etc/containerd/config.toml).

  1. Найдите в файле секцию:
    [plugins."io.containerd.grpc.v1.cri".registry.configs]
    
  2. Добавьте под ней блок с адресом вашего registry и учётными данными:
Пример — иллюстрация
[plugins."io.containerd.grpc.v1.cri".registry.configs."myprivateregistry.domain.ltd".auth]
username = "myLogin"
password = "myPassword"
  1. Сохраните файл и перезапустите ContainerD на узле:
    sudo systemctl restart containerd
    

При обновлении или смене registry потребуется снова отредактировать конфиг и перезапустить ContainerD на всех узлах.

Настройка через ImagePullSecrets

Создайте в нужном неймспейсе Secret типа kubernetes.io/dockerconfigjson с данными для входа в registry. Затем укажите этот секрет в подах (или в defaultServiceAccount неймспейса) как imagePullSecrets.

1. Подготовка данных для аутентификации

Создайте JSON-файл с полем auths, в котором указаны адрес registry и учётные данные. Поле auth — строка base64 от username:password.

Пример JSON
{
  "auths": {
    "my-registry.example:5000": {
      "username": "tiger",
      "password": "pass1234",
      "email": "tiger@acme.example",
      "auth": "dGlnZXI6cGFzczEyMzQ="
    }

2. Создание Secret в кластере

Через веб-интерфейс: выберите кластер → нужный неймспейс → ХранилищеSecrets → создайте Secret с типом dockerconfigjson. В блоке Ключи добавьте ключ (например, .dockerconfigjson) и загрузите или вставьте содержимое JSON-файла с данными аутентификации.

Через kubectl:

Команда — иллюстрация
kubectl create secret docker-registry <имя-секрета> \
  --docker-server=my-registry.example:5000 \
  --docker-username=Username \
  --docker-password=Pass1234 \
  --docker-email=user@example.com \
  -n <имя-неймспейса>

Подставьте свои значения вместо <имя-секрета>, <имя-неймспейса> и учётных данных registry.

Эквивалентный Secret можно описать манифестом:

Пример Secret
apiVersion: v1
kind: Secret
metadata:
  name: external-registry-secret
  namespace: my-namespace
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: <base64-encoded-docker-config>

3. Использование секрета в нагрузках

При создании нагрузки (Deployment, Pod и т.п.) в поле Секреты образов (ImagePullSecrets) укажите созданный секрет. Тогда все поды этой нагрузки будут использовать его для pull образов из приватного registry.

В манифесте Pod или контроллера укажите секрет в поле imagePullSecrets:

Пример фрагмента манифеста
spec:
  imagePullSecrets:
  - name: regcred
  containers:
  - name: app
    image: registry.example.shturval.link/my-app:v1.0.0

Чтобы образы из этого registry тянулись по умолчанию во всём неймспейсе, добавьте imagePullSecrets в ServiceAccount по умолчанию этого неймспейса.

Пример ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: default
  namespace: my-namespace
imagePullSecrets:
- name: regcred

Обратите внимание! секрет действует только в том неймспейсе, где создан. Для использования того же registry в другом неймспейсе создайте там отдельный Secret (или настройте кластерный механизм распространения секретов, если он у вас есть).

Если под переходит в ImagePullBackOff или ErrImagePull, проверьте имя образа и тег, доступность registry из кластера, права на образ и корректность imagePullSecrets. Подробные действия см. в разделе Траблшутинг нагрузок.

Аутентификация при push образов из CI/CD

Для публикации образов из pipeline выполните вход в registry учётной записью CI/CD и отправьте образ в нужный репозиторий.

Для ручной публикации образов выполните вход в registry перед docker push:

docker login registry.example.shturval.link -u <username> -p <password>

Пример GitLab CI

build_and_push:
  stage: build
  script:
    - docker login $REGISTRY_URL -u $REGISTRY_USER -p $REGISTRY_PASSWORD
    - docker build -t $REGISTRY_URL/my-app:$CI_COMMIT_SHA .
    - docker push $REGISTRY_URL/my-app:$CI_COMMIT_SHA
  variables:
    REGISTRY_URL: "registry.example.shturval.link"
    REGISTRY_USER: "ci-user"
    REGISTRY_PASSWORD: "${CI_REGISTRY_PASSWORD}"

Пример GitHub Actions

- name: Build and push
  uses: docker/build-push-action@v2
  with:
    push: true
    tags: registry.example.shturval.link/my-app:${{ github.sha }}
    registry: registry.example.shturval.link
    username: ${{ secrets.REGISTRY_USERNAME }}
    password: ${{ secrets.REGISTRY_PASSWORD }}