PAYATHON 2026

如何使用 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 内容,应避免将其写入公开日志或版本库。

备注:内容仅供参考。