如何使用 helm 解析外部 INI 文件并创建 Secret?
可以用 --set-file 将外部 INI 文件的内容传给 Helm,再在模板中逐行处理:跳过 section、空行和注释,按第一个 = 拆分键和值,生成 Secret。
这种写法适用于 AWS credentials 这类简单的 INI 文件。如果文件包含多行值、转义或特殊的引号规则,建议先用专门的 INI 解析器处理。
修正参数名称和传入方式
模板使用 .Values.secretPath,命令中的参数也要写成 secretPath。问题中的 secrePath 少了一个 t。
helm install my-release ./my-chart \
--set-file secretPath="$HOME/.aws/credentials"
将 ./my-chart 替换为实际的 Chart 路径。使用 "$HOME/..." 可以避免依赖 shell 对参数中 ~ 的展开行为。
--set-file 会读取文件,将完整内容赋给 .Values.secretPath。原来的表达式:
{{ .Values.secretPath | b64enc | quote }}
会把整个文件编码,包括 [default] 等 section 行。b64enc 只做 Base64 编码,不会解析 INI。
解析文件并保留 .env 这个 Secret 键
假设输入文件如下:
[default]
aws_access_key_id = EXAMPLE_ACCESS_KEY
aws_secret_access_key = example/secret+value=
可以将 templates/secret.yaml 写成:
{{- $content := required "请通过 --set-file secretPath=文件路径 传入 INI 内容" .Values.secretPath -}}
{{- $pairs := dict -}}
{{- range $index, $rawLine := splitList "\n" $content -}}
{{- $line := trim $rawLine -}}
{{- $isComment := or (hasPrefix "#" $line) (hasPrefix ";" $line) -}}
{{- $isSection := and (hasPrefix "[" $line) (hasSuffix "]" $line) -}}
{{- if and (ne $line "") (not $isComment) (not $isSection) -}}
{{- $parts := regexSplit "=" $line 2 -}}
{{- if ne (len $parts) 2 -}}
{{- fail (printf "INI 第 %d 行缺少 =" (add1 $index)) -}}
{{- end -}}
{{- $key := trim (index $parts 0) -}}
{{- $value := trim (index $parts 1) -}}
{{- if eq $key "" -}}
{{- fail (printf "INI 第 %d 行的键为空" (add1 $index)) -}}
{{- end -}}
{{- if hasKey $pairs $key -}}
{{- fail (printf "忽略 section 后出现重复键:%s" $key) -}}
{{- end -}}
{{- $_ := set $pairs $key $value -}}
{{- end -}}
{{- end -}}
{{- if eq (len $pairs) 0 -}}
{{- fail "INI 中没有可用的键值对" -}}
{{- end -}}
{{- $lines := list -}}
{{- range $key, $value := $pairs -}}
{{- $lines = append $lines (printf "%s=%s" $key $value) -}}
{{- end -}}
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
.env: {{ printf "%s\n" (join "\n" $lines) | b64enc | quote }}
生成的 Secret 仍然使用 .env 作为键,其内容解码后类似:
aws_access_key_id=EXAMPLE_ACCESS_KEY
aws_secret_access_key=example/secret+value=
regexSplit "=" $line 2 最多将一行拆成两部分,值中的其他 = 会保留。模板还会去掉每行首尾的空白,以及键和值两侧的空白。
将每个 INI 键生成为独立的 Secret 键
保留上面的解析部分,将生成 $lines 的部分及其后续内容替换为:
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
{{- range $key, $value := $pairs }}
{{ $key | quote }}: {{ $value | b64enc | quote }}
{{- end }}
这样,Secret 中会直接包含 aws_access_key_id、aws_secret_access_key 等键,每个值分别进行 Base64 编码。
输入键只能包含字母、数字、-、_ 或 .,以符合 Kubernetes Secret 的键名要求。也可以用 stringData 写入普通字符串,由 Kubernetes 处理编码,此时应去掉 b64enc。
使用限制和注意事项
- AWS credentials 文件中的不同 section 通常包含相同的键,忽略 section 后会发生冲突。示例遇到重复键会直接报错,需要先选定要使用的 profile,或明确覆盖规则。
- 这段模板只处理简单 INI:跳过整行
#、;注释和独占一行的[section],不处理行尾注释、续行、引号去除或转义。key="value"中的引号会保留在值中。 - 示例直接拼接
key=value,没有完成 dotenv 语法转换。如果值包含特殊字符,需要确认应用使用的 dotenv 解析器如何处理。删除 section 后,文件也不再保持 AWS credentials 的原始格式。 - Secret 中的键不会自动变成环境变量。
.env需要通过卷挂载并由应用读取;独立键可以通过secretKeyRef或envFrom引用,具体名称还需符合应用的要求。 - Base64 不提供加密保护。使用真实凭据执行
helm template等预览命令时,输出会包含可还原的 Secret 内容,应避免将其写入公开日志或版本库。
备注:内容仅供参考。
