跳至主要內容

Helm Chart 管理 Kubernetes 應用程式完全指南

Helm Chart 管理 Kubernetes 應用程式完全指南

Kubernetes 的 YAML 配置檔雖然靈活,但當應用程式規模增大時,管理大量的 YAML 文件會變得極其繁瑣。Helm 是 Kubernetes 的套件管理工具,它將一組相關的 Kubernetes 資源打包成 Chart,讓部署、升級和回滾變得簡單可重現。

Helm 基本概念

  • Chart:一組 Kubernetes 資源的描述,類似 npm package
  • Release:Chart 部署到 Kubernetes 後的實例
  • Repository:存放 Chart 的倉庫
  • Values:Chart 的配置變數

安裝 Helm

# macOS
brew install helm

# 確認版本
helm version

常用 Helm 指令

# 新增 Chart 倉庫
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add stable https://charts.helm.sh/stable
helm repo update

# 搜尋 Chart
helm search repo nginx
helm search hub wordpress

# 安裝 Chart
helm install my-nginx bitnami/nginx
helm install my-db bitnami/postgresql --set auth.postgresPassword=secret

# 查看已安裝的 Release
helm list
helm list -n production

# 升級 Release
helm upgrade my-nginx bitnami/nginx --set replicaCount=3

# 回滾
helm rollback my-nginx 1  # 回滾到第 1 版

# 解除安裝
helm uninstall my-nginx

建立自訂 Chart

# 建立 Chart 結構
helm create my-app

生成的目錄結構:

my-app/
├── Chart.yaml           # Chart 基本資訊
├── values.yaml          # 預設配置值
├── charts/              # 子 Chart
└── templates/           # Kubernetes YAML 模板
    ├── deployment.yaml
    ├── service.yaml
    ├── ingress.yaml
    ├── serviceaccount.yaml
    ├── hpa.yaml
    ├── NOTES.txt        # 安裝後顯示的說明
    └── _helpers.tpl     # 可重用的模板片段

Chart.yaml

apiVersion: v2
name: my-app
description: 我的應用程式 Helm Chart
type: application
version: 0.1.0         # Chart 版本
appVersion: "1.0.0"    # 應用程式版本

values.yaml

# 預設配置值
replicaCount: 1

image:
  repository: my-registry/my-app
  pullPolicy: IfNotPresent
  tag: "latest"

service:
  type: ClusterIP
  port: 80
  targetPort: 3000

ingress:
  enabled: false
  className: nginx
  hosts:
    - host: my-app.example.com
      paths:
        - path: /
          pathType: Prefix

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

env:
  NODE_ENV: production
  LOG_LEVEL: info

secrets:
  DATABASE_URL: ""
  JWT_SECRET: ""

autoscaling:
  enabled: false
  minReplicas: 1
  maxReplicas: 5
  targetCPUUtilizationPercentage: 70

templates/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "my-app.fullname" . }}
  labels:
    {{- include "my-app.labels" . | nindent 4 }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  selector:
    matchLabels:
      {{- include "my-app.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "my-app.selectorLabels" . | nindent 8 }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - containerPort: {{ .Values.service.targetPort }}
          env:
            {{- range $key, $value := .Values.env }}
            - name: {{ $key }}
              value: {{ $value | quote }}
            {{- end }}
            {{- if .Values.secrets }}
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: {{ include "my-app.fullname" . }}-secrets
                  key: DATABASE_URL
            {{- end }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
          livenessProbe:
            httpGet:
              path: /health
              port: {{ .Values.service.targetPort }}
            initialDelaySeconds: 30
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /ready
              port: {{ .Values.service.targetPort }}
            initialDelaySeconds: 5
            periodSeconds: 5

環境特定配置

使用不同的 values 檔案針對不同環境:

# values-staging.yaml
replicaCount: 1
image:
  tag: "staging"
ingress:
  enabled: true
  hosts:
    - host: staging.example.com
      paths:
        - path: /
          pathType: Prefix
resources:
  limits:
    cpu: 250m
    memory: 256Mi
# values-production.yaml
replicaCount: 3
image:
  tag: "1.5.0"
ingress:
  enabled: true
  hosts:
    - host: example.com
      paths:
        - path: /
          pathType: Prefix
autoscaling:
  enabled: true
  minReplicas: 3
  maxReplicas: 10
# 部署到不同環境
helm install my-app ./my-app -f values-staging.yaml -n staging
helm install my-app ./my-app -f values-production.yaml -n production

# 升級
helm upgrade my-app ./my-app -f values-production.yaml -n production

Helm Secrets(管理敏感資訊)

# 安裝 helm-secrets 插件
helm plugin install https://github.com/jkroepke/helm-secrets

# 使用 SOPS 加密 secrets
sops -e secrets.yaml > secrets.enc.yaml

# 部署時自動解密
helm secrets upgrade my-app ./my-app \
  -f values-production.yaml \
  -f secrets.enc.yaml

在 CI/CD 中使用 Helm

# .github/workflows/deploy.yml
- name: Deploy to Kubernetes
  run: |
    helm upgrade --install my-app ./charts/my-app \
      --namespace production \
      --create-namespace \
      -f ./charts/my-app/values-production.yaml \
      --set image.tag=${{ github.sha }} \
      --wait \
      --timeout 5m

實用技巧

# 在不實際安裝的情況下渲染模板(偵錯)
helm template my-app ./my-app -f values-production.yaml

# 驗證 Chart
helm lint ./my-app

# 查看 Release 的歷史
helm history my-app -n production

# 查看當前 Release 的 values
helm get values my-app -n production

總結

Helm 大幅簡化了 Kubernetes 應用程式的管理,特別是在多環境部署和版本管理方面。掌握 Chart 的模板語法、values 的分層管理,以及在 CI/CD 中的整合,是現代 DevOps 工程師的必備技能。

分享這篇文章