Helm Charts: Управление пакетами в Kubernetes

Развёртывание Kubernetes с управлением пакетов Helm

Helm изменил подход к развертыванию приложений в Kubernetes, внедрив концепции управления пакетами, знакомые из традиционных операционных систем.

По мере роста популярности Kubernetes управление сложными приложениями с десятками YAML-файлов становится все более сложным. Helm Charts решают эту проблему, объединяя все ресурсы в версионируемые, настраиваемые пакеты.

software-developer in the nature Это красивое изображение было сгенерировано AI-моделью Flux 1 dev.

Понимание Helm: менеджер пакетов для Kubernetes

Helm для Kubernetes то же самое, что apt для Debian, yum для RedHat или Homebrew для macOS. Он упаковывает приложения Kubernetes в Charts – наборы файлов, описывающих связанные ресурсы Kubernetes. Один Chart может развернуть полный стек приложения: веб-серверы, базы данных, кэширующие слои, правила ингресса и компоненты мониторинга. Для новичков в Kubernetes Шпаргалка по Kubernetes предоставляет основные команды и концепции для начала работы.

Почему Helm важен в современной DevOps

Снижение сложности: Вместо управления 20+ YAML-файлами вы управляете одним Chart с настраиваемыми значениями.

Воспроизводимость: Развертывайте идентичные конфигурации в средах разработки, тестирования и продакшена с помощью специфичных для среды переопределений значений. Это особенно ценно при развертывании сложных микросервисных архитектур, где важна согласованность.

Контроль версий: Charts версионируются, что позволяет легко выполнять откаты и отслеживать обновления.

Сообщество и экосистема: Тысячи готовых Charts доступны через Artifact Hub (ранее Helm Hub) для популярных приложений, таких как PostgreSQL, Redis, NGINX, Prometheus и другие.

Мощь шаблонизации: Шаблоны Go позволяют динамически генерировать ресурсы на основе входных значений, уменьшая дублирование.

Архитектура Helm и ключевые концепции

Архитектура Helm 3

Helm 3 упростил архитектуру, удалив Tiller, проблемный серверный компонент из Helm 2:

  • Helm Client: CLI-инструмент, который взаимодействует напрямую с API Kubernetes
  • Chart: Формат пакета, содержащий шаблоны и метаданные
  • Release: Экземпляр Chart, работающий в кластере Kubernetes
  • Репозиторий: Место хранения Charts (HTTP-сервер или OCI-регистр)

Ключевые компоненты Helm Chart

my-app-chart/
├── Chart.yaml          # Метаданные и версия Chart
├── values.yaml         # Значения конфигурации по умолчанию
├── charts/             # Зависимые Charts
├── templates/          # Шаблоны ресурсов Kubernetes
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── _helpers.tpl    # Вспомогательные шаблоны
│   └── NOTES.txt       # Примечания после установки
├── .helmignore         # Файлы для игнорирования при упаковке
├── README.md
└── LICENSE

Создание вашего первого Helm Chart

Инициализация нового Chart

helm create my-application
cd my-application

Это создает стартовый Chart с примерными шаблонами для развертывания, сервиса и ингресса.

Chart.yaml: Определение метаданных

apiVersion: v2
name: my-application
description: Готовый к продакшену Chart приложения
type: application
version: 1.0.0        # Версия Chart
appVersion: "2.4.1"   # Версия приложения

maintainers:
  - name: Ваша команда
    email: team@company.com

dependencies:
  - name: postgresql
    version: "12.x.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled

Values.yaml: Управление конфигурацией

Файл values.yaml определяет конфигурации по умолчанию, которые пользователи могут переопределить. Этот подход разделяет конфигурацию и шаблоны, облегчая управление разными средами (разработка, тестирование, продакшен) и настройку развертываний без изменения файлов шаблонов.

replicaCount: 3

image:
  repository: myapp/backend
  tag: "1.0.0"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  className: "nginx"
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
  hosts:
    - host: myapp.example.com
      paths:
        - path: /
          pathType: Prefix

resources:
  limits:
    cpu: 500m
    memory: 512Mi
  requests:
    cpu: 250m
    memory: 256Mi

autoscaling:
  enabled: true
  minReplicas: 3
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80

Шаблоны: Динамические манифесты Kubernetes

Шаблоны используют синтаксис шаблонизации Go для динамического создания ресурсов Kubernetes. Эти шаблоны могут генерировать любые типы ресурсов Kubernetes, от простых Deployments до сложных StatefulSets для приложений с состоянием, требующих постоянного хранения. Для приложений, которым нужны стабильные идентификаторы и постоянные тома, вы захотите использовать StatefulSets вместо Deployments, как подробно описано в нашем руководстве по StatefulSets и постоянному хранению в Kubernetes.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "my-application.fullname" . }}
  labels:
    {{- include "my-application.labels" . | nindent 4 }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  selector:
    matchLabels:
      {{- include "my-application.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "my-application.selectorLabels" . | nindent 8 }}
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        ports:
        - containerPort: 8080
          protocol: TCP
        resources:
          {{- toYaml .Values.resources | nindent 10 }}

Вспомогательные шаблоны (_helpers.tpl)

Создавайте повторно используемые функции шаблонов для избежания дублирования:

{{/*
Развернуть имя Chart.
*/}}
{{- define "my-application.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Создать стандартное полное имя приложения.
*/}}
{{- define "my-application.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}

{{/*
Общие метки
*/}}
{{- define "my-application.labels" -}}
helm.sh/chart: {{ include "my-application.chart" . }}
{{ include "my-application.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

Управление Helm Charts: установка и операции

Установка Chart

# Установка из репозитория
helm install my-release bitnami/postgresql

# Установка из локальной директории
helm install my-app ./my-application

# Установка с пользовательскими значениями
helm install my-app ./my-application -f values-production.yaml

# Установка с переопределением значений в строке
helm install my-app ./my-application \
  --set replicaCount=5 \
  --set image.tag=2.0.0

Обновление релизов

# Обновление с новыми значениями
helm upgrade my-app ./my-application -f values-production.yaml

# Обновление с атомарным откатом при ошибке
helm upgrade my-app ./my-application --atomic --timeout 5m

# Принудительное обновление ресурсов
helm upgrade my-app ./my-application --force

Откат и история

# Просмотр истории релиза
helm history my-app

# Откат к предыдущей версии
helm rollback my-app

# Откат к конкретной ревизии
helm rollback my-app 3

Тестирование и отладка

# Сухой запуск для просмотра сгенерированных манифестов
helm install my-app ./my-application --dry-run --debug

# Рендеринг шаблонов без установки
helm template my-app ./my-application

# Проверка Chart на ошибки
helm lint ./my-application

# Тестирование релиза с тестовыми хуками
helm test my-app

Дополнительные возможности Helm

Зависимости Chart

Helm Charts могут зависеть от других Charts, позволяя составлять сложные приложения из повторно используемых компонентов. Это особенно полезно при развертывании микросервисов, которым нужны базы данных, очереди сообщений или другие вспомогательные сервисы. Определите зависимости в Chart.yaml:

dependencies:
  - name: redis
    version: "17.x.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: redis.enabled
  - name: postgresql
    version: "12.x.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled

Обновите зависимости:

helm dependency update ./my-application

Helm Hooks для управления жизненным циклом

Хуки выполняются в определенные моменты жизненного цикла релиза:

apiVersion: batch/v1
kind: Job
metadata:
  name: {{ include "my-application.fullname" . }}-db-migration
  annotations:
    "helm.sh/hook": pre-upgrade,pre-install
    "helm.sh/hook-weight": "5"
    "helm.sh/hook-delete-policy": before-hook-creation
spec:
  template:
    spec:
      containers:
      - name: db-migrate
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        command: ["python", "manage.py", "migrate"]
      restartPolicy: Never

Типы хуков включают:

  • pre-install: Перед установкой ресурсов
  • post-install: После установки всех ресурсов
  • pre-upgrade: Перед обновлением
  • post-upgrade: После обновления
  • pre-delete: Перед удалением
  • post-delete: После удаления
  • pre-rollback: Перед откатом
  • post-rollback: После отката

Условная логика и управление потоком

{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ include "my-application.fullname" . }}
  {{- with .Values.ingress.annotations }}
  annotations:
    {{- toYaml . | nindent 4 }}
  {{- end }}
spec:
  {{- if .Values.ingress.className }}
  ingressClassName: {{ .Values.ingress.className }}
  {{- end }}
  rules:
  {{- range .Values.ingress.hosts }}
  - host: {{ .host | quote }}
    http:
      paths:
      {{- range .paths }}
      - path: {{ .path }}
        pathType: {{ .pathType }}
        backend:
          service:
            name: {{ include "my-application.fullname" $ }}
            port:
              number: {{ $.Values.service.port }}
      {{- end }}
  {{- end }}
{{- end }}

Поддержка OCI Registry: Современное распределение Chart

С версии Helm 3.8 поддержка OCI (Open Container Initiative) реестров стала стабильной, что позволяет хранить Chart вместе с контейнерами.

Публикация в OCI Registry

# Вход в реестр
helm registry login registry.example.com

# Упаковка чарта
helm package ./my-application

# Отправка в OCI реестр
helm push my-application-1.0.0.tgz oci://registry.example.com/charts

# Установка из OCI реестра
helm install my-app oci://registry.example.com/charts/my-application --version 1.0.0

Преимущества OCI реестров

  • Единое хранилище: Chart и образы в одном месте
  • Стандартные инструменты: Использование существующей инфраструктуры реестров
  • Лучшая безопасность: Использование аутентификации и сканирования реестра
  • Проще управление: Не требуется отдельный сервер для Chart репозитория

Лучшие практики для производственных Helm Chart

1. Структура и документация значений

Документируйте все значения с комментариями:

# -- Количество реплик для приложения
replicaCount: 3

# -- Настройки образа
image:
  # -- Репозиторий образа
  repository: myapp/backend
  # -- Политика загрузки образа
  pullPolicy: IfNotPresent
  # -- Тег образа (по умолчанию версия чарта)
  tag: ""

2. Управление ресурсами

Всегда устанавливайте запросы и лимиты ресурсов:

resources:
  limits:
    cpu: 1000m
    memory: 1Gi
  requests:
    cpu: 500m
    memory: 512Mi

3. Контексты безопасности

Определяйте контексты безопасности для контейнеров:

securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  fsGroup: 1000
  capabilities:
    drop:
    - ALL
  readOnlyRootFilesystem: true

4. Проверки состояния

Включайте проверки работоспособности и готовности:

livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 30
  periodSeconds: 10

readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5

5. Управление ConfigMap и Secret

Правильное управление секретами критически важно для производственных развертываний. Используйте внешние менеджеры секретов (Sealed Secrets, External Secrets Operator или Vault) вместо хранения секретов в файлах значений. Это обеспечивает безопасное обращение с конфиденциальными данными, такими как пароли баз данных, API ключи и сертификаты:

envFrom:
- secretRef:
    name: {{ include "my-application.fullname" . }}-secrets
- configMapRef:
    name: {{ include "my-application.fullname" . }}-config

6. Схема валидации

Создавайте values.schema.json для валидации входных данных:

{
  "$schema": "https://json-schema.org/draft-07/schema#",
  "properties": {
    "replicaCount": {
      "type": "integer",
      "minimum": 1
    },
    "image": {
      "type": "object",
      "properties": {
        "repository": {
          "type": "string"
        },
        "tag": {
          "type": "string"
        }
      },
      "required": ["repository"]
    }
  },
  "required": ["image"]
}

7. NOTES.txt для руководства пользователя

Предоставляйте инструкции после установки:

1. Получите URL приложения, выполнив:
{{- if .Values.ingress.enabled }}
  https://{{ (index .Values.ingress.hosts 0).host }}
{{- else if contains "NodePort" .Values.service.type }}
  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "my-application.fullname" . }})
  export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT
{{- end }}

2. Мониторьте развертывание:
  kubectl --namespace {{ .Release.Namespace }} get pods -l "app.kubernetes.io/name={{ include "my-application.name" . }}"

Тестирование Helm Chart и интеграция с CI/CD

Тестирование Chart с chart-testing (ct)

# Установка chart-testing
brew install chart-testing

# Проверка синтаксиса чартов
ct lint --config ct.yaml

# Установка и тестирование чартов
ct install --config ct.yaml

Пример GitHub Actions

name: Helm Chart CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  lint-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Настройка Helm
        uses: azure/setup-helm@v3
        with:
          version: 3.12.0

      - name: Настройка chart-testing
        uses: helm/chart-testing-action@v2

      - name: Проверка синтаксиса чартов
        run: ct lint --config ct.yaml

      - name: Создание kind кластера
        uses: helm/kind-action@v1

      - name: Установка чартов
        run: ct install --config ct.yaml

GitOps с Helm: ArgoCD и Flux

Инструменты GitOps, такие как ArgoCD и Flux, интегрируются с Helm Chart, обеспечивая декларативные, автоматизированные развертывания. Эти инструменты следят за изменениями в вашем репозитории Git и автоматически синхронизируют релизы Helm, упрощая непрерывное развертывание. Для сложных микросервисных архитектур рассмотрите использование распределенных транзакционных паттернов, таких как Saga pattern, чтобы управлять согласованностью между сервисами, развертываемыми через Helm.

Пример ArgoCD Application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-application
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/my-app-chart
    targetRevision: main
    path: charts/my-application
    helm:
      valueFiles:
        - values-production.yaml
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Пример Flux HelmRelease

apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: my-application
  namespace: flux-system
spec:
  interval: 5m
  chart:
    spec:
      chart: my-application
      version: '1.x.x'
      sourceRef:
        kind: HelmRepository
        name: my-charts
  values:
    replicaCount: 5
    image:
      tag: "2.0.0"

Устранение распространенных проблем Helm

Проблема: Неудачное обновление зависло в состоянии ожидания

# Проверка статуса релиза
helm list --all-namespaces

# Получение деталей релиза
helm status my-app -n namespace

# Принудительное удаление при необходимости (используйте осторожно)
kubectl delete secret -n namespace -l owner=helm,name=my-app

Проблема: Ошибки рендеринга шаблонов

# Отладка рендеринга шаблонов
helm template my-app ./my-application --debug

# Валидация против Kubernetes
helm template my-app ./my-application | kubectl apply --dry-run=client -f -

Проблема: Значения не применены

# Проверка объединенных значений
helm get values my-app

# Показать все вычисленные значения
helm get values my-app --all

Экосистема Helm и инструменты

Экосистема Helm включает множество инструментов, расширяющих его возможности и интегрирующихся с другими технологиями Kubernetes. При развертывании приложений, требующих продвинутых сетевых функций, таких как коммуникация между сервисами, управление трафиком и политики безопасности, рассмотрите интеграцию с Service Mesh с Istio и Linkerd, которые могут быть развернуты и управляемы через Helm Chart.

Основные инструменты

  • Helmfile: Декларативное описание для развертывания Helm Chart
  • Helm Diff: Предварительный просмотр изменений перед обновлением
  • Helm Secrets: Управление секретами с SOPS
  • Nova: Поиск устаревших Helm Chart
  • Pluto: Обнаружение устаревших API Kubernetes

Пример Helmfile

repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami

releases:
  - name: postgresql
    namespace: database
    chart: bitnami/postgresql
    version: 12.x.x
    values:
      - postgresql:
          auth:
            database: myapp
            username: appuser

  - name: my-app
    namespace: production
    chart: ./charts/my-application
    values:
      - values-production.yaml
    needs:
      - database/postgresql

Будущее Helm

Экосистема Helm продолжает развиваться:

  • OCI-ориентированный: Полный переход на OCI реестры как стандарт
  • Улучшенная безопасность: Лучшее управление секретами и возможности подписи
  • Производительность: Быстрое рендеринг и установка для больших Chart
  • Поддержка WASM: WebAssembly для плагинов и расширений Chart
  • Лучшая валидация: Улучшенная схема валидации и enforcement политик

Заключение

Helm стал де-факто стандартом для управления пакетами Kubernetes, и его освоение необходимо для современных практик DevOps. Понимание структуры Chart, шаблонизации, управления значениями и лучших практик позволяет создавать поддерживаемые, безопасные и масштабируемые развертывания Kubernetes.

Начните с простых Chart, постепенно внедряйте продвинутые функции, такие как хуки и зависимости, и интегрируйтесь с инструментами GitOps для производственных инфраструктур. Сообщество Helm предоставляет тысячи готовых Chart, но настоящая мощь заключается в создании пользовательских Chart, адаптированных под нужды вашей организации. Будь то развертывание безсостоятельных приложений или состоятельных рабочих нагрузок, требующих постоянного хранилища, Helm упрощает сложность управления ресурсами Kubernetes. Для команд, настраивающих новые кластеры Kubernetes, рассмотрите установку Kubernetes с Kubespray или изучение распространений Kubernetes вроде k3s или MicroK8s для сред разработки. Если вы оцениваете, какое распределение подходит для ваших нужд в домашней лаборатории или небольшого кластера, посмотрите наше подробное сравнение распределений Kubernetes для детального анализа.

Полезные ссылки