ADG Оставить заявку
Блог DevOps 5 мин чтения

Helm 3.3 и OCI-реестры: переводим чарты в Harbor с semver-стратегией для monorepo

Helm 3.3 вышел с экспериментальной поддержкой OCI-реестров. Переносим чарты в Harbor: версионирование, сканирование Trivy и интеграция с GitLab CI для зависимых чартов в monorepo.

Контекст момента

Helm 3.3 выходит с экспериментальной поддержкой OCI-реестров для хранения чартов как стандартных артефактов

Helm 3.3 вышел на прошлой неделе, и среди нескольких технических изменений нас сразу зацепила одна вещь: экспериментальная поддержка OCI-реестров через переменную HELM_EXPERIMENTAL_OCI=1. Идея простая - чарты хранятся в том же реестре что и образы, по тому же протоколу, со всеми вытекающими: единый access control, сканирование на уязвимости, стандартный workflow для продвижения артефактов. У нас Harbor уже стоит в инфраструктуре, так что решили проверить насколько это работоспособно в реальных условиях.

Откуда берётся проблема с chartmuseum

До этого мы держали чарты в chartmuseum. Схема рабочая, но обрастает вопросами: отдельный сервис, отдельный access control, отдельный lifecycle. Когда разработчик пушит образ в Harbor и чарт в chartmuseum - это два разных места с разными правилами. Когда security-команда хочет понять что задеплоено - смотреть нужно в двух местах.

Второй момент - в монорепозитории с несколькими сервисами и зависимыми чартами semver-стратегия быстро становится нетривиальной задачей. Chartmuseum не мешает вам пушить одну и ту же версию дважды - если не следить, получите неконсистентное состояние.

Harbor как OCI-реестр для чартов

Harbor 2.x поддерживает OCI Distribution Spec, что делает его совместимым с новым Helm 3.3 API. Включение простое:

export HELM_EXPERIMENTAL_OCI=1
helm registry login harbor.company.com \
  --username robot\$ci-helm \
  --password "$HARBOR_TOKEN"

Пуш чарта выглядит так:

helm chart save ./charts/myapp harbor.company.com/charts/myapp:1.4.2
helm chart push harbor.company.com/charts/myapp:1.4.2

Пул и установка:

helm chart pull harbor.company.com/charts/myapp:1.4.2
helm chart export harbor.company.com/charts/myapp:1.4.2 --destination /tmp/charts
helm upgrade --install myapp /tmp/charts/myapp

Интерфейс чуть многословнее старого helm repo add + helm install, но в CI это скрывается в скриптах.

Trivy и сканирование чартов

Вот где OCI-подход даёт практический плюс. Harbor умеет запускать Trivy не только на образы, но и на чарты в OCI-формате. При пуше чарта в репозиторий с настроенной политикой сканирования Harbor автоматически проверяет его содержимое.

Что именно сканируется в чарте через Trivy: образы, которые чарт объявляет в values.yaml в полях image.repository + image.tag. Trivy вытаскивает эти ссылки и проверяет их по своим базам CVE. Работает не для всех шаблонов одинаково - если образ задаётся через сложный lookup или условный хелпер, Trivy его может пропустить. Но для стандартной структуры values.yaml с явными полями - работает.

Политику блокировки деплоя при CRITICAL-уязвимостях мы пока не включали на все проекты - слишком много легаси-образов с хвостами. Включили как advisory: Harbor помечает чарт статусом сканирования, CI читает этот статус и пишет в отчёт.

Semver-стратегия для зависимых чартов в monorepo

Здесь самое интересное по части process. У нас monorepo с тремя сервисами: api, worker, frontend. Плюс общий umbrella-чарт, который зависит от всех трёх через Chart.yaml:

dependencies:
  - name: api
    version: "~1.4.0"
    repository: "oci://harbor.company.com/charts"
  - name: worker
    version: "~2.1.0"
    repository: "oci://harbor.company.com/charts"
  - name: frontend
    version: "~3.0.0"
    repository: "oci://harbor.company.com/charts"

Правила, которые мы выработали для команды:

Патч-версия (1.4.x) - изменения только в шаблонах без смены контракта: добавление аннотации, правка resource limits, новый sidecar без нового параметра в values.

Минорная версия (1.x.0) - новый опциональный параметр в values с дефолтным значением. Обратная совместимость сохранена - старый values.yaml без нового параметра работает.

Мажорная версия (x.0.0) - переименование параметра, удаление параметра, смена структуры values. Требует явного обновления зависимого umbrella-чарта.

В GitLab CI версию чарта мы выводим из git tag. Tag api/v1.4.2 триггерит pipeline только для api-чарта с версией 1.4.2. Umbrella-чарт версионируется отдельно и собирается при изменении любого из дочерних - там CI сам обновляет Chart.lock через helm dependency update.

build-chart:
  stage: package
  script:
    - export HELM_EXPERIMENTAL_OCI=1
    - CHART_VERSION=$(echo $CI_COMMIT_TAG | sed 's|.*/v||')
    - CHART_NAME=$(echo $CI_COMMIT_TAG | cut -d/ -f1)
    - helm chart save ./charts/$CHART_NAME harbor.company.com/charts/$CHART_NAME:$CHART_VERSION
    - helm chart push harbor.company.com/charts/$CHART_NAME:$CHART_VERSION
  only:
    - tags

Тильда в ~1.4.0 в dependencies означает «любая патч-версия из 1.4.x» - это позволяет автоматически подтягивать патч-обновления без ручного bump umbrella-чарта. Минорные и мажорные требуют явного изменения.

Что работает, что нет

OCI-поддержка в Helm 3.3 помечена как экспериментальная, и это честная маркировка. helm search по OCI-реестру не работает - нельзя сделать helm search repo и увидеть список чартов. Harbor UI показывает артефакты, но через свой интерфейс. Для discovery в CI это не проблема - версии прибиты явно. Но для операционного обзора «что вообще есть в реестре» нужен либо Harbor API, либо отдельный скрипт.

helm dependency update с OCI-зависимостями работает с экспериментальным флагом. На CI-раннерах нужно убедиться что переменная пробрасывается в каждый шаг где используется helm.

Где сейчас

Один production-проект переведён, несколько в процессе. Единый реестр для образов и чартов в Harbor под managed-сопровождением упрощает audit trail: когда нужно понять что именно задеплоено в конкретный момент - смотришь в одно место. Trivy-сканирование настроено, CRITICAL-блокировку добавим после разбора хвостов в легаси-образах.

Semver-стратегия пока живёт в wiki. Задача следующего месяца - сделать CI-проверку что версия чарта в теге соответствует version в Chart.yaml, иначе это регулярно расходится при ручных коммитах.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.