Есть момент в жизни кластера Kubernetes, когда папка с манифестами перестаёт помещаться в голове. Деплоймент, сервис, конфигмапа, секрет, ингресс, HPA - и это для одного приложения. Три окружения (dev, staging, prod) превращают коллекцию в хаотичную россыпь почти одинаковых файлов, где одна опечатка роняет продакшен. Helm пришёл именно в эту точку боли, предложив простую идею: упаковать все манифесты в один шаблонизируемый пакет, назвать его чартом и управлять им как целостной единицей.

Аналогия с apt или npm напрашивается сама. Только вместо двоичных пакетов или JavaScript-модулей здесь - комплекты YAML-манифестов с плейсхолдерами, которые рендерятся в момент установки. На сегодня через Helm так или иначе развёртываются приложения у подавляющего большинства команд, работающих с Kubernetes. Публичный Artifact Hub индексирует более пятнадцати тысяч чартов - от баз данных до полноценных стеков мониторинга.

Что такое чарт и какие концепции нужно уложить в голове сразу

Чарт - это каталог с предсказуемой структурой, где лежат шаблоны манифестов, значения по умолчанию, метаданные и зависимости. Три ключевых понятия, без которых дальше не получится: chart, release, repository. Чарт - сам пакет, инструкция с шаблонами. Релиз - конкретный экземпляр чарта, установленный в кластер. Один и тот же чарт nginx можно поставить дважды с разными именами релизов, получив два независимых развёртывания с разными конфигурациями. Репозиторий - сервер, где лежат упакованные чарты, доступные для скачивания.

Helm 3, который вышел в 2019 году, избавился от tiller - серверного компонента, крутившегося в кластере и требовавшего повышенных привилегий. Это была главная боль Helm 2 с точки зрения безопасности. Современный Helm полностью клиентский, всё общение с кластером идёт через kubeconfig, как у обычного kubectl. Осенью 2025 года вышел Helm 4 с поддержкой server-side apply, улучшенным отслеживанием готовности ресурсов через kstatus и новой плагинной системой на WebAssembly. При этом чарты Helm 3 полностью совместимы с Helm 4, и переезд не требует переписывания шаблонов.

Три способа поставить Helm на Linux и какой выбрать

Самый прямолинейный вариант - официальный скрипт установки. Он определяет архитектуру, скачивает подходящий бинарник, кладёт его в /usr/local/bin и делает исполняемым:

curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh

Такой способ подходит большинству ситуаций. Он работает на любом дистрибутиве Linux с curl, не требует пакетного менеджера и всегда тянет свежую стабильную версию.

Второй вариант - системный пакетный менеджер. На Debian и Ubuntu Helm доступен через собственный apt-репозиторий:

curl https://baltocdn.com/helm/signing.asc | sudo gpg --dearmor -o /usr/share/keyrings/helm.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt update
sudo apt install helm

Для RHEL, Fedora, Rocky и AlmaLinux пакет лежит в dnf:

sudo dnf install -y helm

Третий вариант - скачать бинарник вручную со страницы релизов на github.com/helm/helm и распаковать в нужное место. Этот путь оправдан только тогда, когда нужна конкретная версия, отсутствующая в репозиториях.

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

helm version

Вывод должен показать номер версии и дату сборки. Если в ответ приходит что-то про tiller, это старая Helm 2, её лучше удалить и поставить актуальный релиз. Полезная мелочь - автодополнение команд в bash:

echo 'source <(helm completion bash)' >> ~/.bashrc
source ~/.bashrc

Для zsh синтаксис почти идентичный. После этого Tab после helm начинает подсказывать команды, флаги и названия релизов.

Репозитории чартов и как научить Helm где искать готовое

Helm 3 не приходит с предустановленным репозиторием. Это сознательное решение - пусть пользователь сам выберет, какие источники подключать. Несколько репозиториев, с которых обычно начинают:

  1. Bitnami, один из крупнейших каталогов production-ready чартов для баз данных, кеширующих серверов, систем управления контентом
  2. Ingress-NGINX с официальным чартом одноимённого ingress-контроллера
  3. Jetstack с cert-manager для автоматической выдачи TLS-сертификатов
  4. Prometheus Community со стеком мониторинга
  5. Grafana с чартами Grafana, Loki, Tempo

Добавление и обновление индексов:

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo add jetstack https://charts.jetstack.io
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

Команда update тянет свежие индексы со всех подключённых источников. Выполнять её стоит перед поиском и установкой, иначе Helm будет оперировать устаревшим списком версий.

Поиск работает в двух режимах. helm search repo смотрит только в подключённые репозитории, helm search hub обращается к Artifact Hub и возвращает все публичные чарты:

helm search repo nginx
helm search hub wordpress

Fuzzy-поиск терпимо относится к частичным совпадениям, так что helm search repo kash найдёт чарт kashti. Удобно, когда не помнишь точное название.

Первая установка чарта и разбор того, что вообще произошло

Классический пример - развернуть nginx-ingress. Команда выглядит обманчиво просто:

helm install my-ingress ingress-nginx/ingress-nginx \
    --namespace ingress-nginx \
    --create-namespace

Первый аргумент my-ingress - имя релиза, которое будет идентифицировать эту конкретную установку. Второй - ссылка на чарт в формате репозиторий/имя. Флаг --create-namespace создаёт namespace, если его ещё нет. За кулисами Helm скачивает чарт, подставляет значения в шаблоны, рендерит финальные манифесты и применяет их через Kubernetes API.

Результат виден в списке релизов:

helm list -A

Флаг -A показывает релизы во всех namespace сразу. Для одного пространства имён работает helm list -n ingress-nginx. Статус конкретного релиза:

helm status my-ingress -n ingress-nginx

Команда выводит информацию о развёрнутых ресурсах, ревизии и заметки (NOTES), которые часто содержат полезные подсказки: как получить внешний адрес сервиса, какие учётные данные для доступа, куда смотреть логи.

Параметры чарта настраиваются двумя способами. Первый - флаги --set для точечных правок:

helm install my-ingress ingress-nginx/ingress-nginx \
    --namespace ingress-nginx --create-namespace \
    --set controller.replicaCount=3 \
    --set controller.service.type=LoadBalancer

Второй - файл values.yaml для серьёзных переопределений:

helm install my-ingress ingress-nginx/ingress-nginx \
    --namespace ingress-nginx --create-namespace \
    -f values-prod.yaml

Файл values.yaml в продакшене удобнее флагов --set. Он коммитится в git, ревьюится в pull-request, переиспользуется между окружениями. Флаги --set хороши для быстрых экспериментов, но плохо сохраняются в памяти и истории.

Увидеть, какие значения вообще принимает чарт, позволяет helm show values:

helm show values ingress-nginx/ingress-nginx > default-values.yaml

Файл с дефолтами можно внимательно прочитать, скопировать только нужные ключи и поменять их в собственном values.yaml. Оставлять в своём файле полный набор дефолтов не стоит - так меняющиеся в будущих версиях чарта значения перекроются старыми и поведение станет неожиданным.

Обновления, откаты и почему у релизов есть история

Helm ведёт историю каждого релиза. Новая установка - ревизия 1, каждое обновление через helm upgrade увеличивает номер:

helm upgrade my-ingress ingress-nginx/ingress-nginx \
    --namespace ingress-nginx \
    -f values-prod.yaml

Посмотреть историю:

helm history my-ingress -n ingress-nginx

Вывод показывает все ревизии с их статусами: deployed, superseded, failed. Откат к любой предыдущей ревизии - одна команда:

helm rollback my-ingress 2 -n ingress-nginx

Цифра 2 - номер ревизии, к которой возвращаемся. Откат создаёт новую ревизию с тем же состоянием, что и указанная. Это значит, что даже после отката история не теряется, и можно откатиться ещё раз, если новое решение тоже оказалось неудачным.

Шаблон helm upgrade --install - идеальная команда для CI/CD. Она устанавливает релиз, если его нет, или обновляет, если он уже существует. Флаг --atomic добавляет автоматический откат при сбое, --wait заставляет Helm дождаться готовности всех ресурсов:

helm upgrade --install my-app ./mychart \
    --namespace production \
    --create-namespace \
    -f values-prod.yaml \
    --wait \
    --timeout 5m \
    --atomic

Такой вызов идемпотентен, его можно запускать сколько угодно раз подряд с одинаковым результатом. Именно это нужно автоматизации - предсказуемое поведение без зависимости от текущего состояния.

Удаление релиза:

helm uninstall my-ingress -n ingress-nginx

Команда убирает все ресурсы, созданные чартом, и стирает запись о релизе. Флаг --keep-history сохранит историю, если хочется иметь возможность проверить, что именно было развёрнуто. Полное состояние кластера можно увидеть через kubectl get all -n namespace - если там после uninstall ничего не осталось от приложения, релиз удалён корректно.

Создание собственного чарта и что лежит внутри

Команда helm create порождает скелет:

helm create myapp

Результат - каталог myapp со структурой:

myapp/
├── Chart.yaml
├── values.yaml
├── charts/
├── templates/
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── hpa.yaml
│   ├── serviceaccount.yaml
│   ├── _helpers.tpl
│   └── NOTES.txt
└── .helmignore

Chart.yaml содержит метаданные: имя чарта, версии чарта (version) и приложения (appVersion), описание, поддерживаемые версии Kubernetes. values.yaml - значения по умолчанию, которые используются в шаблонах. Каталог templates хранит сами шаблоны с подстановками на языке Go templates. Файл _helpers.tpl вмещает общие функции, например генератор имён ресурсов или стандартный набор лейблов. NOTES.txt - тот самый текст, который выводится после helm install.

Шаблонный синтаксис выглядит так:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "myapp.fullname" . }}
  labels:
    {{- include "myapp.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "myapp.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "myapp.selectorLabels" . | nindent 8 }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
          ports:
            - containerPort: {{ .Values.service.port }}

Фигурные скобки с точкой - подстановка. .Values читает из values.yaml, .Chart из Chart.yaml, .Release содержит данные о текущем релизе. Конструкция include подключает именованные шаблоны из _helpers.tpl. Фильтр nindent добавляет отступы, чтобы вывод оставался валидным YAML.

Перед установкой полезно проверить, что чарт рендерится корректно:

helm lint ./myapp
helm template test-release ./myapp -f values.yaml

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

Несколько привычек, которые отличают уверенную работу от гадания

Опыт эксплуатации Helm накопил набор правил, которые проще принять, чем выводить заново через собственные ошибки. Версии чартов в продакшене всегда пинятся явно через --version, иначе завтрашний автоматический деплой может подтянуть несовместимое обновление из репозитория. Values-файлы версионируются в git рядом с остальной инфраструктурой как код, не в отдельных хранилищах и не в тикетной системе. Секреты не лежат в values.yaml открытым текстом - для них существуют sealed-secrets, external-secrets или sops с шифрованием.

Для managed-кластеров и CI/CD пайплайнов полезно завести отдельный values-файл на каждое окружение: values-dev.yaml, values-staging.yaml, values-prod.yaml. Общие значения живут в базовом values.yaml чарта, специфичные - в файлах окружений. Такая схема масштабируется от одного сервиса до целой платформы.

Helmfile - декларативная надстройка над Helm, которая описывает весь набор релизов в одном YAML-файле. Для команды, эксплуатирующей десяток чартов в нескольких окружениях, это качественный скачок в управляемости. Один helmfile.yaml описывает все приложения, их версии, зависимости и окружения, одна команда helmfile apply приводит кластер к нужному состоянию.

Helm - это инструмент, который превращает копипасту YAML-манифестов в структурированный процесс с версионированием, параметризацией и откатами. Начать стоит с установки клиента, подключения пары репозиториев, развёртывания готового чарта из Bitnami или Artifact Hub. Через несколько таких упражнений появляется чутьё, когда готовый чарт подходит, а когда проще написать свой. А дальше Helm становится частью ежедневного инструментария, такой же привычной, как kubectl, и таким же способом незаметно экономит часы времени, которые иначе ушли бы на борьбу с YAML.