Helm-чарт: от пользователя к создателю
Helm — это не просто команда для установки приложений в Kubernetes. Это инструмент управления приложениями, где чарт является его фундаментом. Понимание внутренней структуры чарта — это ключ к переходу от пассивного использования готовых решений к осмысленному созданию и кастомизации. Чарт — это единица управления, которая инкапсулирует версионность, конфигурацию и зависимости вашего приложения.
В этом руководстве вы получите не только теорию, но и практические навыки создания production-ready чартов. Вы узнаете:
- Как устроены ключевые файлы: Chart.yaml, values.yaml и templates/.
- Как создать с нуля рабочий чарт для Nginx.
- Как строить сложные структуры values.yaml для реальных приложений.
- Лучшие практики для production: валидация, управление зависимостями, организация шаблонов.
- Частые ошибки DevOps инженеров и их решения.
- Пример реального чарта с зависимостями (Nginx + Redis).
Цель этого руководства — не просто перечислить файлы, а показать систему, где каждый элемент играет свою роль. К концу статьи у вас будет не только теоретическое понимание, но и ваш собственный минимальный, но полностью рабочий чарт. Это основа для решения любых задач с Helm, от простой установки до создания production-ready развертываний.
Анатомия чарта: разбираем структуру директории
Стандартная структура директории Helm-чарта, созданная командой helm create, выглядит следующим образом:
my-chart/
├── Chart.yaml
├── values.yaml
├── charts/
├── templates/
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── NOTES.txt
│ └── tests/
└── .helmignore
Каждый элемент имеет строгое назначение:
- Chart.yaml: Паспорт чарта, содержащий метаданные.
- values.yaml: Центральный узел конфигурации, значения по умолчанию.
- charts/: Директория для зависимостей (subcharts).
- templates/: Сердце чарта — шаблоны манифестов Kubernetes.
- .helmignore: Аналог .gitignore, исключает файлы из упаковки чарта.
Chart.yaml: паспорт вашего приложения
Файл Chart.yaml — это не формальность, а критически важные метаданные. Он используется репозиториями для индексации, Helm CLI для управления зависимостями и семантического версионирования.
Ключевые поля:
- apiVersion: Версия API Helm (v2 для Helm 2, v1 для Helm 3). Для Helm 3 используйте
apiVersion: v2. - name: Имя чарта. Должно быть уникальным в репозитории.
- version: Версия чарта по правилам семантического версионирования (например, 1.0.0). Именно эта версия используется для управления релизами.
- appVersion: Версия приложения, которое упаковывает чарт (например, 1.21.1 для nginx). Это информационное поле.
- description: Краткое описание чарта.
- type: Обычно
application. Может бытьlibraryдля чартов-библиотек.
Особое внимание заслуживает секция dependencies. Здесь описываются другие чарты, от которых зависит ваш. Зависимости скачиваются и помещаются в директорию charts/.
# Пример расширенного Chart.yaml
apiVersion: v2
name: my-nginx
version: surveyed
appVersion: "1.21.1"
description: A minimal Nginx deployment chart.
type: application
dependencies:
- name: redis
version: "~12.0.0"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled
values.yaml: центральный узел конфигурации и сложные структуры
Файл values.yaml — это главный инструмент для кастомизации чарта без правки шаблонов. Он реализует принцип разделения кода (шаблоны) и конфигурации (значения). Пользователь может переопределять эти значения через собственный файл values или флаг --set.
Структура данных — стандартный YAML: словари, списки, простые значения.
# Пример values.yaml с комментариями
# Количество реплик пода
replicaCount: 1
# Настройки образа контейнера
image:
repository: nginx
tag: "1.21.1"
pullPolicy: IfNotPresent
# Настройки сервиса
service:
type: ClusterIP
port: 80
# Включение Ingress
ingress:
enabled: false
className: "nginx"
hosts:
- host: chart-example.local
paths:
- path: /
pathType: ImplementationSpecific
Правильно документированный values.yaml с комментариями — признак профессионального чарта, который легко адаптировать под свою среду.
Работа со сложными структурами в values.yaml
В production-чартах часто используются вложенные объекты и массивы. Вот как правильно с ними работать:
# Пример сложной структуры values.yaml
config:
# Массив строковых конфигураций
envVars:
- name: LOG_LEVEL
value: "INFO"
- name: CACHE_SIZE
value: "256"
# Вложенный объект с настройками
database:
host: "db-primary"
port: 5432
ssl: true
# Массив объектов для sidecar-контейнеров
sidecars:
- name: log-shipper
image: "fluentd:latest"
enabled: true
- name: metrics-agent
image: "prometheus/node-exporter"
enabled: false
# Использование в шаблоне:
# Для массива envVars
{{- range .Values.config.envVars }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}
# Для вложенного объекта
databaseUrl: "postgresql://{{ .Values.config.database.host }}:{{ .Values.config.database.port }}"
# Для условного включения sidecar
{{- range .Values.config.sidecars }}
{{- if .enabled }}
- name: {{ .name }}
image: {{ .image }}
{{- end }}
{{- end }}
Если вы хотите глубже разобраться в инструментах конфигурации в Kubernetes, рекомендуем наше практическое сравнение CRD и ConfigMap.
Директория templates/: где манифесты обретают форму
Файлы в директории templates/ — это не готовые манифесты Kubernetes, а их шаблоны, написанные на языке Go Templates. «Магия» Helm заключается в том, что движок шаблонов подставляет значения из values.yaml и других источников в эти шаблоны, генерируя итоговые YAML-манифесты для применения в кластере.
Типовой набор включает:
deployment.yaml: Шаблон для развертывания (Deployment).service.yaml: Шаблон для сервиса (Service).ingress.yaml: Шаблон для входящего трафика (Ingress).configmap.yaml,secret.yaml: Для конфигураций и секретов.NOTES.txt: Шаблон для вывода кастомного сообщения после установки.
Ключевые концепции, которые используются в шаблонах:
{{ .Values.replicaCount }}— подстановка значения из файла values.yaml.{{ .Release.Name }}— имя текущего релиза Helm.{{ .Chart.Name }}— имя чарта из Chart.yaml.
Создаем свой первый чарт: практика на примере Nginx
Перейдем от теории к практике. Создадим минимальный, но полностью функциональный чарт для развертывания Nginx.
- Создаем базовую структуру и чистим лишнее:
helm create my-nginx cd my-nginx # Удаляем лишние файлы для чистоты примера rm -rf templates/* - Редактируем Chart.yaml:
Упростим файл, оставив только самое необходимое.
apiVersion: v2 name: my-nginx version: 0.1.0 description: A minimal Nginx Helm chart type: application - Настраиваем values.yaml:
Оставим только ключевые параметры для образа Nginx и сервиса.
replicaCount: 1 image: repository: nginx tag: "stable" pullPolicy: IfNotPresent service: type: ClusterIP port: 80 - Создаем основные шаблоны:
В директории
templates/создадим два файла:deployment.yamlиservice.yaml.
Пишем и понимаем шаблоны: от переменных к функциям
Давайте детально разберем синтаксис на примере шаблона deployment.yaml.
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-nginx
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.port }}
Разбор элементов:
- Подстановки:
{{ .Values.replicaCount }}заменится на число1из values.yaml. - Конкатенация строк:
"{{ .Values.image.repository }}:{{ .Values.image.tag }}"сформирует строку"nginx:stable". - Использование объектов:
{{ .Release.Name }}гарантирует уникальность имени развертывания для каждого релиза Helm.
Шаблоны поддерживают управляющие структуры:
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
...
{{- end -}}
И функции с пайплайнами (конвейерами):
# Функция default задает значение по умолчанию, quote — оборачивает в кавычки.
name: {{ .Values.name | default .Chart.Name | quote }}
Для управления сложными приложениями часто требуется оркестрация контейнеров. Если вы рассматриваете альтернативы Kubernetes, вам может быть полезно практическое руководство по Docker Swarm.
Проверка и установка: не нажимаем Enter без проверки
Перед установкой чарта в кластер обязательна его верификация. Это предотвратит ошибки и потенциальные сбои.
- Проверка синтаксиса и структуры:
Команда проверит корректность Chart.yaml и шаблонов.helm lint . - Рендеринг итоговых манифестов (отладка):
Или с имитацией установки:helm template . --debug
Эти команды покажут, какие именно YAML-файлы будут отправлены в кластер. Это лучший способ проверить логику подстановок и условных операторов.helm install my-release . --dry-run --debug - Установка в тестовый неймспейс:
Если все проверки прошли успешно, можно выполнять установку.helm install my-nginx-release . --namespace test-namespace --create-namespace
Best Practices для production чартов
Создание чартов для production требует соблюдения определенных практик, которые повышают надежность, безопасность и удобство поддержки.
Организация шаблонов и использование _helpers.tpl
Для сложных чартов рекомендуется выносить повторяющуюся логику в файл-помощник templates/_helpers.tpl:
{{/*
Генерация стандартных лейблов для всех ресурсов чарта.
*/}}
{{- define "my-nginx.labels" -}}
app: nginx
chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
release: {{ .Release.Name }}
heritage: Helm
{{- end -}}
{{/*
Генерация селектора для Deployment.
*/}}
{{- define "my-nginx.selectorLabels" -}}
app: nginx
release: {{ .Release.Name }}
{{- end -}}
{{/*
Создание полного имени образа с возможностью переопределения репозитория.
*/}}
{{- define "my-nginx.image" -}}
{{- $registry := .Values.image.registry | default "" -}}
{{- $repository := .Values.image.repository -}}
{{- $tag := .Values.image.tag | default .Chart.AppVersion -}}
{{- if $registry -}}
{{ $registry }}/{{ $repository }}:{{ $tag }}
{{- else -}}
{{ $repository }}:{{ $tag }}
{{- end -}}
{{- end -}}
Использование в шаблонах:
metadata:
labels:
{{- include "my-nginx.labels" . | nindent 4 }}
selector:
matchLabels:
{{- include "my-nginx.selectorLabels" . | nindent 6 }}
containers:
- image: {{ include "my-nginx.image" . }}
Управление зависимостями и версионирование
Для production важно четко управлять зависимостями:
- Всегда указывайте точные версии зависимостей или используйте диапазоны с семантическим версионированием.
- Используйте
helm dependency updateдля генерацииChart.lock, который фиксирует версии. - Проверяйте обновления зависимостей регулярно с помощью
helm dependency list.
Валидация значений с помощью JSON Schema
Файл values.schema.json позволяет валидировать входные данные до рендеринга шаблонов:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"replicaCount": {
"type": "integer",
"minimum": 1,
"maximum": 10,
"description": "Количество реплик пода"
},
"image": {
"type": "object",
"properties": {
"repository": {
"type": "string",
"pattern": "^[a-zA-Z0-9./_-]+$"
},
"tag": {
"type": "string",
"default": "latest"
}
},
"required": ["repository"]
}
},
"required": ["replicaCount", "image"]
}
Частые ошибки и их решение
При работе с Helm-чартами DevOps инженеры часто сталкиваются с типовыми проблемами. Вот наиболее распространенные из них и способы решения.
Ошибки в условных операторах и функциях
Проблема: Неправильное использование функций default или empty.
# НЕПРАВИЛЬНО: default не сработает, если ключ существует, но имеет значение false/0/""
{{ .Values.feature.enabled | default true }}
# ПРАВИЛЬНО: проверка на существование ключа
{{- if hasKey .Values "feature" }}
{{ .Values.feature.enabled | default true }}
{{- else }}
true
{{- end }}
Проблема: Ошибки в условных операторах с вложенными структурами.
# НЕПРАВИЛЬНО: вызовет ошибку, если .Values.ingress не определен
{{- if .Values.ingress.enabled }}
# ПРАВИЛЬНО: безопасная проверка
{{- if and .Values.ingress .Values.ingress.enabled }}
Проблемы с рендерингом и whitespace
Проблема: Лишние пустые строки в сгенерированных YAML-файлах.
# НЕПРАВИЛЬНО: оставляет пустые строки
{{ if .Values.debug }}
env:
- name: DEBUG
value: "true"
{{ end }}
# ПРАВИЛЬНО: использование дефисов для контроля whitespace
{{- if .Values.debug }}
env:
- name: DEBUG
value: "true"
{{- end }}
Ошибки, выявляемые helm lint
Команда helm lint помогает находить распространенные проблемы:
- "chart metadata is missing" — проверьте, что все обязательные поля в Chart.yaml заполнены.
- "unable to parse YAML" — проверьте синтаксис YAML в шаблонах, особенно отступы.
- "icon is recommended" — добавьте поле icon в Chart.yaml для лучшего отображения в репозиториях.
Проблемы с зависимостями
Проблема: Зависимости не обновляются или устанавливаются неправильные версии.
Решение:
- Всегда запускайте
helm dependency updateпосле изменения dependencies в Chart.yaml. - Проверяйте содержимое директории
charts/— там должны быть распакованные чарты. - Используйте
helm dependency buildдля пересборки зависимостей из lock-файла.
Если вы столкнулись с проблемами в работе пользовательских ресурсов (CR), которые часто используются в сложных чартах, вам поможет полное руководство по диагностике Custom Resources.
Пример реального чарта с зависимостями
Рассмотрим пример чарта для веб-приложения с Nginx и Redis в качестве кэша.
Chart.yaml с зависимостями
apiVersion: v2
name: web-app
version: 1.0.0
appVersion: "2.5.0"
description: Web application with Nginx and Redis cache
type: application
dependencies:
- name: redis
version: "~12.0.0"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled
tags:
- cache
- name: postgresql
version: "^11.0.0"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
tags:
- database
Values.yaml с конфигурацией зависимостей
# Основное приложение
replicaCount: 2
image:
repository: myapp/web
tag: "2.5.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 8080
# Redis зависимость
redis:
enabled: true
architecture: standalone
auth:
enabled: false
master:
persistence:
enabled: false
# PostgreSQL зависимость
postgresql:
enabled: true
auth:
username: appuser
password: ""
database: appdb
primary:
persistence:
enabled: false
# Конфигурация приложения
appConfig:
cache:
host: "{{ .Release.Name }}-redis-master"
port: 6379
database:
host: "{{ .Release.Name }}-postgresql"
port: 5432
Шаблон ConfigMap с использованием зависимостей
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-config
labels:
{{- include "web-app.labels" . | nindent 4 }}
data:
app.properties: |
# Конфигурация кэша
cache.host={{ .Values.appConfig.cache.host }}
cache.port={{ .Values.appConfig.cache.port }}
# Конфигурация базы данных
db.host={{ .Values.appConfig.database.host }}
db.port={{ .Values.appConfig.database.port }}
db.name={{ .Values.postgresql.auth.database }}
db.user={{ .Values.postgresql.auth.username }}
# Условная конфигурация
{{- if .Values.redis.enabled }}
cache.enabled=true
{{- else }}
cache.enabled=false
{{- end }}
От простого к сложному: элементы для поддерживаемых чартов
Минимальный рабочий чарт — это начало. Для создания профессиональных, удобных для командной работы и повторного использования чартов, рекомендуется добавить следующие элементы:
- Файлы-помощники (
templates/_helpers.tpl): Здесь выносят сложную логику шаблонов и определяют общие метки или функции. Например, определение стандартных лейблов чарта.
Затем в шаблоне используете{{- define "my-nginx.labels" -}} app: nginx chart: {{ .Chart.Name }}-{{ .Chart.Version }} release: {{ .Release.Name }} {{- end -}}{{ include "my-nginx.labels" . }}. - Файл
NOTES.txt: Шаблон вtemplates/NOTES.txt. Его содержимое выводится после успешной установкиhelm install. Идеально для подсказок пользователю: как получить доступ к приложению, проверить статус. - JSON-схема для values (
values.schema.json): Позволяет валидировать файлvalues.yamlна соответствие структуре и типам данных до рендеринга шаблонов. Защищает от опечаток и некорректных конфигураций. - Файл
Chart.lock: Автоматически генерируется командойhelm dependency update. Фиксирует точные версии зависимостей, обеспечивая воспроизводимость сборки. - Тесты (
templates/tests/): Позволяют определить Pod'ы, которые проверяют работоспособность установленного приложения. Запускаются командойhelm test.
Итоги: ваш путь от структуры к мастерству
Вы разобрали фундаментальные блоки Helm-чарта:
- Chart.yaml — метаданные и зависимости.
- values.yaml — централизованная конфигурация.
- templates/ — логика генерации манифестов на основе конфигурации.
Вы освоили принцип разделения кода (шаблоны) и конфигурации (values), который лежит в основе гибкости Helm. Вы научились обязательной практике проверки чарта с помощью helm lint и helm template --debug перед установкой в кластер.
Для дальнейшего развития рекомендуется:
- Изучить официальную документацию по функциям и пайплайнам шаблонов Helm.
- Анализировать структуру чартов из популярных репозиториев (например, bitnami).
- Практиковаться в упаковке своих собственных приложений, начиная с простых и постепенно добавляя элементы для поддерживаемости (
_helpers.tpl, схему валидации).
Понимание внутренней структуры — это основа, которая позволяет уверенно читать, модифицировать и создавать Helm-чарты для эффективного управления приложениями в Kubernetes.