本章概述
Values 文件是 Helm Chart 的核心配置机制,它提供了一种灵活的方式来管理应用程序的配置参数。本章将深入探讨 Values 文件的结构、使用方法以及配置管理的最佳实践。
学习目标
- 理解 Values 文件的作用和重要性
- 掌握 Values 文件的结构和语法
- 学会使用不同层级的 Values 文件
- 了解配置优先级和覆盖机制
- 掌握配置验证和安全管理
- 学习环境特定配置的管理方法
3.1 Values 文件概述
3.1.1 什么是 Values 文件
Values 文件是 YAML 格式的配置文件,用于定义 Chart 模板中使用的变量值。它们提供了一种将配置与模板分离的机制,使得同一个 Chart 可以在不同环境中使用不同的配置。
graph TB
A[Chart 模板] --> B[Values 文件]
B --> C[默认 values.yaml]
B --> D[环境特定 Values]
B --> E[命令行 Values]
C --> F[最终配置]
D --> F
E --> F
F --> G[渲染后的 Kubernetes 资源]
3.1.2 Values 文件的优势
- 配置分离:将配置与模板逻辑分离
- 环境适配:支持多环境配置管理
- 可重用性:同一 Chart 可用于不同场景
- 版本控制:配置变更可追踪
- 安全性:敏感信息可单独管理
3.2 Values 文件结构
3.2.1 基本结构
# values.yaml
# 应用基本信息
app:
name: myapp
version: "1.0.0"
environment: production
# 镜像配置
image:
repository: nginx
tag: "1.21"
pullPolicy: IfNotPresent
pullSecrets: []
# 服务配置
service:
type: ClusterIP
port: 80
targetPort: 8080
annotations: {}
# Ingress 配置
ingress:
enabled: false
className: ""
annotations: {}
hosts:
- host: chart-example.local
paths:
- path: /
pathType: Prefix
tls: []
# 资源限制
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
# 副本数
replicaCount: 1
# 自动扩缩容
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
targetMemoryUtilizationPercentage: 80
# 节点选择器
nodeSelector: {}
# 容忍度
tolerations: []
# 亲和性
affinity: {}
# 安全上下文
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
# 存储配置
persistence:
enabled: false
storageClass: ""
accessMode: ReadWriteOnce
size: 8Gi
# 配置映射
configMap:
enabled: true
data:
app.properties: |
server.port=8080
logging.level.root=INFO
# 密钥
secrets:
enabled: false
data: {}
# 健康检查
healthCheck:
enabled: true
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
3.2.2 嵌套结构示例
# 复杂的嵌套配置
database:
primary:
host: db-primary.example.com
port: 5432
name: myapp
credentials:
username: app_user
passwordSecret: db-password
replica:
enabled: true
host: db-replica.example.com
port: 5432
cache:
redis:
enabled: true
cluster:
enabled: false
standalone:
host: redis.example.com
port: 6379
auth:
enabled: true
passwordSecret: redis-password
monitoring:
prometheus:
enabled: true
scrapeInterval: 30s
path: /metrics
grafana:
enabled: true
dashboards:
- name: app-dashboard
configMap: app-grafana-dashboard
logging:
level: INFO
format: json
outputs:
- console
- file
file:
path: /var/log/app.log
maxSize: 100MB
maxBackups: 5
3.3 Values 文件使用方法
3.3.1 在模板中使用 Values
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.app.name }}
labels:
app: {{ .Values.app.name }}
version: {{ .Values.app.version }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Values.app.name }}
template:
metadata:
labels:
app: {{ .Values.app.name }}
version: {{ .Values.app.version }}
spec:
containers:
- name: {{ .Values.app.name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.targetPort }}
{{- if .Values.healthCheck.enabled }}
livenessProbe:
{{- toYaml .Values.healthCheck.livenessProbe | nindent 10 }}
readinessProbe:
{{- toYaml .Values.healthCheck.readinessProbe | nindent 10 }}
{{- end }}
{{- if .Values.resources }}
resources:
{{- toYaml .Values.resources | nindent 10 }}
{{- end }}
{{- if .Values.configMap.enabled }}
volumeMounts:
- name: config
mountPath: /etc/config
{{- end }}
{{- if .Values.configMap.enabled }}
volumes:
- name: config
configMap:
name: {{ .Values.app.name }}-config
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
3.3.2 条件渲染
# templates/ingress.yaml
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ .Values.app.name }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ $.Values.app.name }}
port:
number: {{ $.Values.service.port }}
{{- end }}
{{- end }}
{{- end }}
3.3.3 循环和列表处理
# templates/configmap.yaml
{{- if .Values.configMap.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Values.app.name }}-config
data:
{{- range $key, $value := .Values.configMap.data }}
{{ $key }}: |
{{- $value | nindent 4 }}
{{- end }}
{{- end }}
---
# templates/secrets.yaml
{{- if .Values.secrets.enabled }}
apiVersion: v1
kind: Secret
metadata:
name: {{ .Values.app.name }}-secret
type: Opaque
data:
{{- range $key, $value := .Values.secrets.data }}
{{ $key }}: {{ $value | b64enc }}
{{- end }}
{{- end }}
3.4 配置优先级和覆盖
3.4.1 优先级顺序
Helm 按以下优先级顺序合并 Values:
- 命令行参数 (
--set
和--set-string
) - 用户指定的 Values 文件 (
-f
或--values
) - Chart 的
values.yaml
文件 - 依赖 Chart 的默认值
# 优先级示例
helm install myapp ./mychart \
-f values-prod.yaml \
--set image.tag=v2.0.0 \
--set replicaCount=3
3.4.2 环境特定配置
# values-dev.yaml
app:
environment: development
image:
tag: "latest"
pullPolicy: Always
replicaCount: 1
resources:
limits:
cpu: 200m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
ingress:
enabled: true
hosts:
- host: myapp-dev.example.com
paths:
- path: /
pathType: Prefix
database:
primary:
host: db-dev.example.com
logging:
level: DEBUG
# values-prod.yaml
app:
environment: production
image:
tag: "v1.2.3"
pullPolicy: IfNotPresent
replicaCount: 3
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 70
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
database:
primary:
host: db-prod.example.com
replica:
enabled: true
host: db-replica-prod.example.com
logging:
level: WARN
3.4.3 部署不同环境
# 开发环境部署
helm install myapp-dev ./mychart \
-f values-dev.yaml \
--namespace dev
# 生产环境部署
helm install myapp-prod ./mychart \
-f values-prod.yaml \
--namespace prod
# 临时覆盖配置
helm upgrade myapp-prod ./mychart \
-f values-prod.yaml \
--set image.tag=v1.2.4 \
--namespace prod
3.5 配置验证
3.5.1 JSON Schema 验证
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"app": {
"type": "object",
"properties": {
"name": {
"type": "string",
"pattern": "^[a-z0-9-]+$"
},
"version": {
"type": "string",
"pattern": "^v?[0-9]+\\.[0-9]+\\.[0-9]+$"
},
"environment": {
"type": "string",
"enum": ["development", "staging", "production"]
}
},
"required": ["name", "version"]
},
"image": {
"type": "object",
"properties": {
"repository": {
"type": "string"
},
"tag": {
"type": "string"
},
"pullPolicy": {
"type": "string",
"enum": ["Always", "IfNotPresent", "Never"]
}
},
"required": ["repository", "tag"]
},
"replicaCount": {
"type": "integer",
"minimum": 1,
"maximum": 100
},
"resources": {
"type": "object",
"properties": {
"limits": {
"type": "object",
"properties": {
"cpu": {"type": "string"},
"memory": {"type": "string"}
}
},
"requests": {
"type": "object",
"properties": {
"cpu": {"type": "string"},
"memory": {"type": "string"}
}
}
}
}
},
"required": ["app", "image"]
}
3.5.2 模板中的验证
# templates/_helpers.tpl
{{/*
验证必需的值
*/}}
{{- define "mychart.validateValues" -}}
{{- if not .Values.app.name -}}
{{- fail "app.name is required" -}}
{{- end -}}
{{- if not .Values.image.repository -}}
{{- fail "image.repository is required" -}}
{{- end -}}
{{- if not .Values.image.tag -}}
{{- fail "image.tag is required" -}}
{{- end -}}
{{- if lt (.Values.replicaCount | int) 1 -}}
{{- fail "replicaCount must be at least 1" -}}
{{- end -}}
{{- end -}}
{{/*
验证环境配置
*/}}
{{- define "mychart.validateEnvironment" -}}
{{- $validEnvs := list "development" "staging" "production" -}}
{{- if not (has .Values.app.environment $validEnvs) -}}
{{- fail (printf "Invalid environment '%s'. Must be one of: %s" .Values.app.environment (join ", " $validEnvs)) -}}
{{- end -}}
{{- end -}}
# templates/deployment.yaml
{{- include "mychart.validateValues" . -}}
{{- include "mychart.validateEnvironment" . -}}
apiVersion: apps/v1
kind: Deployment
# ... 其余配置
3.6 安全配置管理
3.6.1 敏感信息处理
# values.yaml - 不包含敏感信息
database:
primary:
host: db.example.com
port: 5432
name: myapp
credentials:
usernameSecret: db-credentials
usernameKey: username
passwordSecret: db-credentials
passwordKey: password
cache:
redis:
host: redis.example.com
port: 6379
auth:
enabled: true
passwordSecret: redis-credentials
passwordKey: password
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.app.name }}
spec:
template:
spec:
containers:
- name: {{ .Values.app.name }}
env:
- name: DB_HOST
value: {{ .Values.database.primary.host }}
- name: DB_PORT
value: {{ .Values.database.primary.port | quote }}
- name: DB_NAME
value: {{ .Values.database.primary.name }}
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: {{ .Values.database.primary.credentials.usernameSecret }}
key: {{ .Values.database.primary.credentials.usernameKey }}
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.database.primary.credentials.passwordSecret }}
key: {{ .Values.database.primary.credentials.passwordKey }}
{{- if .Values.cache.redis.auth.enabled }}
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.cache.redis.auth.passwordSecret }}
key: {{ .Values.cache.redis.auth.passwordKey }}
{{- end }}
3.6.2 创建密钥的脚本
#!/bin/bash
# scripts/create-secrets.sh
set -e
NAMESPACE=${1:-default}
echo "Creating secrets in namespace: $NAMESPACE"
# 创建数据库凭据
kubectl create secret generic db-credentials \
--from-literal=username=myapp_user \
--from-literal=password=secure_db_password \
--namespace=$NAMESPACE \
--dry-run=client -o yaml | kubectl apply -f -
# 创建 Redis 凭据
kubectl create secret generic redis-credentials \
--from-literal=password=secure_redis_password \
--namespace=$NAMESPACE \
--dry-run=client -o yaml | kubectl apply -f -
echo "Secrets created successfully"
3.7 高级配置技巧
3.7.1 动态配置生成
# templates/_config.tpl
{{- define "mychart.config" -}}
{{- $config := dict -}}
{{- $_ := set $config "server.port" .Values.service.targetPort -}}
{{- $_ := set $config "logging.level.root" .Values.logging.level -}}
{{- $_ := set $config "app.name" .Values.app.name -}}
{{- $_ := set $config "app.version" .Values.app.version -}}
{{- $_ := set $config "app.environment" .Values.app.environment -}}
{{- if .Values.database.primary.host -}}
{{- $_ := set $config "spring.datasource.url" (printf "jdbc:postgresql://%s:%d/%s" .Values.database.primary.host (.Values.database.primary.port | int) .Values.database.primary.name) -}}
{{- end -}}
{{- if .Values.cache.redis.enabled -}}
{{- $_ := set $config "spring.redis.host" .Values.cache.redis.standalone.host -}}
{{- $_ := set $config "spring.redis.port" .Values.cache.redis.standalone.port -}}
{{- end -}}
{{- if .Values.monitoring.prometheus.enabled -}}
{{- $_ := set $config "management.endpoints.web.exposure.include" "health,info,metrics,prometheus" -}}
{{- $_ := set $config "management.endpoint.prometheus.enabled" true -}}
{{- end -}}
{{- range $key, $value := $config }}
{{ $key }}={{ $value }}
{{- end -}}
{{- end -}}
3.7.2 条件配置合并
# templates/_helpers.tpl
{{/*
合并默认配置和用户配置
*/}}
{{- define "mychart.mergeConfig" -}}
{{- $defaultConfig := dict "timeout" 30 "retries" 3 "debug" false -}}
{{- $userConfig := .Values.config | default dict -}}
{{- $finalConfig := merge $userConfig $defaultConfig -}}
{{- toYaml $finalConfig -}}
{{- end -}}
3.7.3 多环境配置模板
# values-template.yaml
app:
name: myapp
version: "${APP_VERSION}"
environment: "${ENVIRONMENT}"
image:
repository: "${IMAGE_REPOSITORY}"
tag: "${IMAGE_TAG}"
replicaCount: ${REPLICA_COUNT}
resources:
limits:
cpu: "${CPU_LIMIT}"
memory: "${MEMORY_LIMIT}"
requests:
cpu: "${CPU_REQUEST}"
memory: "${MEMORY_REQUEST}"
database:
primary:
host: "${DB_HOST}"
port: ${DB_PORT}
name: "${DB_NAME}"
#!/bin/bash
# scripts/generate-values.sh
ENVIRONMENT=$1
VALUES_TEMPLATE="values-template.yaml"
VALUES_OUTPUT="values-${ENVIRONMENT}.yaml"
case $ENVIRONMENT in
"dev")
export APP_VERSION="latest"
export IMAGE_REPOSITORY="myapp"
export IMAGE_TAG="dev"
export REPLICA_COUNT=1
export CPU_LIMIT="200m"
export MEMORY_LIMIT="256Mi"
export CPU_REQUEST="100m"
export MEMORY_REQUEST="128Mi"
export DB_HOST="db-dev.example.com"
export DB_PORT=5432
export DB_NAME="myapp_dev"
;;
"prod")
export APP_VERSION="v1.0.0"
export IMAGE_REPOSITORY="myapp"
export IMAGE_TAG="v1.0.0"
export REPLICA_COUNT=3
export CPU_LIMIT="1000m"
export MEMORY_LIMIT="1Gi"
export CPU_REQUEST="500m"
export MEMORY_REQUEST="512Mi"
export DB_HOST="db-prod.example.com"
export DB_PORT=5432
export DB_NAME="myapp_prod"
;;
*)
echo "Unknown environment: $ENVIRONMENT"
exit 1
;;
esac
envsubst < $VALUES_TEMPLATE > $VALUES_OUTPUT
echo "Generated $VALUES_OUTPUT for $ENVIRONMENT environment"
3.8 实践练习
3.8.1 练习1:创建多环境配置
创建一个 Web 应用的 Chart,包含以下配置:
- 基础 values.yaml
- 开发环境配置 values-dev.yaml
- 生产环境配置 values-prod.yaml
- 配置验证逻辑
# 创建 Chart
helm create webapp
cd webapp
# 编辑 values.yaml
vim values.yaml
# 创建环境特定配置
vim values-dev.yaml
vim values-prod.yaml
# 验证配置
helm template . -f values-dev.yaml
helm template . -f values-prod.yaml
# 部署测试
helm install webapp-dev . -f values-dev.yaml --dry-run
helm install webapp-prod . -f values-prod.yaml --dry-run
3.8.2 练习2:配置安全管理
实现敏感信息的安全管理:
- 创建密钥管理模板
- 实现配置验证
- 编写部署脚本
# 创建密钥
kubectl create secret generic app-secrets \
--from-literal=db-password=secret123 \
--from-literal=api-key=abc123
# 验证模板
helm template . --set secrets.enabled=true
# 部署应用
helm install myapp . --set secrets.enabled=true
3.8.3 练习3:动态配置生成
创建一个可以根据环境动态生成配置的 Chart:
# 练习目标配置结构
config:
database:
connections: 10
timeout: 30
cache:
ttl: 3600
maxSize: 1000
features:
enableMetrics: true
enableTracing: false
3.9 故障排除
3.9.1 常见配置问题
YAML 语法错误 “`bash
验证 YAML 语法
yaml-lint values.yaml
使用 Helm 验证
helm template . -f values.yaml
2. **配置覆盖不生效**
```bash
# 检查配置合并结果
helm template . -f values.yaml --debug
# 查看最终配置
helm get values RELEASE_NAME
模板渲染错误 “`bash
调试模板
helm template . –debug
检查特定模板
helm template . –show-only templates/deployment.yaml
### 3.9.2 调试技巧
```yaml
# 在模板中添加调试信息
{{- if .Values.debug }}
# DEBUG: Current values
# {{- toYaml .Values | nindent 2 }}
{{- end }}
# 启用调试模式
helm install myapp . --set debug=true --debug
# 查看渲染结果
helm template myapp . --set debug=true
3.10 本章小结
核心概念回顾
- Values 文件:Helm Chart 的配置管理核心
- 配置层次:默认值、环境配置、命令行覆盖
- 模板集成:在模板中使用 Values 的方法
- 安全管理:敏感信息的安全处理
- 配置验证:确保配置的正确性和安全性
技术要点总结
- Values 文件使用 YAML 格式,支持嵌套结构
- 配置优先级:命令行 > 用户文件 > 默认文件
- 模板中通过
.Values
对象访问配置 - 支持条件渲染和循环处理
- 可以实现配置验证和安全管理
最佳实践
- 结构化配置:使用清晰的层次结构组织配置
- 环境分离:为不同环境创建专门的配置文件
- 安全优先:敏感信息使用 Secret 管理
- 配置验证:实现必要的配置验证逻辑
- 文档完善:为配置项提供清晰的注释和说明
下一章预告
下一章我们将学习「依赖管理与子图表」,探讨如何管理 Chart 之间的依赖关系,以及如何使用子图表构建复杂的应用架构。我们将深入了解依赖声明、版本管理、子图表配置等高级主题。