Модуль 13 / 19
Helm: пакеты и шаблоны
Содержание
1. Цели модуля
Вы научитесь читать и разрабатывать Helm chart, отделять шаблоны от конфигурации, проверять отрендеренные ресурсы до установки и безопасно выполнять upgrade, test и rollback.
- chart, release и revision
- Go templates и values
- JSON Schema и lint
- upgrade/install и rollback
- Helm 3 → Helm 4
2. Теория: chart, release и revision
Helm — клиентский package manager для Kubernetes. Chart содержит metadata, values, templates и при необходимости dependencies или CRDs. Установка chart с конкретными values создаёт release; каждое изменение release образует revision, доступную через history и rollback.
Release хранит отрендеренное состояние в namespace, обычно в Secrets. Helm не заменяет Kubernetes controllers: он создаёт или изменяет API objects, а их reconciliation выполняет Kubernetes.
3. Теория: структура и шаблоны
Обязательный Chart.yaml задаёт имя и SemVer версии пакета; appVersion описывает версию приложения и не управляет upgrade. values.yaml содержит безопасные defaults, templates рендерят Kubernetes manifests, values.schema.json валидирует входные параметры.
Порядок приоритета: defaults chart → каждый файл -f слева направо → параметры --set/--set-string. Секреты не следует передавать через values в Git или командную строку: они попадут в release metadata, shell history или CI logs.
4. Теория: безопасный lifecycle
До изменения кластера выполняйте helm lint, helm template и server-side dry-run отрендеренного YAML. После установки проверяйте status, history, workload Conditions и helm test. Флаг --wait ограничивает успех готовностью ресурсов, но требует разумного timeout.
В Helm 4 прежний --atomic переименован в --rollback-on-failure, а --force — в --force-replace. Helm 4 обычно управляет существующими Helm 3 releases без миграции данных; старые releases сохраняют прежний apply method, а новые по умолчанию используют Server-Side Apply. Совместимость chart не отменяет тестирование plugins, CI flags и post-renderers.
5. Методические указания
- Версионируйте chart независимо от appVersion
- Фиксируйте chart version или OCI digest в автоматизации
- Храните environment overrides отдельно от defaults
- Используйте required, default и schema вместо неявных предположений
- Не читайте результат только по exit code Helm: проверяйте ресурсы и Events
- Не помещайте mutable данные в selector labels
- Hooks должны быть идемпотентны и иметь delete policy или TTL
- Перед переходом на Helm 4 прогоните charts и pipeline в staging
6. Лабораторная работа: каркас chart
Создайте каталог webapp/templates. Сохраните следующие блоки как webapp/Chart.yaml, webapp/values.yaml, values-lab.yaml и webapp/values.schema.json соответственно.
apiVersion: v2
name: webapp
description: Training web application
type: application
version: 0.1.0
appVersion: "1.29"replicaCount: 2
image:
repository: nginx
tag: 1.29-alpine
pullPolicy: IfNotPresent
service:
port: 80
resources:
requests:
cpu: 25m
memory: 32Mi
limits:
memory: 64Mi
podLabels: {}replicaCount: 3
podLabels:
environment: lab
resources:
requests:
cpu: 50m
memory: 32Mi
limits:
memory: 96Mi{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["replicaCount", "image", "service", "resources"],
"properties": {
"replicaCount": {"type": "integer", "minimum": 1, "maximum": 10},
"image": {
"type": "object",
"required": ["repository", "tag", "pullPolicy"],
"properties": {
"repository": {"type": "string", "minLength": 1},
"tag": {"type": "string", "minLength": 1},
"pullPolicy": {"enum": ["Always", "IfNotPresent", "Never"]}
}
},
"service": {
"type": "object",
"required": ["port"],
"properties": {"port": {"type": "integer", "minimum": 1, "maximum": 65535}}
},
"resources": {"type": "object"},
"podLabels": {"type": "object", "additionalProperties": {"type": "string"}}
}
}7. Лабораторная работа: templates
Сохраните шаблоны как webapp/templates/deployment.yaml, service.yaml и test-connection.yaml. Все copyable-блоки ниже являются YAML/Go templates, а не командами терминала.
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}
labels:
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | quote }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
containers:
- name: web
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- {name: http, containerPort: 80}
readinessProbe:
httpGet: {path: /, port: http}
livenessProbe:
httpGet: {path: /, port: http}
resources:
{{- toYaml .Values.resources | nindent 12 }}apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}
labels:
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
selector:
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
ports:
- {name: http, port: {{ .Values.service.port }}, targetPort: http}apiVersion: v1
kind: Pod
metadata:
name: "{{ .Release.Name }}-test"
annotations:
"helm.sh/hook": test
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
restartPolicy: Never
containers:
- name: check
image: busybox:1.37.0
command: ["wget", "-qO-", "http://{{ .Release.Name }}:{{ .Values.service.port }}"]8. Лабораторная работа: render, install и test
Сначала проверьте локальный chart и отрендеренный результат, затем создайте namespace и release. Server dry-run выполняется над точным rendered.yaml, который будет изучаться.
helm version
mkdir -p webapp/templates
helm lint ./webapp -f values-lab.yaml
helm template course-web ./webapp --namespace lab-helm -f values-lab.yaml --debug > rendered.yaml
kubectl create namespace lab-helm
kubectl apply --dry-run=server -f rendered.yaml
helm upgrade --install course-web ./webapp --namespace lab-helm -f values-lab.yaml --rollback-on-failure --wait --timeout 2m
helm list -n lab-helm
helm status course-web -n lab-helm
helm get values course-web -n lab-helm --all
helm get manifest course-web -n lab-helm
helm test course-web -n lab-helm --logs
kubectl get deploy,service,pod -n lab-helm -l app.kubernetes.io/instance=course-webКритерий: lint успешен, schema принимает values, release deployed, три Pod Ready, effective values соответствуют values-lab.yaml, helm test завершается успешно.
9. Диагностика: неуспешный upgrade и rollback
Задайте несуществующий image tag. Upgrade ожидаемо завершится ошибкой после timeout, а --rollback-on-failure восстановит предыдущую рабочую revision. Соберите history, status, Pods и Warning Events до очистки.
helm upgrade course-web ./webapp --namespace lab-helm -f values-lab.yaml --set image.tag=does-not-exist --rollback-on-failure --wait --timeout 45s
helm history course-web -n lab-helm
helm status course-web -n lab-helm
kubectl get deployment,replicaset,pod -n lab-helm
kubectl events -n lab-helm --types=Warning
helm get values course-web -n lab-helm --all
helm uninstall course-web -n lab-helm
kubectl delete namespace lab-helmЦепочка: Helm error → history/status → rendered manifest и effective values → Deployment Conditions → Pod state → Events → rollback. Не применяйте kubectl edit к управляемому ресурсу: следующий upgrade создаст drift или перезапишет изменение.
10. Контроль и шпаргалка
- Чем chart отличается от release и revision?
- Почему appVersion не заменяет chart version?
- Какие values победят при нескольких -f и --set?
- Почему helm template не заменяет server-side validation?
- Что Helm хранит в release metadata?
- Какие CLI flags изменились в Helm 4?
- Почему hook может пережить uninstall?
Модуль освоен, если вы собираете chart с schema, доказываете итоговый YAML до apply, выполняете проверяемый upgrade и подтверждаете rollback по history и состоянию workload.
PDF для работы офлайн
Скачайте оформленную версию модуля для чтения без подключения к сети.