lenec ru

← все посты

GitOps с ArgoCD: declarative deployments, sync policies, rollback

10K

Вы развернули Node.js приложение в Kubernetes через kubectl apply -f deployment.yaml. Работает. Теперь нужно развернуть то же приложение в staging с другими переменными окружения, другим количеством реплик и другим ingress. Копируете YAML, меняете значения, применяете. Через месяц у вас 15 почти идентичных файлов с дублированным кодом. Helm решает эту проблему — это package manager для Kubernetes, который превращает набор манифестов в переиспользуемый шаблон.

Зачем Helm: package manager для Kubernetes

Helm — это apt/yum/npm для Kubernetes. Он упаковывает манифесты (Deployment, Service, Ingress) в единицу, называемую chart, и отделяет конфигурацию от структуры через values.yaml. Вместо копирования YAML вы пишете шаблон один раз и переопределяете значения для каждого окружения.

Преимущества: переиспользование (один chart для dev/staging/prod), версионирование (можно откатиться), зависимости (chart может зависеть от PostgreSQL, Redis), шаблонизация (условия, циклы, функции), release management (Helm отслеживает установки и историю).

Структура chart

Создание chart:

helm create myapp

Структура:

myapp/
├── Chart.yaml          # Метаданные
├── values.yaml         # Значения по умолчанию
├── charts/             # Зависимости
├── templates/          # Шаблоны манифестов
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── _helpers.tpl    # Вспомогательные функции
│   └── NOTES.txt
└── .helmignore

Chart.yaml

apiVersion: v2
name: myapp
description: Node.js application
type: application
version: 0.1.0         # Версия chart
appVersion: "1.0.0"    # Версия приложения

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

Templating: Go templates

Файлы в templates/ — это YAML с вставками Go template синтаксиса.

templates/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-{{ .Chart.Name }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Chart.Name }}
  template:
    metadata:
      labels:
        app: {{ .Chart.Name }}
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        ports:
        - containerPort: {{ .Values.service.port }}
        env:
        {{- range .Values.env }}
        - name: {{ .name }}
          value: {{ .value | quote }}
        {{- end }}
        {{- if .Values.resources }}
        resources:
          {{- toYaml .Values.resources | nindent 10 }}
        {{- end }}

Ключевые конструкции:

  • {{ .Values.key }} — подстановка из values.yaml
  • {{ .Chart.Name }} — имя chart
  • {{ .Release.Name }} — имя release
  • {{- ... }} — удаляет пробелы слева
  • {{ if }} ... {{ end }} — условие
  • {{ range }} ... {{ end }} — цикл
  • {{ .value | quote }} — функция
  • {{- toYaml .Values.obj | nindent 10 }} — конвертирует в YAML с отступом

_helpers.tpl: переиспользуемые фрагменты

{{- define "myapp.labels" -}}
app: {{ .Chart.Name }}
version: {{ .Chart.AppVersion }}
release: {{ .Release.Name }}
{{- end }}

Использование:

metadata:
  labels:
    {{- include "myapp.labels" . | nindent 4 }}

Values и overrides

values.yaml

replicaCount: 2

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

service:
  type: ClusterIP
  port: 3000

env:
  - name: NODE_ENV
    value: production
  - name: PORT
    value: "3000"

resources:
  requests:
    memory: "128Mi"
    cpu: "100m"
  limits:
    memory: "512Mi"
    cpu: "500m"

autoscaling:
  enabled: false
  minReplicas: 2
  maxReplicas: 10

Environment-specific values

values-dev.yaml:

replicaCount: 1
image:
  tag: "dev"
env:
  - name: NODE_ENV
    value: development

values-prod.yaml:

replicaCount: 5
autoscaling:
  enabled: true

Установка:

helm install myapp-dev ./myapp -f values-dev.yaml
helm install myapp-prod ./myapp -f values-prod.yaml

# Или через --set
helm install myapp ./myapp --set image.tag=1.2.3

Приоритет: values.yaml-f values-prod.yaml--set.

helm upgrade

helm upgrade myapp-prod ./myapp -f values-prod.yaml --set image.tag=1.2.4

# Откат
helm rollback myapp-prod

# История
helm history myapp-prod

Dependencies: subcharts

Добавьте зависимость в Chart.yaml:

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

Скачивание:

helm dependency update ./myapp

Конфигурация subchart через values.yaml:

postgresql:
  enabled: true
  auth:
    username: myapp
    password: secret
    database: myapp_db
  primary:
    persistence:
      size: 10Gi

Отключение зависимости:

helm install myapp ./myapp --set postgresql.enabled=false

Использование в Deployment:

env:
- name: DATABASE_URL
  value: "postgresql://{{ .Values.postgresql.auth.username }}:{{ .Values.postgresql.auth.password }}@{{ .Release.Name }}-postgresql:5432/{{ .Values.postgresql.auth.database }}"

Практические советы

Проверка шаблонов:

# Рендер без установки
helm template myapp ./myapp -f values-prod.yaml

# Dry-run
helm install myapp ./myapp --dry-run --debug

# Lint
helm lint ./myapp

Упаковка и публикация:

helm package ./myapp
helm push myapp-0.1.0.tgz oci://myregistry.io/charts

Вывод

Helm превращает набор YAML-файлов в переиспользуемый, версионируемый пакет. Вместо копирования манифестов для каждого окружения вы пишете шаблон один раз и переопределяете значения через values.yaml. Go templates позволяют использовать условия, циклы и функции. Dependencies упрощают управление зависимостями — PostgreSQL, Redis устанавливаются автоматически.

Начните с helm create, адаптируйте шаблоны, создайте values-dev.yaml и values-prod.yaml. Используйте helm template и --dry-run для проверки. Добавляйте зависимости через Chart.yaml. Helm — стандарт де-факто для деплоя в Kubernetes, и в 2026 году управление сырыми YAML через kubectl apply — антипаттерн для любого проекта сложнее hello-world.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.