Перейти к содержанию

Universal Helm Chart v0.1.7

Полное руководство по использованию универсального Helm-чарта для деплоя приложений в Kubernetes.


Содержание

  1. Обзор
  2. Ключевые особенности
  3. Быстрый старт
  4. pluckEnv — как работает выбор значений по окружению
  5. Структура values.yaml
  6. Deployment — конфигурация деплоймента
  7. Image — конфигурация образа
  8. Service — конфигурация сервиса
  9. Переменные окружения
  10. Volumes — монтирование томов
  11. Scheduling — распределение по нодам
  12. Метаданные и аннотации
  13. Helper-функции
  14. Примеры
  15. Интеграция с CI/CD

Обзор

Universal Chart — это универсальный Helm-чарт для деплоя приложений в Kubernetes.

Версия: 0.1.7
Репозиторий: oci://cr.yandex/crp3ccidau046kdj8g9q/charts

dependencies:
  - name: universal-chart
    repository: oci://cr.yandex/crp3ccidau046kdj8g9q/charts
    version: 0.1.7

Ключевые особенности

Возможность Описание
Multi-service Деплой нескольких сервисов (api, frontend, celery, etc) в одном релизе
Env-specific values Поддержка значений для разных окружений: _default, stage, preprod, production
External secrets Секреты и ConfigMap управляются внешними средствами (e.g Vault/Terraform)
Flexible volumes Поддержка secret, configMap, PVC, emptyDir, hostPath, projected
Advanced scheduling nodeSelector, tolerations, affinity rules
Health probes Гибкая настройка liveness/readiness probes всех типов

Важно: Чарт НЕ создаёт Secrets и ConfigMaps — только ссылается на внешние ресурсы.


Быстрый старт

1. Создайте Chart.yaml

apiVersion: v2
name: my-service
version: 1.0.0
dependencies:
  - name: universal-chart
    repository: oci://cr.yandex/crp3ccidau046kdj8g9q/charts
    version: 0.1.7

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

echo $HELM_REGISTRY_KEY | base64 -d | helm registry login cr.yandex --username json_key --password-stdin
helm dependency update .helm

3. Создайте values.yaml

universal-chart:
  global:
    env: stage

  services:
    main:
      enabled: true
      deployment:
        enabled: true
        name:
          _default: my-service
        port:
          _default: 8080
      image:
        name:
          _default: cr.yandex/.../my-service
      service:
        enabled: true
        port:
          _default: 80
        targetPort:
          _default: 8080

4. Проверьте и задеплойте

# Проверка
helm template my-release .helm -f .helm/values.yaml --set universal-chart.global.env=stage

# Деплой
helm upgrade -i my-release .helm -n my-namespace -f .helm/values.yaml \
  --set universal-chart.global.env=stage

Как работает выбор значений по окружению

Принцип работы

  1. Берёт параметр с ключами: _default, stage, preprod, production
  2. Ищет значение для текущего окружения ( из значения global.env)
  3. Если не найдено — берёт _default

Пример

replicaCount:
  _default: 1
  stage: 2
  preprod: 2
  production: 5
global.env Результат
stage 2
preprod 2
production 5
любое другое 1 (_default)

Где используется

Практически все параметры поддерживают данную функцию:

  • deployment.replicaCount, deployment.port, deployment.resources
  • image.name, image.pullPolicy
  • service.type, service.port
  • envs[].value
  • secretEnvs[].secretName, secretEnvs[].secretKey
  • volumes[].mountPath, volumes[].secret.secretName
  • nodeSelector.*, tolerations[].key, affinity.*

Структура values.yaml

Общая структура

universal-chart:
  global:
    env: stage  # ОБЯЗАТЕЛЬНО: stage | preprod | production

  services:
    <service-name>:        # api, frontend, worker, main и т.д.
      enabled: true        # вкл/выкл сервис
      deployment: { ... }  # Kubernetes Deployment
      image: { ... }       # Docker-образ
      service: { ... }     # Kubernetes Service
      imagePullSecrets: { ... }
      envs: [ ... ]        # env vars
      secretEnvs: [ ... ]  # env vars из секретов
      volumes: { ... }     # вольюмы
      nodeSelector: { ... }
      tolerations: [ ... ]
      affinity: { ... }
      labels: { ... }
      commitSha: ""        # метаданные
      gitlabUri: ""
      gitlabJobUrl: ""
      owner: ""


Deployment — конфигурация деплоймента

Полный пример

deployment:
  enabled: true  # создавать Deployment

  # Имя деплоймента (опционально)
  # Если не указано: <release-name>-<service-name>
  name:
    _default: api-service
    stage: api-stage
    production: api-prod

  # Количество реплик
  replicaCount:
    _default: 1
    stage: 2
    production: 3

  # Порт контейнера
  port:
    _default: 8080
    stage: 8081

  # История ревизий для rollback
  revisionHistoryLimit:
    _default: 10
    production: 5

  # Ресурсы
  resources:
    requests:
      memory:
        _default: "256Mi"
        stage: "512Mi"
        production: "1Gi"
      cpu:
        _default: "200m"
        stage: "500m"
        production: "1000m"
    limits:
      memory:
        _default: "512Mi"
      cpu:
        _default: "400m"

  # Переопределение команды и аргументов
  command:
    _default: ["python"]
    production: ["python3"]
  args:
    _default: ["-m", "uvicorn", "app:app"]
    stage: ["-m", "uvicorn", "app:app", "--reload"]

  # Health probes
  probes:
    liveness:
      enabled:
        _default: true
      type:
        _default: httpGet  # httpGet | tcpSocket | exec
      httpGet:
        path:
          _default: /health
        port:
          _default: 8080
        scheme:
          _default: HTTP
      initialDelaySeconds:
        _default: 10
      periodSeconds:
        _default: 60
      timeoutSeconds:
        _default: 1
      successThreshold:
        _default: 1
      failureThreshold:
        _default: 3

    readiness:
      enabled:
        _default: true
      type:
        _default: httpGet
      httpGet:
        path:
          _default: /ready
        port:
          _default: 8080
      initialDelaySeconds:
        _default: 10
      periodSeconds:
        _default: 30

Типы проб

Тип Описание
httpGet HTTP GET запрос
tcpSocket TCP-подключение
exec Выполнение кастомной команды

Image — конфигурация образа

image:
  # Путь к образу в values.yaml
  name:
    _default: cr.yandex/crp3ccidau046kdj8g9q/my-service
    stage: cr.yandex/crp3ccidau046kdj8g9q/my-service:stage
    production: cr.yandex/crp3ccidau046kdj8g9q/my-service:v1.0.0

  # Политика pull
  pullPolicy:
    _default: IfNotPresent
    stage: Always

imagePullSecrets

imagePullSecrets: #добавлет референс секрета, который используется для скачивания образа из registry
  enabled:
    _default: false
    production: true
  name:
    _default: registry-secret

Service — конфигурация сервиса

service:
  enabled: true  # создавать Service

  # Имя сервиса (опционально)
  # Если не указано: <release-name>-<service-name>-svc
  name:
    _default: api-svc
    stage: api-svc-stage

  # Тип сервиса
  type:
    _default: ClusterIP
    stage: NodePort
    production: ClusterIP

  # Порт сервиса
  port:
    _default: 80
    stage: 8080

  # Порт контейнера
  targetPort:
    _default: 8080

  # Имя порта (для service discovery)
  portName:
    _default: http

Переменные окружения

envs — простые переменные окружения

envs:
  - name: APP_ENV
    value:
      _default: development
      stage: staging
      production: production

  - name: LOG_LEVEL
    value:
      _default: debug
      stage: info
      production: warn

  - name: API_PORT
    value:
      _default: "8080"

secretEnvs — из внешних секретов

Важно: секреты создаются внешними средствами.

secretEnvs:
  - name: DB_PASSWORD
    secretName:
      _default: ya-pg-secret
      production: ya-pg-secret-prod
    secretKey: password

  - name: API_KEY
    secretName:
      _default: api-secret
    secretKey:
      _default: key
      production: key-prod

Генерируется в манифесте:

env:
  - name: DB_PASSWORD
    valueFrom:
      secretKeyRef:
        name: "ya-pg-secret"
        key: "password"

Volumes — монтирование томов

Структура volumes

volumes:
  _default:  
    - name: <volume-name>
      mountPath:
        _default: /path/in/container
      subPath:
        _default: file.conf
      readOnly:
        _default: true
      <volume-type>: { ... }

Типы томов

1. ConfigMap — монтирование внешнего ConfigMap

volumes:
  _default:
    - name: app-config
      mountPath:
        _default: /etc/app/config.yaml
      subPath:
        _default: config.yaml
      readOnly:
        _default: true
      configMap:
        name:
          _default: app-config
          production: app-config-prod
        items:
          - key: config.yaml
            path:
              _default: config.yaml
        defaultMode:
          _default: "0644"

2. Secret — монтирование внешнего секрета

volumes:
  _default:
    - name: tls-certs
      mountPath:
        _default: /etc/ssl/certs
      readOnly:
        _default: true
      secret:
        secretName:
          _default: tls-secret
          production: tls-secret-prod
        items:
          - key: tls.crt
            path:
              _default: tls.crt
          - key: tls.key
            path:
              _default: tls.key
        defaultMode:
          _default: "0400"

3. EmptyDir — временное хранилище

volumes:
  _default:
    - name: cache
      mountPath:
        _default: /tmp/cache
      emptyDir:
        sizeLimit:
          _default: 1Gi
          production: 2Gi
        medium:
          _default: ""      # пустая строка = диск
          stage: Memory     # RAM-диск

4. PersistentVolumeClaim — PVC

volumes:
  _default:
    - name: data
      mountPath:
        _default: /data
      persistentVolumeClaim:
        claimName:
          _default: api-pvc
          production: api-pvc-prod
        readOnly:
          _default: false
          production: true

5. Projected — комбинация нескольких источников в одну директорию в контейнере

volumes:
  _default:
    - name: combined-config
      mountPath:
        _default: /etc/app/config
      readOnly:
        _default: true
      projected:
        sources:
          - secret:
              name:
                _default: app-secret
              items:
                - key: credentials.json
                  path:
                    _default: credentials.json
          - configMap:
              name:
                _default: app-config
              items:
                - key: settings.yaml
                  path:
                    _default: settings.yaml

Scheduling — распределение по нодам

nodeSelector — выбор нод по лейблам

nodeSelector:
  node-type:
    _default: standard
    production: gpu
  environment:
    _default: development
    stage: staging
    production: production

tolerations — tolerations для tainted нод

tolerations:
  - key:
      _default: "node.kubernetes.io/not-ready"
      stage: "dedicated"
    operator:
      _default: "Exists"
      stage: "Equal"
    value:
      stage: "stage-workload"
      production: "gpu-workload"
    effect:
      _default: "NoExecute"
      stage: "NoSchedule"
    tolerationSeconds:
      _default: 300

affinity — pod anti-affinity

affinity:
  podAntiAffinity:
    # Жёсткое требование, если оно неудовлетворено - под будет висеть в Pending
    requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
            - key:
                _default: "app"
              operator:
                _default: "In"
              values:
                - api-service
        topologyKey:
          _default: "kubernetes.io/hostname"

    # Мягкое требование, sheduler может его проигнорировать
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight:
          _default: 100
          stage: 50
        podAffinityTerm:
          labelSelector:
            matchExpressions:
              - key:
                  _default: "app"
                operator:
                  _default: "In"
                values:
                  - api-service
          topologyKey:
            _default: "kubernetes.io/hostname"

Метаданные и аннотации

Лейблы

labels:
  team: backend
  tier: api
  component: api-service

Аннотации для трассировки

commitSha: ""       # SHA коммита
gitlabUri: ""       # URL репозитория
gitlabJobUrl: ""    # URL CI/CD джобы
owner: ""           # команда-owner

Обычно задаются через CI:

HELM_SET_ARGS: >-
  --set universal-chart.services.main.commitSha=${CI_COMMIT_SHA}
  --set universal-chart.services.main.gitlabUri=${CI_PROJECT_URL}
  --set universal-chart.services.main.gitlabJobUrl=${CI_JOB_URL}
  --set universal-chart.services.main.owner=${CI_PROJECT_NAMESPACE}

Примечания

  1. Секреты и ConfigMap — создаются внешними средствами (Vault/Terraform). Чарт только ссылается на них.

  2. global.env — обязательный параметр. Устанавливается через --set universal-chart.global.env=<env>.

  3. Limits vs Requests — в бизнес-приложениях рекомендуется использовать только requests, без limits.

  4. pluckEnv — если для окружения нет значения, используется _default.

  5. Имена ресурсов — автоматически обрезаются до 63 символов (лимит Kubernetes).