Helm:Kubernetes 包管理利器
深入理解 Helm 的 Chart 结构、模板语法、values 配置管理,以及 Helm 在 CI/CD 中的最佳实践。
概述
Helm 是 Kubernetes 的包管理器,类似 Linux 的 apt/yum 或前端的 npm。它允许开发者将 Kubernetes 资源打包成可重用的 Chart,方便分发和部署。本文将深入探讨:
学习目标:
- 理解 Helm 的设计理念与核心概念
- 掌握 Chart 的目录结构和模板语法
- 学会使用 values 文件进行配置管理
- 了解 Helm 仓库的创建与维护
- 掌握 Helm 在 CI/CD 中的集成方法
Helm 核心概念
为什么需要 Helm?
┌─────────────────────────────────────────────────────────────────┐
│ Helm 解决的问题 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 传统方式:直接部署 YAML │
│ │
│ ├── deployment.yaml │
│ ├── service.yaml │
│ ├── configmap.yaml │
│ ├── ingress.yaml │
│ └── secret.yaml │
│ │
│ 问题: │
│ ✗ 大量文件难以管理 │
│ ✗ 环境差异需要复制多份 │
│ ✗ 版本跟踪困难 │
│ ✗ 难以复用和分享 │
│ │
│ Helm 方式:Chart 包 │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ myapp-1.0.0.tgz(Chart 包) │ │
│ │ │ │
│ │ ├── Chart.yaml │ │
│ │ ├── values.yaml │ │
│ │ └── templates/ │ │
│ │ ├── deployment.yaml │ │
│ │ ├── service.yaml │ │
│ │ └── ... │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 优点: │
│ ✓ 一键部署/升级/回滚 │
│ ✓ 环境差异化配置 │
│ ✓ 版本管理和可复现 │
│ ✓ 社区分享和复用 │
│ │
└─────────────────────────────────────────────────────────────────┘
Helm 核心术语
┌─────────────────────────────────────────────────────────────────┐
│ Helm 核心概念 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌────────────┐ ┌────────────┐ │
│ │ Repo │ │ Chart │ │ Release │ │
│ ├─────────┤ ├────────────┤ ├────────────┤ │
│ │ Chart │ │ 打包格式 │ │ 已部署实例 │ │
│ │ 存储仓库 │ │ 包含模板和 │ │ Chart 运行 │ │
│ │ │ │ 配置 │ │ 在集群的 │ │
│ │ helm.sh │ │ │ │ 实例 │ │
│ └─────────┘ └────────────┘ └────────────┘ │
│ │ │ │
│ │ install │ │
│ ▼ ▼ │
│ ┌────────────┐ ┌────────────┐ │
│ │ Version │ │ History │ │
│ ├────────────┤ ├────────────┤ │
│ │ Chart 版本 │ │ 升级/回滚 │ │
│ │ 1.0.0 → │ │ 历史记录 │ │
│ │ 2.0.0 │ │ │ │
│ └────────────┘ └────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Helm 工作原理
┌─────────────────────────────────────────────────────────────────┐
│ Helm 工作流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 用户命令:helm install myapp ./myapp-chart │
│ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Helm Client │ │
│ │ │ │
│ │ 1. 读取 Chart.yaml │ │
│ │ 2. 合并 values.yaml(+ 用户自定义值) │ │
│ │ 3. 执行模板渲染(Go template) │ │
│ │ 4. 生成最终 YAML │ │
│ │ 5. 发送到 kube-apiserver │ │
│ │ 6. 保存 release 信息到 ConfigMap/Secret │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Kubernetes Cluster │ │
│ │ │ │
│ │ Deployment ← Service ← ConfigMap ← Secret │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Chart 结构
Chart 目录结构
mychart/
├── Chart.yaml # Chart 元数据(名称、版本、依赖等)
├── values.yaml # 默认配置
├── values.schema.json # 配置校验 schema(可选)
├── charts/ # 依赖的子 Chart
│ └── common-1.0.0.tgz
├── templates/ # Kubernetes 资源模板
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── _helpers.tpl # 公共模板函数
│ └── NOTES.txt # 部署后显示的说明
└── crds/ # 自定义 CRD(可选)
└── mycrd.yaml
Chart.yaml 详解
# Chart.yaml
apiVersion: v2 # Chart API 版本(v2 支持依赖)
name: myapp # Chart 名称
description: My Kubernetes application # 描述
type: application # application 或 library
version: 1.0.0 # Chart 版本(语义化)
appVersion: "2.0" # 应用版本
keywords: # 关键字(用于搜索)
- web
- http
- api
home: https://github.com/myorg/myapp # 主页
sources: # 代码仓库
- https://github.com/myorg/myapp
maintainers: # 维护者
- name: John Doe
email: john@example.com
dependencies: # Chart 依赖(Helm v3)
- name: common
version: "1.x.x"
repository: "https://charts.bitnami.com"
- name: redis
version: "17.x.x"
repository: "https://charts.bitnami.com"
condition: redis.enabled # 条件启用
tags:
- cache
values.yaml 结构
# values.yaml - 默认配置
# 全局配置(所有模板可用)
global:
imageRegistry: myregistry.com
imagePullSecrets:
- name: my-registry-secret
# 镜像配置
image:
repository: myapp
tag: "1.0.0"
pullPolicy: IfNotPresent
# 副本数
replicaCount: 3
# 服务配置
service:
type: ClusterIP
port: 80
# 资源配置
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 100m
memory: 128Mi
# Ingress 配置
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: myapp.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: myapp-tls
hosts:
- myapp.example.com
# 持久化存储
persistence:
enabled: true
size: 10Gi
storageClass: "fast-storage"
# 标签和注解
labels: {}
annotations: {}
模板语法
Go 模板基础
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }} # Release 名称
labels:
app: {{ include "mychart.fullname" . }}
chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
version: {{ .Chart.AppVersion }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ include "mychart.fullname" . }}
template:
metadata:
labels:
app: {{ include "mychart.fullname" . }}
spec:
serviceAccountName: {{ .Release.Name }}-sa
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
内置对象
┌─────────────────────────────────────────────────────────────────┐
│ Helm 内置对象 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ .Release │
│ ├── .Release.Name # Release 名称 │
│ ├── .Release.Namespace # 命名空间 │
│ ├── .Release.Service # 服务名称(helm) │
│ ├── .Release.Revision # 版本号(1, 2, 3...) │
│ └── .Release.IsUpgrade # 是否升级 │
│ │
│ .Chart │
│ ├── .Chart.Name # Chart 名称 │
│ ├── .Chart.Version # Chart 版本 │
│ ├── .Chart.AppVersion # 应用版本 │
│ └── .Chart.Description # 描述 │
│ │
│ .Values # 用户提供的 values │
│ .Values.image.repository # 访问值 │
│ │
│ .Capabilities │
│ ├── .Capabilities.APIVersions.Has apps/v1 # API 可用 │
│ └── .Capabilities.KubeVersion # K8s 版本 │
│ │
│ .Files # Chart 内的文件 │
│ .Files.Get "config.yaml" # 获取文件内容 │
│ │
│ .Capabilities.APIVersions.Has networking.k8s.io/v1/Ingress │
│ │
└─────────────────────────────────────────────────────────────────┘
模板函数
# 常用模板函数
# 字符串函数
{{ .Values.name | default "default-name" }}
{{ .Values.name | upper }}
{{ .Values.name | lower }}
{{ .Values.name | title }}
{{ .Values.name | trim }}
{{ "hello world" | replace "world" "helm" }}
# 数值函数
{{ .Values.replicaCount | int }}
{{ 1.234 | printf "%.2f" }}
# 条件判断
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
...
{{- end }}
# with 作用域
{{- with .Values.image }}
image: {{ .repository }}:{{ .tag }}
{{- end }}
# range 循环
{{- range .Values.env }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}
# default 值
image: {{ .Values.image.repository | default "nginx" }}
# required 值(必须存在)
name: {{ required "image name is required" .Values.image.name }}
# lookup 获取资源
{{- $existing := lookup "v1" "ConfigMap" .Release.Namespace "my-config" }}
{{- if $existing }}
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
data: {{ $existing.data }}
{{- else }}
...
{{- end }}
命名模板(_helpers.tpl)
# templates/_helpers.tpl
{{/*
Expand the name of the chart.
*/}}
{{- define "mychart.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "mychart.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 }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "mychart.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "mychart.labels" -}}
app: {{ include "mychart.name" . }}
chart: {{ include "mychart.chart" . }}
release: {{ .Release.Name }}
{{- end }}
NOTES.txt
# templates/NOTES.txt
Thank you for installing {{ .Chart.Name }}.
Your release is named {{ .Release.Name }}.
To learn more about the release, try:
$ helm get all {{ .Release.Name }}
To get the application URL:
{{- if .Values.ingress.enabled }}
{{- range .Values.ingress.hosts }}
http://{{ .host }}
{{- end }}
{{- else }}
# Port forward for local testing
$ kubectl port-forward svc/{{ include "mychart.fullname" . }} {{ .Values.service.port }}:80
{{- end }}
To upgrade the release:
$ helm upgrade {{ .Release.Name }} .
To uninstall the release:
$ helm uninstall {{ .Release.Name }}
条件与循环
条件渲染
# 启用/禁用配置
{{- if .Values.feature.enabled }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: feature-config
data:
feature-flag: "true"
{{- end }}
# 条件赋值
{{ $image := .Values.image.repository }}
{{- if .Values.global.imageRegistry }}
{{ $image = printf "%s/%s" .Values.global.imageRegistry .Values.image.repository }}
{{- end }}
# 多条件
{{- if and .Values.ingress.enabled .Values.ingress.tls.enabled }}
tls:
{{- range .Values.ingress.tls }}
- secretName: {{ .secretName }}
hosts:
{{- range .hosts }}
- {{ . }}
{{- end }}
{{- end }}
{{- end }}
循环遍历
# 遍历列表
{{- range .Values.env }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}
# 遍历 Map
{{- range $key, $value := .Values.config }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
# 遍历带索引
{{- range $index, $service := .Values.services }}
# Service {{ $index }}: {{ $service.name }}
{{- end }}
with 作用域
# 改变当前作用域
{{- with .Values.service }}
type: {{ .type }}
port: {{ .port }}
{{- end }}
# with 内的 else
{{- with .Values.persistence }}
enabled: true
size: {{ .size }}
{{- else }}
enabled: false
{{- end }}
依赖管理
Chart 依赖
# Chart.yaml
apiVersion: v2
name: myapp
version: 1.0.0
dependencies:
- name: postgresql
version: "12.x.x"
repository: "https://charts.bitnami.com"
condition: postgresql.enabled
tags:
- database
- name: redis
version: "17.x.x"
repository: "https://charts.bitnami.com"
condition: redis.enabled
tags:
- cache
- name: common
version: "1.x.x"
repository: "https://charts.bitnami.com"
依赖下载
# 初始化依赖
helm dependency update ./mychart
# 查看依赖
helm dependency list ./mychart
# 输出:
# NAME VERSION REPOSITORY STATUS
# postgresql 12.x.x https://charts.bitnami.com fetched
# redis 17.x.x https://charts.bitnami.com fetched
# common 1.x.x https://charts.bitnami.com fetched
# 更新依赖
helm dependency update ./mychart
# 构建 Chart(打包时)
helm package ./mychart
子 Chart 访问
┌─────────────────────────────────────────────────────────────────┐
│ Chart 依赖作用域 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 父 Chart │
│ │
│ values.yaml │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ global: │ │
│ │ color: blue │ │
│ │ │ │
│ │ postgresql: │ │
│ │ enabled: true │ │
│ │ password: secret123 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ │ 子 Chart 可以访问父 Chart 的 global │
│ ▼ │
│ 子 Chart (postgresql) │
│ │
│ templates/deployment.yaml │
│ env: │
│ - name: PASSWORD │
│ value: {{ .Values.password | default "default" }} │
│ - name: GLOBAL_COLOR │
│ value: {{ .Values.global.color }} │
│ │
│ 注意:子 Chart 不能访问父 Chart 的非 global 配置 │
│ │
└─────────────────────────────────────────────────────────────────┘
共享模板(Library Chart)
# library chart 结构
common/
├── Chart.yaml
├── templates/
│ ├── _deployment.tpl
│ ├── _service.tpl
│ └── _helpers.tpl
└── values.yaml
---
# Chart.yaml
apiVersion: v2
type: library # 关键:类型为 library
name: common
version: 1.0.0
---
# 父 Chart 引用
dependencies:
- name: common
version: "1.x.x"
repository: "file://../common"
多环境配置
环境目录结构
myapp/
├── Chart.yaml
├── values.yaml # 默认值
├── values-staging.yaml # 预发环境
├── values-prod.yaml # 生产环境
└── templates/
└── deployment.yaml
values 文件继承
# values.yaml(默认)
image:
repository: myapp
tag: "1.0.0"
replicaCount: 1
resources:
limits:
cpu: 500m
memory: 512Mi
---
# values-staging.yaml(预发)
image:
tag: "1.1.0-staging"
replicaCount: 2
resources:
limits:
cpu: 1000m
memory: 1Gi
---
# values-prod.yaml(生产)
image:
tag: "1.1.0"
replicaCount: 5
resources:
limits:
cpu: 2000m
memory: 4Gi
部署命令
# 安装到不同环境
helm install myapp ./mychart -f values.yaml
helm install myapp-staging ./mychart \
-f values.yaml \
-f values-staging.yaml
helm install myapp-prod ./mychart \
-f values.yaml \
-f values-prod.yaml
# 升级
helm upgrade myapp-prod ./mychart \
-f values.yaml \
-f values-prod.yaml
# 查看差异
helm diff upgrade myapp-prod ./mychart \
-f values.yaml \
-f values-prod.yaml
命名空间覆盖
# values-prod.yaml
namespace: production
# 安装时指定命名空间
helm install myapp ./mychart \
-n production \
--create-namespace \
-f values-prod.yaml
# 或在 Chart.yaml 中使用
namespace: {{ .Release.Namespace }}
Helm 仓库
添加仓库
# 添加官方仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add prometheus https://prometheus-community.github.io/helm-charts
helm repo add grafana https://grafana.github.io/helm-charts
# 更新仓库索引
helm repo update
# 搜索 Chart
helm search repo nginx
helm search repo prometheus
# 查看仓库列表
helm repo list
# 移除仓库
helm repo remove bitnami
创建私有仓库
# 方式1:ChartMuseum(私有仓库服务)
helm repo add chartmuseum https://chartmuseum.example.com \
--username=admin \
--password=secret
# 方式2:对象存储
# 将 Chart 包上传到 S3/MinIO 等
# 方式3:GitHub Pages
# 1. 创建 GitHub 仓库
# 2. 发布 Chart 包到 gh-pages 分支
# 3. 添加仓库
helm repo add myrepo https://myorg.github.io/charts
# 方式4:Harbor
# Harbor 内置 Chart 仓库支持
打包与发布
# 打包 Chart
helm package ./mychart
# 输出:mychart-1.0.0.tgz
# 签名(可选)
helm package --sign --key mykey --keyring ~/.gnupg/secring.gpg ./mychart
# 上传到私有仓库
curl -u admin:secret -X POST https://chartmuseum.example.com/api/charts \
-F "chart=@mychart-1.0.0.tgz"
# 签名验证
helm verify mychart-1.0.0.tgz
CI/CD 集成
GitHub Actions 示例
# .github/workflows/helm.yml
name: Helm Charts CI/CD
on:
push:
branches: [main]
paths:
- 'charts/**'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Helm
uses: azure/setup-helm@v3
with:
version: v3.14.0
- name: Helm lint
run: |
helm lint ./charts/myapp
- name: Helm template
run: |
helm template myapp ./charts/myapp \
-f ./charts/myapp/values.yaml > /tmp/rendered.yaml
test:
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Kubernetes
uses: azure/setup-kubectl@v4
- name: Helm test
run: |
helm template test-app ./charts/myapp \
--dry-run --debug
deploy-staging:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment: staging
steps:
- uses: actions/checkout@v4
- name: Set up Helm
uses: azure/setup-helm@v3
- name: Configure kubectl
run: |
echo "${{ secrets.KUBE_CONFIG_STAGING }}" | base64 -d > kubeconfig
export KUBECONFIG=kubeconfig
- name: Deploy to Staging
run: |
helm upgrade --install myapp ./charts/myapp \
--namespace staging \
--create-namespace \
--wait --timeout 5m \
--debug
deploy-prod:
needs: deploy-staging
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: Set up Helm
uses: azure/setup-helm@v3
- name: Configure kubectl
run: |
echo "${{ secrets.KUBE_CONFIG_PROD }}" | base64 -d > kubeconfig
export KUBECONFIG=kubeconfig
- name: Diff before deploy
run: |
helm diff upgrade myapp ./charts/myapp \
-f ./charts/myapp/values-prod.yaml \
--namespace production
- name: Deploy to Production
run: |
helm upgrade --install myapp ./charts/myapp \
--namespace production \
-f ./charts/myapp/values.yaml \
-f ./charts/myapp/values-prod.yaml \
--wait --timeout 10m \
--atomic \
--cleanup-on-fail
Helmfile 编排
# helmfile.yaml
repositories:
- name: bitnami
url: https://charts.bitnami.com/bitnami
releases:
- name: myapp
chart: ./charts/myapp
values:
- values.yaml.gotmpl
- environment: {{ .Environment.Name }}
values:
- environments/{{ .Environment.Name }}/values.yaml
namespaces:
- {{ .Environment.Name }}
secrets:
- environments/{{ .Environment.Name }}/secrets.yaml.gotmpl
- name: redis
chart: bitnami/redis
version: "17.x.x"
condition: myapp.redis.enabled
values:
- environments/{{ .Environment.Name }}/redis.yaml
高级技巧
测试 Chart
# Chart.yaml 添加测试
apiVersion: v2
name: myapp
version: 1.0.0
# templates/ 目录添加测试
# tests/ 目录下的资源不会在 install 时部署
templates/
├── deployment.yaml
├── service.yaml
└── tests/
└── test-connection.yaml
# templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "mychart.fullname" . }}-test"
labels:
{{- include "mychart.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox:1.36
command: ['wget']
args: ['{{ include "mychart.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never
# 运行测试
helm test myapp
# 测试钩子类型:
# - test:运行测试
# - pre-install:在安装前执行
# - post-install:在安装后执行
# - pre-upgrade:在升级前执行
# - post-upgrade:在升级后执行
# - pre-rollback:在回滚前执行
# - post-rollback:在回滚后执行
Helm Hooks
# 使用 Hook 执行任务
apiVersion: batch/v1
kind: Job
metadata:
name: database-migration
annotations:
"helm.sh/hook": pre-upgrade,pre-rollback
"helm.sh/hook-weight": "-1" # 权重,越小越先执行
"helm.sh/hook-delete-policy": before-hook-creation
spec:
template:
spec:
containers:
- name: migration
image: myapp-migration:latest
command: ["./migrate.sh"]
restartPolicy: Never
模板调试
# 本地渲染模板
helm template myapp ./mychart
# 调试模式
helm template myapp ./mychart --debug
# 只渲染指定模板
helm template myapp ./mychart --show-only templates/deployment.yaml
# 指定 values
helm template myapp ./mychart -f values-prod.yaml
# 渲染并验证(不安装)
helm install myapp ./mychart --dry-run --debug
# 在集群上模拟安装
helm upgrade --install myapp ./mychart --dry-run --debug --namespace test
常见问题与避坑指南
Q1:如何回滚 Release?
# 查看历史
helm history myapp
# 输出:
# REVISION UPDATED STATUS CHART DESCRIPTION
# 1 2024-05-19 10:00:00 superseded myapp-1.0.0 Install complete
# 2 2024-05-19 11:00:00 deployed myapp-1.1.0 Upgrade complete
# 3 2024-05-19 12:00:00 superseded myapp-1.2.0 Upgrade failed
# 回滚到版本 1
helm rollback myapp 1
# 指定命名空间
helm rollback myapp 1 -n production
Q2:如何处理敏感数据?
# 方式1:外部密钥管理
# values.yaml
image:
password: ""
# 部署时从 Vault 注入
helm upgrade myapp ./mychart \
--set image.password=$(vault kv get -field=password secret/myapp)
# 方式2:SOPS 加密
# .sops.yaml
creation_rules:
- age: >1
# 加密文件
sops --encrypt values.enc.yaml > values.enc.yaml
# 使用加密文件
helm upgrade myapp ./mychart --secrets-file values.enc.yaml
Q3:如何管理多个集群?
# 使用 kubeconfig 或指定 kubeconfig
export KUBECONFIG=/path/to/config
helm list --all-namespaces
# 或在 CI/CD 中使用不同 kubeconfig
Q4:Chart 版本冲突?
# 依赖版本范围
dependencies:
- name: common
version: ">=1.0.0,<2.0.0" # 范围语法
# >= 1.0.0, < 2.0.0
- name: postgresql
version: "~12" # 修定版本
# >=12.0.0, <13.0.0
- name: redis
version: "^17.0.0" # 兼容版本
# >=17.0.0, <18.0.0
总结
┌─────────────────────────────────────────────────────────────────┐
│ 核心要点回顾 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Helm 核心概念 │
│ ├── Chart:打包格式,包含模板和配置 │
│ ├── Release:Chart 在集群中的实例 │
│ └── Repository:Chart 存储仓库 │
│ │
│ Chart 结构 │
│ ├── Chart.yaml:元数据和依赖 │
│ ├── values.yaml:默认配置 │
│ └── templates/:K8s 资源模板 │
│ │
│ 模板语法 │
│ ├── 内置对象:.Release, .Chart, .Values │
│ ├── 模板函数:default, upper, lower, replace... │
│ └── 流程控制:if, with, range, ... │
│ │
│ 依赖管理 │
│ ├── dependencies 定义依赖 │
│ ├── helm dependency update 下载 │
│ └── library chart 共享模板 │
│ │
│ 最佳实践 │
│ ├── 合理使用 _helpers.tpl │
│ ├── values 分层管理环境 │
│ ├── CI/CD 集成自动化 │
│ └── Helm Hooks 处理迁移和清理 │
│ │
└─────────────────────────────────────────────────────────────────┘
思考题
- Helm 和 Kustomize 各有什么优缺点?什么场景下选择哪个?
- 如何设计一个可复用的 Chart 模板库?
- 如何在 Helm 中实现蓝绿部署或金丝雀发布?
引用与参考
下篇预告
下一篇文章我们将探讨 Operator 与 CRD,包括:
- 自定义资源定义
- Operator 模式与控制器
- KubeBuilder 开发框架
- 实战:一个数据库 Operator
敬请期待!