microservices
Создание и использование Helm-чартов в Kubernetes
Полное руководство по работе с Helm для управления приложениями в Kubernetes
•
#microservices
#kubernetes
#helm
#devops
#infrastructure
Создание и использование Helm-чартов в Kubernetes
Helm — это пакетный менеджер для Kubernetes, который упрощает развертывание и управление приложениями в кластере.
Что такое Helm?
Helm позволяет определить, установить и обновить даже самые сложные Kubernetes приложения. Чарты (charts) — это пакеты предварительно сконфигурированных ресурсов Kubernetes.
Структура Helm Chart
my-microservice/
├── Chart.yaml # Метаданные чарта
├── values.yaml # Значения по умолчанию
├── charts/ # Зависимости
├── templates/ # Шаблоны Kubernetes манифестов
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── configmap.yaml
│ └── _helpers.tpl
└── .helmignore # Игнорируемые файлы
Создание Chart
Chart.yaml
apiVersion: v2
name: order-service
description: Order management microservice
type: application
version: 1.0.0
appVersion: "1.0.0"
keywords:
- microservices
- orders
maintainers:
- name: DevOps Team
email: devops@example.com
dependencies:
- name: postgresql
version: "12.1.0"
repository: "https://charts.bitnami.com/bitnami"
values.yaml
# Настройки по умолчанию
replicaCount: 3
image:
repository: myregistry/order-service
tag: "1.0.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
targetPort: 3000
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: orders.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: orders-tls
hosts:
- orders.example.com
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 80
env:
- name: NODE_ENV
value: production
- name: DATABASE_HOST
value: postgresql
- name: DATABASE_PORT
value: "5432"
secrets:
DATABASE_PASSWORD: ""
JWT_SECRET: ""
healthCheck:
liveness:
path: /health
initialDelaySeconds: 30
periodSeconds: 10
readiness:
path: /ready
initialDelaySeconds: 10
periodSeconds: 5
Шаблоны манифестов
templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "order-service.fullname" . }}
labels:
{{- include "order-service.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "order-service.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
labels:
{{- include "order-service.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.targetPort }}
protocol: TCP
env:
{{- range .Values.env }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}
{{- range $key, $value := .Values.secrets }}
- name: {{ $key }}
valueFrom:
secretKeyRef:
name: {{ include "order-service.fullname" $ }}-secrets
key: {{ $key }}
{{- end }}
livenessProbe:
httpGet:
path: {{ .Values.healthCheck.liveness.path }}
port: http
initialDelaySeconds: {{ .Values.healthCheck.liveness.initialDelaySeconds }}
periodSeconds: {{ .Values.healthCheck.liveness.periodSeconds }}
readinessProbe:
httpGet:
path: {{ .Values.healthCheck.readiness.path }}
port: http
initialDelaySeconds: {{ .Values.healthCheck.readiness.initialDelaySeconds }}
periodSeconds: {{ .Values.healthCheck.readiness.periodSeconds }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ include "order-service.fullname" . }}
labels:
{{- include "order-service.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "order-service.selectorLabels" . | nindent 4 }}
templates/_helpers.tpl
{{/*
Expand the name of the chart.
*/}}
{{- define "order-service.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "order-service.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "order-service.labels" -}}
helm.sh/chart: {{ include "order-service.chart" . }}
{{ include "order-service.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "order-service.selectorLabels" -}}
app.kubernetes.io/name: {{ include "order-service.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
Использование Helm
Установка чарта
# Установка с дефолтными значениями
helm install order-service ./order-service
# Установка с кастомными значениями
helm install order-service ./order-service \
--values values-production.yaml \
--set image.tag=1.2.0 \
--set replicaCount=5
# Установка в конкретный namespace
helm install order-service ./order-service \
--namespace production \
--create-namespace
Обновление релиза
# Обновление с новыми значениями
helm upgrade order-service ./order-service \
--values values-production.yaml \
--set image.tag=1.3.0
# Обновление или установка (если не существует)
helm upgrade --install order-service ./order-service
# Откат к предыдущей версии
helm rollback order-service 1
Управление релизами
# Список установленных релизов
helm list
# История релиза
helm history order-service
# Удаление релиза
helm uninstall order-service
# Удаление с сохранением истории
helm uninstall order-service --keep-history
Переопределение значений
values-production.yaml
replicaCount: 5
image:
tag: "1.3.0"
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
autoscaling:
enabled: true
minReplicas: 5
maxReplicas: 20
targetCPUUtilizationPercentage: 70
env:
- name: NODE_ENV
value: production
- name: LOG_LEVEL
value: info
Использование секретов
# Создание секретов из файла
kubectl create secret generic order-service-secrets \
--from-literal=DATABASE_PASSWORD=secret123 \
--from-literal=JWT_SECRET=jwt-secret-key
# Или через Helm
helm install order-service ./order-service \
--set secrets.DATABASE_PASSWORD=secret123 \
--set secrets.JWT_SECRET=jwt-secret-key
Тестирование чарта
# Проверка синтаксиса
helm lint ./order-service
# Dry-run установки
helm install order-service ./order-service --dry-run --debug
# Рендеринг шаблонов
helm template order-service ./order-service
# Тестирование установленного релиза
helm test order-service
Упаковка и публикация
# Упаковка чарта
helm package ./order-service
# Создание индекса репозитория
helm repo index .
# Добавление репозитория
helm repo add myrepo https://charts.example.com
# Обновление репозиториев
helm repo update
# Установка из репозитория
helm install order-service myrepo/order-service
Hooks
templates/hooks/pre-install-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "order-service.fullname" . }}-migration
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "-5"
"helm.sh/hook-delete-policy": before-hook-creation
spec:
template:
spec:
restartPolicy: Never
containers:
- name: migration
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
command: ["npm", "run", "migrate"]
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: {{ include "order-service.fullname" . }}-secrets
key: DATABASE_URL
Best Practices
- Используйте values.yaml — все конфигурируемые параметры должны быть в values
- Версионируйте чарты — следуйте semantic versioning
- Документируйте параметры — добавляйте комментарии в values.yaml
- Тестируйте перед деплоем — используйте
helm lintи--dry-run - Используйте зависимости — не дублируйте чарты для общих сервисов
- Применяйте hooks — для миграций и других задач
- Храните секреты безопасно — используйте external secrets или sealed secrets
Заключение
Helm значительно упрощает управление Kubernetes приложениями, обеспечивая переиспользование конфигураций, версионирование и простое обновление микросервисов.