Helm Chart最佳实践:打造生产级Kubernetes应用包
一、Helm概述
Helm是Kubernetes的包管理工具,通过Chart方式打包、分发和管理Kubernetes应用。一个好的Helm Chart不仅要能正确部署应用,还要考虑可配置性、安全性、可维护性等多方面因素。
二、Chart结构规范
2.1 标准Chart目录结构
my-chart/ ├── Chart.yaml # Chart元数据 ├── values.yaml # 默认配置值 ├── charts/ # 依赖的子Chart ├── templates/ # 模板文件目录 │ ├── deployment.yaml │ ├── service.yaml │ ├── ingress.yaml │ └── _helpers.tpl # 辅助模板函数 └── README.md # Chart说明文档2.2 Chart.yaml规范
apiVersion: v2 name: my-chart description: A Helm chart for Kubernetes type: application version: 1.0.0 appVersion: "1.0.0" kubeVersion: ">= 1.21.0-0" keywords: - my-app - example home: https://example.com sources: - https://github.com/example/my-chart maintainers: - name: John Doe email: john@example.com三、模板设计最佳实践
3.1 使用辅助函数
创建_helpers.tpl文件:
{{/* Chart name */}} {{- define "my-chart.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} {{- end -}} {{/* Full name */}} {{- define "my-chart.fullname" -}} {{- $name := default .Chart.Name .Values.nameOverride -}} {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} {{- end -}} {{/* Labels */}} {{- define "my-chart.labels" -}} helm.sh/chart: {{ include "my-chart.name" . }}-{{ .Chart.Version | replace "+" "_" }} app.kubernetes.io/name: {{ include "my-chart.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end -}}3.2 条件渲染
apiVersion: v1 kind: Service metadata: name: {{ include "my-chart.fullname" . }} labels: {{- include "my-chart.labels" . | nindent 4 }} spec: type: {{ .Values.service.type }} {{- if eq .Values.service.type "LoadBalancer" }} loadBalancerIP: {{ .Values.service.loadBalancerIP }} {{- end }} ports: - port: {{ .Values.service.port }} targetPort: http protocol: TCP name: http selector: app.kubernetes.io/name: {{ include "my-chart.name" . }} app.kubernetes.io/instance: {{ .Release.Name }}3.3 数组遍历
apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "my-chart.fullname" . }} spec: template: spec: containers: - name: {{ .Chart.Name }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports: {{- range .Values.service.ports }} - name: {{ .name }} containerPort: {{ .port }} protocol: {{ .protocol }} {{- end }}四、values.yaml设计
4.1 合理的配置层级
# 全局配置 global: imageRegistry: "" imagePullSecrets: [] storageClass: "" # 应用配置 replicaCount: 3 image: repository: my-app tag: latest pullPolicy: IfNotPresent service: type: ClusterIP port: 80 ports: - name: http port: 80 protocol: TCP ingress: enabled: false className: "" hosts: - host: chart-example.local paths: - path: / pathType: ImplementationSpecific resources: limits: cpu: 100m memory: 128Mi requests: cpu: 100m memory: 128Mi autoscaling: enabled: false minReplicas: 1 maxReplicas: 10 targetCPUUtilizationPercentage: 80 targetMemoryUtilizationPercentage: 804.2 默认值设置原则
- 安全性:默认禁用不安全配置
- 合理性:提供合理的默认值
- 灵活性:允许用户覆盖所有配置
- 文档化:为每个配置项添加注释
五、依赖管理
5.1 声明依赖
在Chart.yaml中声明依赖:
dependencies: - name: redis version: 17.3.0 repository: https://charts.bitnami.com/bitnami condition: redis.enabled tags: - database5.2 管理依赖版本
# 更新依赖 helm dependency update # 查看依赖状态 helm dependency list # 打包Chart(包含依赖) helm package --dependency-update .六、安全性最佳实践
6.1 使用Secrets管理敏感数据
apiVersion: v1 kind: Secret metadata: name: {{ include "my-chart.fullname" . }} type: Opaque data: {{- if .Values.secret }} {{- range $key, $value := .Values.secret }} {{ $key }}: {{ $value | b64enc | quote }} {{- end }} {{- end }}6.2 限制容器权限
securityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 1000 allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL6.3 Pod安全标准
podSecurityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault七、可观测性配置
7.1 配置监控
metrics: enabled: true serviceMonitor: enabled: true interval: 30s scrapeTimeout: 10s7.2 配置日志
logging: enabled: true format: json level: info八、测试与验证
8.1 模板测试
# 渲染模板 helm template . # 检查模板语法 helm lint . # 验证安装 helm install --dry-run --debug my-release .8.2 集成测试
使用helm test进行测试:
apiVersion: v1 kind: ConfigMap metadata: name: {{ include "my-chart.fullname" . }}-test data: test.sh: | #!/bin/bash curl -s http://{{ include "my-chart.fullname" . }}:{{ .Values.service.port }}/health --- apiVersion: v1 kind: Pod metadata: name: "{{ include "my-chart.fullname" . }}-test" annotations: "helm.sh/hook": test spec: containers: - name: test image: busybox command: ['sh', '-c', 'source /test/test.sh'] volumeMounts: - name: test mountPath: /test volumes: - name: test configMap: name: {{ include "my-chart.fullname" . }}-test restartPolicy: Never九、版本管理与发布
9.1 版本策略
version: 1.0.0 # Chart版本 appVersion: "2.0.0" # 应用版本版本号遵循Semantic Versioning:
- MAJOR:不兼容的API变更
- MINOR:向后兼容的功能新增
- PATCH:向后兼容的bug修复
9.2 Chart仓库管理
# 创建Chart仓库 helm repo index . # 上传到仓库 helm package . mv my-chart-1.0.0.tgz charts/ helm repo index . --url https://charts.example.com十、高级技巧
10.1 使用模板函数
# 字符串操作 {{ .Values.someValue | upper }} {{ .Values.someValue | trunc 10 }} {{ .Values.someValue | replace "foo" "bar" }} # 条件判断 {{- if .Values.enabled }} # enabled配置 {{- else }} # disabled配置 {{- end }} # 数学运算 {{ add .Values.replicaCount 1 }} {{ mul .Values.resources.limits.cpu 2 }}10.2 自定义模板函数
{{/* 定义自定义函数 */}} {{- define "my-chart.envFromSecret" -}} {{- range $key, $value := .Values.secret }} - name: {{ $key | upper | replace "-" "_" }} valueFrom: secretKeyRef: name: {{ include "my-chart.fullname" . }} key: {{ $key }} {{- end }} {{- end -}}十一、总结
Helm Chart是Kubernetes应用分发的标准方式,遵循最佳实践可以提高Chart的质量和可维护性。建议从模板规范、安全性、可观测性等方面入手,逐步完善Chart设计。
参考资料:
- Helm官方文档
- Helm Chart最佳实践指南
- CNCF Helm Chart标准