Helm 图表:Kubernetes 包管理
使用 Helm 包管理的 Kubernetes 部署
Helm 已彻底改变 Kubernetes 应用程序部署,通过引入传统操作系统中熟悉的软件包管理概念。
随着 Kubernetes 的采用率增长,管理包含数十个 YAML 文件的复杂应用程序变得具有挑战性。Helm Charts 通过将所有资源打包成版本化、可配置的软件包来解决这个问题。
这张漂亮的图片是由 AI 模型 Flux 1 dev 生成的。
了解 Helm:Kubernetes 的软件包管理器
Helm 对 Kubernetes 的作用,就像 apt 对 Debian、yum 对 RedHat 或 Homebrew 对 macOS 的作用一样。它将 Kubernetes 应用程序打包成 Charts – 一组描述相关 Kubernetes 资源的文件集合。一个 Chart 可能部署一个完整的应用程序堆栈:Web 服务器、数据库、缓存层、入口规则和监控组件。对于 Kubernetes 新手,Kubernetes 快速参考 提供了启动所需的必备命令和概念。
为什么 Helm 在现代 DevOps 中很重要
复杂性降低:您不再需要管理 20 多个 YAML 文件,而是通过可自定义的值管理一个 Chart。
可重复性:通过环境特定的值覆盖,可以在开发、测试和生产环境中部署相同的配置。这对于部署需要一致性的复杂微服务架构尤其有价值。
版本控制:Charts 是版本化的,便于轻松回滚和升级跟踪。
社区生态系统:通过 Artifact Hub(以前称为 Helm Hub)可以获取数千个预构建的 Charts,用于流行的 PostgreSQL、Redis、NGINX、Prometheus 等应用程序。
模板功能:Go 模板可以根据输入值动态生成资源,减少重复。
Helm 架构和核心概念
Helm 3 架构
Helm 3 通过移除 Helm 2 中有问题的服务器端组件 Tiller 简化了架构:
- Helm 客户端:与 Kubernetes API 直接交互的 CLI 工具
- Chart:包含模板和元数据的软件包格式
- Release:在 Kubernetes 集群中运行的 Chart 实例
- Repository:Charts 的存储位置(HTTP 服务器或 OCI 注册表)
Helm Chart 的关键组件
my-app-chart/
├── Chart.yaml # Chart 元数据和版本
├── values.yaml # 默认配置值
├── charts/ # 依赖的 Charts
├── templates/ # Kubernetes 资源模板
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── _helpers.tpl # 模板助手
│ └── NOTES.txt # 安装后说明
├── .helmignore # 打包时忽略的文件
├── README.md
└── LICENSE
创建您的第一个 Helm Chart
初始化新 Chart
helm create my-application
cd my-application
这将生成一个包含部署、服务和入口示例模板的初始 Chart。
Chart.yaml:定义元数据
apiVersion: v2
name: my-application
description: 一个生产就绪的应用程序 Chart
type: application
version: 1.0.0 # Chart 版本
appVersion: "2.4.1" # 应用程序版本
maintainers:
- name: 您的团队
email: team@company.com
dependencies:
- name: postgresql
version: "12.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
values.yaml:配置管理
values.yaml 文件定义了用户可以覆盖的默认配置。这种方法将配置与模板分离,使管理不同环境(开发、测试、生产)和自定义部署变得容易,而无需修改模板文件。
replicaCount: 3
image:
repository: myapp/backend
tag: "1.0.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: myapp.example.com
paths:
- path: /
pathType: Prefix
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 80
模板:动态 Kubernetes 清单
模板使用 Go 模板语法动态生成 Kubernetes 资源。这些模板可以生成任何 Kubernetes 资源类型,从简单的 Deployment 到需要持久存储的复杂 StatefulSet。对于需要稳定身份和持久卷的应用程序,您应该使用 StatefulSet 而不是 Deployment,如我们在 Kubernetes 中的 StatefulSets 和持久存储 指南中所述。
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-application.fullname" . }}
labels:
{{- include "my-application.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "my-application.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "my-application.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: 8080
protocol: TCP
resources:
{{- toYaml .Values.resources | nindent 10 }}
模板助手 (_helpers.tpl)
创建可重用的模板函数以避免重复:
{{/*
扩展 Chart 的名称。
*/}}
{{- 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 }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{/*
通用标签
*/}}
{{- define "my-application.labels" -}}
helm.sh/chart: {{ include "my-application.chart" . }}
{{ include "my-application.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
管理 Helm Charts:安装和操作
安装 Chart
# 从仓库安装
helm install my-release bitnami/postgresql
# 从本地目录安装
helm install my-app ./my-application
# 使用自定义值安装
helm install my-app ./my-application -f values-production.yaml
# 使用内联值覆盖安装
helm install my-app ./my-application \
--set replicaCount=5 \
--set image.tag=2.0.0
升级发布
# 使用新值升级
helm upgrade my-app ./my-application -f values-production.yaml
# 失败时自动回滚
helm upgrade my-app ./my-application --atomic --timeout 5m
# 强制资源更新
helm upgrade my-app ./my-application --force
回滚和历史记录
# 查看发布历史
helm history my-app
# 回滚到上一版本
helm rollback my-app
# 回滚到特定版本
helm rollback my-app 3
测试和调试
# 干运行查看生成的清单
helm install my-app ./my-application --dry-run --debug
# 渲染模板而不安装
helm template my-app ./my-application
# 检查 Chart 的问题
helm lint ./my-application
# 使用测试钩子测试发布
helm test my-app
高级 Helm 功能
Chart 依赖
Helm Charts 可以依赖其他 Charts,允许您通过可重用组件构建复杂的应用程序。这对于需要数据库、消息队列或其他支持服务的微服务部署特别有用。在 Chart.yaml 中定义依赖项:
dependencies:
- name: redis
version: "17.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled
- name: postgresql
version: "12.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
更新依赖项:
helm dependency update ./my-application
Helm 钩子用于生命周期管理
钩子在发布生命周期的特定点执行:
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "my-application.fullname" . }}-db-migration
annotations:
"helm.sh/hook": pre-upgrade,pre-install
"helm.sh/hook-weight": "5"
"helm.sh/hook-delete-policy": before-hook-creation
spec:
template:
spec:
containers:
- name: db-migrate
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
command: ["python", "manage.py", "migrate"]
restartPolicy: Never
钩子类型包括:
pre-install:在资源安装之前post-install:在所有资源安装之后pre-upgrade:在升级之前post-upgrade:在升级之后pre-delete:在删除之前post-delete:在删除之后pre-rollback:在回滚之前post-rollback:在回滚之后
条件逻辑和流程控制
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "my-application.fullname" . }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "my-application.fullname" $ }}
port:
number: {{ $.Values.service.port }}
{{- end }}
{{- end }}
{{- end }}
OCI 注册表支持:现代 Chart 分发
自 Helm 3.8 起,OCI(开放容器倡议)注册表支持已稳定,允许将 Charts 与容器镜像一起存储。
发布到 OCI 注册表
# 登录到注册表
helm registry login registry.example.com
# 打包 Chart
helm package ./my-application
# 推送到 OCI 注册表
helm push my-application-1.0.0.tgz oci://registry.example.com/charts
# 从 OCI 注册表安装
helm install my-app oci://registry.example.com/charts/my-application --version 1.0.0
OCI 注册表的优势
- 统一存储:Charts 和镜像在一个地方
- 标准工具:使用现有的注册表基础设施
- 更好的安全性:利用注册表认证和扫描
- 更简单的管理:不需要单独的 Chart 仓库服务器
生产 Helm Charts 的最佳实践
1. 值结构和文档
用注释文档所有值:
# -- 应用程序的副本数
replicaCount: 3
# -- 图像配置
image:
# -- 图像仓库
repository: myapp/backend
# -- 图像拉取策略
pullPolicy: IfNotPresent
# -- 图像标签(默认为 chart appVersion)
tag: ""
2. 资源管理
始终设置资源请求和限制:
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
3. 安全上下文
为容器定义安全上下文:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
4. 健康检查
包括存活和就绪探针:
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
5. ConfigMap 和 Secret 管理
对于生产部署,正确管理 Secret 至关重要。使用外部 Secret 管理器(如 Sealed Secrets、External Secrets Operator 或 Vault)而不是在 values 文件中存储 Secret。这确保了数据库密码、API 密钥和证书等敏感数据的安全处理:
envFrom:
- secretRef:
name: {{ include "my-application.fullname" . }}-secrets
- configMapRef:
name: {{ include "my-application.fullname" . }}-config
6. Schema 验证
创建 values.schema.json 以验证用户输入:
{
"$schema": "https://json-schema.org/draft-07/schema#",
"properties": {
"replicaCount": {
"type": "integer",
"minimum": 1
},
"image": {
"type": "object",
"properties": {
"repository": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"required": ["repository"]
}
},
"required": ["image"]
}
7. NOTES.txt 用于用户指导
提供安装后说明:
1. 通过运行以下命令获取应用程序 URL:
{{- if .Values.ingress.enabled }}
https://{{ (index .Values.ingress.hosts 0).host }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "my-application.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- end }}
2. 监控部署:
kubectl --namespace {{ .Release.Namespace }} get pods -l "app.kubernetes.io/name={{ include "my-application.name" . }}"
Helm Chart 测试和 CI/CD 集成
使用 chart-testing (ct) 进行 Chart 测试
# 安装 chart-testing
brew install chart-testing
# 验证 Charts
ct lint --config ct.yaml
# 安装并测试 Charts
ct install --config ct.yaml
GitHub Actions 示例
name: Helm Chart CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lint-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: 设置 Helm
uses: azure/setup-helm@v3
with:
version: 3.12.0
- name: 设置 chart-testing
uses: helm/chart-testing-action@v2
- name: 验证 Charts
run: ct lint --config ct.yaml
- name: 创建 kind 集群
uses: helm/kind-action@v1
- name: 安装 Charts
run: ct install --config ct.yaml
使用 Helm 的 GitOps:ArgoCD 和 Flux
像 ArgoCD 和 Flux 这样的 GitOps 工具可以与 Helm Charts 无缝集成,实现声明式、自动化的部署。这些工具监视您的 Git 仓库中的更改,并自动同步 Helm 发布,使持续部署变得简单。对于复杂的微服务架构,考虑如何使用分布式事务模式,如 Saga 模式 来管理通过 Helm 部署的服务之间的一致性。
ArgoCD 应用程序
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-application
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/myorg/my-app-chart
targetRevision: main
path: charts/my-application
helm:
valueFiles:
- values-production.yaml
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
Flux HelmRelease
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: my-application
namespace: flux-system
spec:
interval: 5m
chart:
spec:
chart: my-application
version: '1.x.x'
sourceRef:
kind: HelmRepository
name: my-charts
values:
replicaCount: 5
image:
tag: "2.0.0"
解决常见的 Helm 问题
问题:升级失败并处于挂起状态
# 检查发布状态
helm list --all-namespaces
# 获取发布详细信息
helm status my-app -n namespace
# 如果需要,强制删除(谨慎使用)
kubectl delete secret -n namespace -l owner=helm,name=my-app
问题:模板渲染错误
# 调试模板渲染
helm template my-app ./my-application --debug
# 验证 Kubernetes
helm template my-app ./my-application | kubectl apply --dry-run=client -f -
问题:值未应用
# 检查合并后的值
helm get values my-app
# 显示所有计算后的值
helm get values my-app --all
Helm 生态系统和工具
Helm 生态系统包括许多扩展其功能并与其他 Kubernetes 技术集成的工具。当部署需要高级网络功能(如服务到服务通信、流量管理和安全策略)的应用程序时,考虑集成 使用 Istio 和 Linkerd 的服务网格,这些可以通过 Helm Charts 部署和管理。
必要工具
- Helmfile:用于部署 Helm Charts 的声明式规范
- Helm Diff:升级前预览更改
- Helm Secrets:使用 SOPS 管理 Secret
- Nova:查找过时的 Helm Charts
- Pluto:检测过时的 Kubernetes API
示例 Helmfile
repositories:
- name: bitnami
url: https://charts.bitnami.com/bitnami
releases:
- name: postgresql
namespace: database
chart: bitnami/postgresql
version: 12.x.x
values:
- postgresql:
auth:
database: myapp
username: appuser
- name: my-app
namespace: production
chart: ./charts/my-application
values:
- values-production.yaml
needs:
- database/postgresql
Helm 的未来
Helm 生态系统持续发展:
- OCI 原生:完全过渡到 OCI 注册表作为标准
- 改进的安全性:更好的 Secret 管理和签名功能
- 性能:大型 Charts 的更快渲染和安装
- WASM 支持:用于 Chart 插件和扩展的 WebAssembly
- 更好的验证:增强的 Schema 验证和策略执行
结论
Helm 已成为 Kubernetes 软件包管理的事实标准,掌握它是现代 DevOps 实践的关键。通过理解 Chart 结构、模板、值管理以及最佳实践,您可以创建可维护、安全且可扩展的 Kubernetes 部署。
从简单的 Chart 开始,逐步引入钩子和依赖项等高级功能,并与 GitOps 工具集成以实现生产级基础设施。Helm 社区提供了数千个预构建的 Charts,但真正的力量来自于创建定制的 Charts,以满足您组织的需求。无论您是部署无状态应用程序还是需要持久存储的有状态工作负载,Helm 都简化了 Kubernetes 资源管理的复杂性。对于正在设置新 Kubernetes 集群的团队,考虑 使用 Kubespray 安装 Kubernetes 或探索 Kubernetes 发行版,如 k3s 或 MicroK8s 用于开发环境。如果您正在评估哪个发行版适合您的家庭实验室或小型集群需求,请参阅我们的 Kubernetes 发行版全面比较 以获得详细分析。
有用的链接
- 官方 Helm 文档
- Artifact Hub - 发现 Helm Charts
- Helm GitHub 仓库
- Helm 最佳实践指南
- Chart 测试工具
- Helmfile
- ArgoCD
- Flux CD
- Bitnami Charts 仓库
- Kubernetes 快速参考
- 使用 Kubespray 安装 Kubernetes
- 3 节点家庭实验室的 Kubernetes 发行版全面比较
- Kubernetes 发行版 - kubeadm、k3s、MicroK8s、Minikube、Talos Linux 和 RKE2 的概述
- 使用 Istio 和 Linkerd 的服务网格
- Kubernetes 中的 StatefulSets 和持久存储
- 分布式事务中的 Saga 模式