Reputation: 451
I'm using a kubernetes ConfigMap that contains database configurations for an app and there is a secret that has the database password. I need to use this secret in the ConfigMap so when I try to add environment variable in the ConfigMap and specify the value in the pod deployment from the secret I'm not able to connect to mysql with password as the values in the ConfigMap took the exact string of the variable.
apiVersion: v1
kind: ConfigMap
metadata:
name: config
data:
APP_CONFIG: |
port: 8080
databases:
default:
connector: mysql
host: "mysql"
port: "3306"
user: "root"
password: "$DB_PASSWORD"
and the deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: app
labels:
app: backend
spec:
replicas: 1
template:
metadata:
labels:
app: backend
spec:
containers:
- name: app
image: simple-app-image
ports:
- name: "8080"
containerPort: 8080
env:
- name: APP_CONFIG
valueFrom:
configMapKeyRef:
name: config
key: APP_CONFIG
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: "mysql-secret"
key: "mysql-root-password"
Note: the secret exist and I'm able to get "mysql-root-password" value and use to login to the database
Upvotes: 37
Views: 42694
Reputation: 31
There is an option to use external-secret operator and pull your configMap, inject passwords to it and create a secret out of it and finally mount it.
https://external-secrets.io/latest/guides/templating-v1/
Upvotes: 3
Reputation: 159
For me, something like this worked (sharing just the relevant example snippet for simplicity):
example-configmap
data:
example.yaml: |
user: ${USER}
example-secret
data:
user: <some base64 encoded value>
example-deployment
containers:
- name: example-container
image: example-image
env:
- name: USER
valueFrom:
secretKeyRef:
key: user
name: example-secret
volumeMounts:
- mountPath: /some/path/in/container
name: config
readOnly: true
volumes:
- name: config
configMap:
name: example-configmap
Explanation:
In the above example, say,
I need to substitute ${USER}
in the configmap with the decoded value of the user:
key from the secret.
Then, as done above, in the deployment/pod definition, I need to:
volumes.configMap
) under volumeMounts
in the container, andenv.valueFrom.secretKeyRef
) in the container.Result:
The ${USER}
in the configmap will have been substituted with the decoded value of the user:
key from the secret.
Reason:
This is because the configmap is now mounted as a file at the mountPath
inside the container, and thus, can access any env variable exposed within the container.
Note: namespace for deployment/pod, configmap, and secret should be the same.
Upvotes: -1
Reputation: 16678
You could do something like this in HELM:
{{- define "getValueFromSecret" }}
{{- $len := (default 16 .Length) | int -}}
{{- $obj := (lookup "v1" "Secret" .Namespace .Name).data -}}
{{- if $obj }}
{{- index $obj .Key | b64dec -}}
{{- else -}}
{{- randAlphaNum $len -}}
{{- end -}}
{{- end }}
Then you could do something like this in configmap:
{{- include "getValueFromSecret" (dict "Namespace" .Release.Namespace "Name" "<secret_name>" "Length" 10 "Key" "<key>") -}}
The secret should be already present while deploying; or you can control the order of deployment using https://github.com/vmware-tanzu/carvel-kapp-controller
Upvotes: 2
Reputation: 3739
I would transform the whole configMap
into a secret
and deploy the database password directly in there.
Then you can mount the secret as a file to a volume and use it like a regular config file in the container.
Upvotes: -2
Reputation: 8066
Kubernetes can't make that substitution for you, you should do it with shell in the entrypoint of the container.
This is a working example. I modify the default entrypoint to create a new variable with that substitution. After this command you should add the desired entrypoint.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: app
labels:
app: backend
spec:
replicas: 1
template:
metadata:
labels:
app: backend
spec:
containers:
- name: app
image: simple-app-image
command:
- /bin/bash
- -c
args:
- "NEW_APP_CONFIG=$(echo $APP_CONFIG | envsubst) && echo $NEW_APP_CONFIG && <INSERT IMAGE ENTRYPOINT HERE>"
ports:
- name: "app"
containerPort: 8080
env:
- name: APP_CONFIG
valueFrom:
configMapKeyRef:
name: config
key: APP_CONFIG
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: "mysql-secret"
key: "mysql-root-password"
Upvotes: 21