Helm 3 OCI Registry: храним чарты там же, где образы
Helm 3.5 вывел поддержку OCI Registry из эксперимента в рабочий режим. Переносим внутренний chart repo с ChartMuseum на Harbor и разбираем, что реально поменялось.
Helm 3.5+ выводит поддержку OCI Registry для хранения чартов из экспериментального статуса в стабильный
У нас давно сидел ChartMuseum для внутренних Helm-чартов - поставили когда-то, прижилось. Работал нормально: push через helm-push плагин, версионирование, простой API. Но рядом всегда стоял Harbor как container registry для образов. И каждый раз при настройке нового проекта нужно было помнить два endpoint - один для образов, другой для чартов. Плюс две точки доступа, два набора credentials, два места для мониторинга доступности.
Когда Helm 3.5 сделал OCI Registry поддержку официально рабочей - убрал флаг HELM_EXPERIMENTAL_OCI=1 из обязательных - мы решили проверить, не пора ли убрать ChartMuseum совсем.
Что изменилось в 3.5
OCI-поддержка в Helm появилась раньше - экспериментально. Но со статусом «эксперимент» в продакшне жить неудобно: API мог меняться, поведение было не до конца предсказуемым. В 3.5 эту метку сняли. Команды helm pull и helm registry теперь работают с OCI-совместимым registry без флага HELM_EXPERIMENTAL_OCI=1. Push чартов в OCI пока доступен через тот же механизм с флагом.
Harbor с версии 2.0 поддерживает хранение OCI-артефактов - то есть не только Docker-образов, но и всего, что соответствует спецификации OCI Distribution. Helm-чарт как раз такой артефакт. Репозиторий в Harbor с типом helm-charts делает чарты видимыми в UI с именами и версиями - не просто blob.
Переезд с ChartMuseum
Наш ChartMuseum хранил несколько десятков чартов разных версий. Задача - перенести их все в Harbor, не потеряв историю версий.
Алгоритм оказался прямолинейным. Пуллим всё локально через старый клиент, потом пушим в OCI:
# Получаем список чартов и версий из ChartMuseum
curl https://charts.internal.example.com/api/charts | \
jq -r 'to_entries[] | .key as $name | .value[] | "\($name) \(.version)"' \
> charts-list.txt
# Для каждого чарта - pull и push в Harbor
while read name version; do
helm pull "cm://charts.internal.example.com/${name}" --version "${version}"
helm push "${name}-${version}.tgz" "oci://harbor.internal.example.com/helm-charts"
rm "${name}-${version}.tgz"
done < charts-list.txt
cm:// - это схема из плагина helm-push для ChartMuseum. В новом мире такая схема не нужна: OCI registry адресуется через oci://.
Логин в Harbor через Helm - отдельная команда перед push:
helm registry login harbor.internal.example.com \
--username robot\$helm-push \
--password <token>
Для CI используем robot account в Harbor с правами только на push в нужный проект. Credentials идут через переменные CI, не хардкодятся.
Как это выглядит в работе
Pull чарта для деплоя:
helm pull oci://harbor.internal.example.com/helm-charts/myapp --version 1.4.2
Или напрямую в helm upgrade:
helm upgrade --install myapp \
oci://harbor.internal.example.com/helm-charts/myapp \
--version 1.4.2 \
--values values-prod.yaml
Это работает. Никакого helm repo add перед этим - OCI-ссылка самодостаточна.
В Harbor в разделе проекта чарты видны как артефакты: имя, тег-версия, размер, дата push. Можно смотреть историю версий конкретного чарта прямо в UI, без отдельных инструментов.
Что реально поменялось для нас
Один registry вместо двух. Теперь у нас один endpoint для образов и чартов, одни credentials для доступа, один RBAC в Harbor. В рамках managed-сопровождения это сокращает количество сервисов, которые нужно мониторить и обслуживать.
Версионирование работает нативно. Версия чарта = тег в OCI-репозитории. Нет дополнительного слоя абстракции в ChartMuseum с его собственной БД индекса. Потерять индекс (как это иногда случалось при проблемах с ChartMuseum) уже нельзя - метаданные хранит сам registry.
Dependency через OCI. Pull чартов-зависимостей из OCI-репозиторий доступен через helm pull oci://... с последующим размещением в charts/. Прямая запись oci:// scheme в repository в Chart.yaml пока не поддерживается - зависимости всё ещё требуют helm repo add или ручного размещения.
Подписи. Harbor поддерживает Notary для подписи OCI-артефактов. ChartMuseum такого не умел из коробки. Пока мы это не использовали в продакшне, но опция есть.
Что не так гладко
Плагин helm-push для ChartMuseum и команда helm push для OCI (через флаг HELM_EXPERIMENTAL_OCI=1) - разные команды с немного разным синтаксисом. Если в команде кто-то привык к плагину - нужно переучиваться. Мелочь, но на это уходит время при первом столкновении.
helm search для OCI registry не работает так же как для обычных helm-репозиториев - нет helm search repo с полнотекстовым поиском. Список чартов смотришь в Harbor UI или через OCI Distribution API напрямую. Для небольшого количества чартов это не проблема, для большого каталога - может раздражать.
ChartMuseum мы пока оставили в режиме read-only на пару недель - на случай если что-то упустили при переносе. Но уже сейчас понятно, что новые чарты пойдут только в Harbor, а ChartMuseum отключим в апреле.