Helm Kubernetes 应用包管理部署与运维实战 一、背景与目标 Helm 是 Kubernetes 生态系统中最重要的包管理工具,被誉为”Kubernetes 的 apt/yum”。它通过 Chart 的形式封装 Kubernetes 应用,简化了应用的部署、升级和管理流程。
本文档将介绍:
Helm 核心概念与架构
Helm 3 安装与配置
Chart 开发与定制
应用部署与升级实战
Helm 运维最佳实践
企业级 Helm 仓库搭建
二、Helm 核心概念 2.1 核心术语
术语
描述
Chart
Helm 应用包,包含 Kubernetes 资源模板和配置
Release
Chart 在集群中运行的实例
Repository
Chart 仓库,用于存储和分享 Chart
Values
用户自定义配置,覆盖 Chart 默认值
Hook
在特定生命周期阶段执行的临时资源
2.2 Helm 3 vs Helm 2
特性
Helm 2
Helm 3
服务端组件
Tiller
无(纯客户端)
存储方式
ConfigMap(kube-system)
Secret(release 命名空间)
安全性
依赖 RBAC 配置 Tiller
使用用户 kubeconfig
发布版本管理
数字版本
语义化版本
JSON Schema 验证
不支持
支持
三、Helm 安装与配置 3.1 安装 Helm 3 1 2 3 4 5 6 7 8 9 10 curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash wget https://get.helm.sh/helm-v3.14.0-linux-amd64.tar.gz tar -zxvf helm-v3.14.0-linux-amd64.tar.gz sudo mv linux-amd64/helm /usr/local/bin/helmhelm version
3.2 配置 Helm 仓库 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 helm repo add stable https://charts.helm.sh/stable helm repo add bitnami https://charts.bitnami.com/bitnami helm repo add harbor https://helm.goharbor.io helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update helm repo list helm search repo nginx helm search repo redis --versions
3.3 Helm 环境配置 1 2 3 4 5 6 7 8 9 10 11 helm env export HELM_CONFIG_HOME=~/.config/helmexport HELM_CACHE_HOME=~/.cache/helmexport HELM_DATA_HOME=~/.local/share/helmexport http_proxy=http://proxy.company.com:8080export https_proxy=http://proxy.company.com:8080
四、Chart 结构解析 4.1 Chart 目录结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 my-chart/ ├── Chart.yaml # Chart 元数据 ├── values.yaml # 默认配置值 ├── values.schema.json # Values 的 JSON Schema(可选) ├── .helmignore # 打包时忽略的文件 ├── charts/ # 子 Chart 依赖 │ └── postgresql-12.0.0.tgz ├── templates/ # Kubernetes 模板 │ ├── _helpers.tpl # 模板辅助函数 │ ├── deployment.yaml │ ├── service.yaml │ ├── configmap.yaml │ ├── secret.yaml │ ├── ingress.yaml │ └── tests/ # 测试模板 │ └── test-connection.yaml └── files/ # 静态文件(可选) └── config.json
4.2 Chart.yaml 示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 apiVersion: v2 name: my-application description: 企业级微服务应用 Helm Chart type: application version: 1.0 .0 appVersion: "2.5.0" keywords: - microservice - api - production home: https://github.com/company/my-application sources: - https://github.com/company/my-application maintainers: - name: DevOps Team email: devops@company.com dependencies: - name: postgresql version: "12.0.0" repository: "https://charts.bitnami.com/bitnami" condition: postgresql.enabled - name: redis version: "18.0.0" repository: "https://charts.bitnami.com/bitnami" condition: redis.enabled
4.3 values.yaml 示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 replicaCount: 3 image: repository: registry.company.com/my-application pullPolicy: IfNotPresent tag: "2.5.0" imagePullSecrets: - name: registry-secret nameOverride: "" fullnameOverride: "my-application-prod" serviceAccount: create: true annotations: {} name: "" podAnnotations: {}podSecurityContext: fsGroup: 1000 securityContext: runAsNonRoot: true runAsUser: 1000 readOnlyRootFilesystem: true allowPrivilegeEscalation: false service: type: ClusterIP port: 80 targetPort: 8080 ingress: enabled: true className: nginx annotations: nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/proxy-body-size: "50m" hosts: - host: api.company.com paths: - path: / pathType: Prefix tls: - secretName: api-tls-secret hosts: - api.company.com resources: limits: cpu: 2000m memory: 4Gi requests: cpu: 500m memory: 1Gi autoscaling: enabled: true minReplicas: 3 maxReplicas: 20 targetCPUUtilizationPercentage: 80 targetMemoryUtilizationPercentage: 80 nodeSelector: {}tolerations: []affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: my-application topologyKey: kubernetes.io/hostname postgresql: enabled: true auth: postgresPassword: "changeme" primary: persistence: enabled: true size: 50Gi redis: enabled: true auth: enabled: true password: "changeme" master: persistence: enabled: true size: 10Gi metrics: enabled: true serviceMonitor: enabled: true namespace: monitoring interval: 30s
4.4 模板辅助函数 (_helpers.tpl) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 {{/* 创建标准化的名称 */}} {{- 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 }} {{- if contains $name .Release.Name }} {{- .Release.Name | trunc 63 | trimSuffix "-" }} {{- else }} {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} {{- end }} {{- end }} {{- end }} {{/* 创建 Chart 标签 */}} {{- define "my-application.labels" -}} helm.sh/chart: {{ include "my-application.chart" . }} {{ include "my-application.selectorLabels" . }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} {{/* 创建选择器标签 */}} {{- define "my-application.selectorLabels" -}} app.kubernetes.io/name: {{ include "my-application.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} {{/* 创建 Chart 版本信息 */}} {{- define "my-application.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }}
五、应用部署实战 5.1 部署前检查 1 2 3 4 5 6 7 8 9 10 11 12 helm template my-release ./my-chart --debug helm template my-release ./my-chart -f values-prod.yaml --debug helm lint ./my-chart helm dependency update ./my-chart helm dependency build ./my-chart
5.2 安装 Release 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 helm install my-release ./my-chart helm install my-release ./my-chart -n production helm install my-release ./my-chart -f values-prod.yaml helm install my-release ./my-chart --set replicaCount=5 --set image.tag=2.6.0 helm install my-release ./my-chart --dry-run --debug helm install my-release ./my-chart --wait --timeout 10m
5.3 查看 Release 状态 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 helm list helm list -n production helm list --all-namespaces helm status my-release helm status my-release -n production helm history my-release helm get manifest my-release helm get values my-release helm get hooks my-release helm get notes my-release helm get manifest my-release | grep -A 20 "kind: Deployment"
5.4 升级 Release 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 helm upgrade my-release ./my-chart helm upgrade my-release ./my-chart -f values-prod-v2.yaml helm upgrade my-release ./my-chart --set image.tag=2.6.0 helm upgrade my-release ./my-chart --atomic --timeout 10m helm upgrade my-release ./my-chart --force helm diff upgrade my-release ./my-chart -f values-prod-v2.yaml
5.5 回滚 Release 1 2 3 4 5 6 7 8 9 10 11 helm rollback my-release helm rollback my-release 1 helm history my-release helm rollback my-release 2 --wait --timeout 10m
5.6 卸载 Release 1 2 3 4 5 6 7 8 9 10 11 helm uninstall my-release helm uninstall my-release --no-hooks helm uninstall my-release -n production helm uninstall my-release --dry-run
六、Helm 插件生态 6.1 常用插件安装 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 helm plugin install https://github.com/databus23/helm-diff helm plugin install https://github.com/jkroepke/helm-secrets helm plugin install https://github.com/norwoodj/helm-docs helm plugin install https://github.com/helm-unittest/helm-unittest helm plugin install https://github.com/mumoshu/helm-whatup helm plugin install https://github.com/chartmuseum/helm-push
6.2 插件使用示例 1 2 3 4 5 6 7 8 9 10 11 12 helm diff upgrade my-release ./my-chart -f values-prod.yaml helm secrets enc values-secret.yaml helm secrets install my-release ./my-chart -f values-secret.yaml helm unittest ./my-chart helm-docs
七、企业级 Helm 仓库搭建 7.1 使用 Harbor 搭建 Helm 仓库 1 2 3 4 5 6 7 8 9 10 11 12 chartmuseum: enabled: true env: open: STORAGE: local LOCAL_ROOT_DIRECTORY: /storage DEPTH: 1 persistence: enabled: true size: 50Gi storageClass: nfs-storage
7.2 推送 Chart 到仓库 1 2 3 4 5 6 7 8 9 helm package ./my-chart helm push my-chart-1.0.0.tgz oci://registry.company.com/helm-charts helm repo add company-charts https://harbor.company.com/chartrepo/helm-charts helm push my-chart-1.0.0.tgz company-charts
7.3 使用 OCI 注册表 1 2 3 4 5 6 7 8 9 10 11 helm registry login registry.company.com -u admin -p password helm push ./my-chart-1.0.0.tgz oci://registry.company.com/helm-charts helm pull oci://registry.company.com/helm-charts/my-chart --version 1.0.0 helm install my-release oci://registry.company.com/helm-charts/my-chart --version 1.0.0
7.4 Chart 版本管理 1 2 3 4 5 6 7 8 9 10 11 12 13 version: 1.0.0 -> 1.0.1 version: 1.0.0 -> 1.1.0 version: 1.0.0 -> 2.0.0
八、CI/CD 集成 8.1 GitHub Actions 示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 name: Helm CI/CD on: push: branches: [main ] paths: - 'charts/**' pull_request: branches: [main ] paths: - 'charts/**' jobs: lint-test: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Helm uses: azure/setup-helm@v3 with: version: v3.14.0 - name: Set up chart-testing uses: helm/chart-testing-action@v2.6.0 - name: Run chart-testing (list-changed) id: list-changed run: | changed=$(ct list-changed --target-branch main) if [[ -n "$changed" ]]; then echo "changed=true" >> $GITHUB_OUTPUT fi - name: Run chart-testing (lint) run: ct lint --target-branch main --validate-maintainers=false - name: Create kind cluster if: steps.list-changed.outputs.changed == 'true' uses: helm/kind-action@v1.9.0 - name: Run chart-testing (install) if: steps.list-changed.outputs.changed == 'true' run: ct install --target-branch main release: needs: lint-test if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Helm uses: azure/setup-helm@v3 - name: Package charts run: | for chart in charts/*; do helm package $chart done - name: Push to OCI registry run: | helm registry login registry.company.com -u ${{ secrets.HARBOR_USER }} -p ${{ secrets.HARBOR_PASSWORD }} for pkg in *.tgz; do helm push $pkg oci://registry.company.com/helm-charts done
8.2 GitLab CI 示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 stages: - lint - test - release variables: HELM_VERSION: "3.14.0" .lint-template: &lint image: alpine/helm:${HELM_VERSION} script: - helm lint charts/${CHART_NAME} lint: <<: *lint variables: CHART_NAME: "my-application" rules: - changes: - charts/**/* test: image: quay.io/helmpack/chart-testing:latest script: - ct lint --target-branch main - ct install --target-branch main rules: - changes: - charts/**/* release: image: alpine/helm:${HELM_VERSION} script: - helm package charts/${CHART_NAME} - helm registry login ${HARBOR_URL} -u ${HARBOR_USER} -p ${HARBOR_PASSWORD} - helm push ${CHART_NAME}-*.tgz oci://${HARBOR_URL}/helm-charts rules: - if: $CI_COMMIT_BRANCH == "main" changes: - charts/**/*
九、运维最佳实践 9.1 命名规范 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 labels: app.kubernetes.io/name: my-application app.kubernetes.io/instance: my-release app.kubernetes.io/version: "2.5.0" app.kubernetes.io/component: api app.kubernetes.io/part-of: my-system app.kubernetes.io/managed-by: helm
9.2 Values 文件管理 1 2 3 4 5 6 7 8 values/ ├── values.yaml # 默认值(开发环境) ├── values-staging.yaml # 预发环境 ├── values-prod.yaml # 生产环境 ├── values-dr.yaml # 灾备环境 └── secrets/ ├── values-secrets.yaml.enc └── values-secrets-prod.yaml.enc
9.3 多环境部署策略 1 2 3 4 5 6 7 8 9 10 helm install myapp-dev ./my-chart -f values.yaml -n dev helm install myapp-staging ./my-chart -f values-staging.yaml -n staging helm install myapp-prod ./my-chart -f values-prod.yaml -n prod helm install myapp-prod ./my-chart \ --set replicaCount=5 \ --set resources.limits.cpu=4000m \ --set ingress.hosts[0].host=api-prod.company.com
9.4 备份与恢复 1 2 3 4 5 6 7 8 9 10 11 12 13 helm get manifest my-release > my-release-manifest.yaml helm get values my-release > my-release-values.yaml for release in $(helm list -q); do mkdir -p backup/$release helm get manifest $release > backup/$release /manifest.yaml helm get values $release > backup/$release /values.yaml done helm install my-release ./my-chart -f backup/my-release/values.yaml
9.5 安全实践 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 secret: create: true data: {} podSecurityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 1000 securityContext: readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: - ALL networkPolicy: enabled: true ingress: - from: - namespaceSelector: matchLabels: name: ingress-nginx egress: - to: - namespaceSelector: matchLabels: name: database
9.6 监控与告警 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 serviceMonitor: enabled: true namespace: monitoring interval: 30s scrapeTimeout: 10s labels: release: prometheus prometheusRule: enabled: true rules: - alert: HelmReleaseFailed expr: helm_release_info{status="failed"} == 1 for: 5m labels: severity: critical annotations: summary: "Helm Release 部署失败" description: "Release {{ $labels.release }} 部署失败"
十、常见问题与解决方案 10.1 Release 卡在 pending 状态 1 2 3 4 5 6 7 8 9 kubectl get pods -n <namespace> kubectl describe pod <pod-name> -n <namespace> kubectl get secret -n <namespace> | grep sh.helm.release kubectl delete secret sh.helm.release.v1.<release>.v<version> -n <namespace>
10.2 升级失败无法回滚 1 2 3 4 5 6 7 8 9 helm history my-release helm rollback my-release <revision> --force helm uninstall my-release --no-hooks helm install my-release ./my-chart -f values.yaml
10.3 Chart 依赖问题 1 2 3 4 5 6 7 8 9 helm dependency update helm dependency list rm -rf charts/helm dependency build
10.4 模板渲染错误 1 2 3 4 5 6 7 8 helm template my-release ./my-chart --debug helm lint ./my-chart --with-subcharts
十一、总结 Helm 作为 Kubernetes 事实标准的包管理工具,具有以下优势:
简化部署 : 一键部署复杂应用
版本管理 : 清晰的 Release 版本历史
配置复用 : Values 文件支持多环境
生态丰富 : 大量现成 Chart 可用
CI/CD 友好 : 易于集成自动化流程
建议在企业环境中:
建立内部 Helm 仓库,统一管理 Chart
制定 Chart 开发规范和审核流程
集成 CI/CD 实现自动化部署
使用 helm-secrets 等工具管理敏感信息
定期审计和更新 Chart 依赖
十二、参考资料
Helm 官方文档 - https://helm.sh/docs/
Helm Chart 开发指南 - https://helm.sh/docs/chart_template_guide/
Artifact Hub(Chart 搜索) - https://artifacthub.io/
Bitnami Charts - https://github.com/bitnami/charts
Helm 最佳实践 - https://helm.sh/docs/chart_best_practices/
Helm 插件列表 - https://helm.sh/docs/community/related/#helm-plugins