Kubernetes multiple Secrets with Helm template and unifying value access with ConfigMaps.

Artiya
BOOTLEGSOFT
Published in
2 min readSep 18, 2020

--

Using Kubernetes Secrets is really hard especially with multiple secret and need to access all value from a single place in the program. The solution I found on the internet is really complex for a beginner like me. I need something that works quickly and simply understandable even it needs to change a little bit of code to make it work.

Use the helm template to read all secrets in the values file and add it to pod environment variables.

1. Add secret in values.yaml separate from configmap and use _ to separate hierarchy like in the YAML file.

.
.
.
secrets:
all:

enc_key: 'njsprlwa8d64fvnsfnjsk61156aodlmr'
enc_iv: '48914829jfs2'
sql_user: "root"
sql_password: "password"
redis_password: "rpass"
redis_prefix: "k34234:"

2. Create file templates/secret.yaml, use Helm template language to loop all secrets in values from key secrets.alland prefix the key with SECRET_ like this:

apiVersion: v1
kind: Secret
metadata:
name: {{ include "my-app.fullname" . }}
data:
{{- range $key, $val := .Values.secrets.all }}
{{"SECRET_"}}{{ $key }}: {{ $val | b64enc | quote }}
{{- end}}

3. Add the secret to deployment.yaml in environment variables like this:

.
.
.
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
envFrom:
- configMapRef:
name: {{ include "my-app.fullname" . }}
- secretRef:
name: {{ include "my-app.fullname" . }}

Using secrets from environment variables and unifying value with ConfigMaps.

The env in the pod will be like:

SECRET_enc_key='njsprlwa8d64fvnsfnjsk61156aodlmr'
SECRET_enc_iv='48914829jfs2'
SECRET_sql_user="root"
SECRET_sql_password="password"
SECRET_redis_password="rpass"
SECRET_redis_prefix="k34234:"

We are using Viper a Golang library to read the config file in YAML. However, it does not parse secrets in the environment variables to config for access. It needs a utility code to read and set values like how it gonna use like this:

func GetSecrets() {
for _, value := range os.Environ() {
pair := strings.SplitN(value, "=", 2)
if strings.Contains(pair[0], "SECRET_") == true {
keys := strings.Replace(pair[0], "SECRET_", "", -1)
keys = strings.Replace(keys, "_", ".", -1)
newKey := strings.Trim(keys, " ")
newValue := strings.Trim(pair[1], " ")
viper.Set(newKey, newValue)
}
}
}

Call this function when the program starts and now can use the values like from config.yaml like this:

viper.GetString("enc.key")
viper.GetString("enc.iv")
viper.GetString("sql.user")
viper.GetString("sql.password")
viper.GetString("redis.password")
viper.GetString("redis.prefix")

Now I can access all secrets like in the config file as many secrets as you like. “Tell me what do you want to hear”

--

--