Merge ConfigMap and Secrets
To use a Secret value within a ConfigMap you can use an initContainer to call a template engine.
The premise
In the previous post, I presented how to use kubernetes-event-exporter with Elasticsearch.
One of the problems I faced is that the tool doesn't follow the configuration guidelines from the 12-factor app methodology.
That is to say, we have to put the credentials in the YAML configuration rather than in environment variables.
As for Kubernetes, it doesn't allow us to mix Secret values within ConfigMap.
The solution
To solve that issue, we have 3 components:
- the
Secretas-is - the
ConfigMapwhich will have the configuration as a template - the
initContainerthat will merge the two
Secret
The secret comes from the ECK Operator:
apiVersion: v1
kind: Secret
data:
elastic: YU84bnc4NzZWMXBWMThOZThqOFlnOE1r
ConfigMap
The important piece is using ERB syntax <%%= %> to call ruby code and ENV hash to access environment variables:
receivers:
- name: "es"
elasticsearch:
hosts:
- https://quickstart-es-http:9200
index: kube-events
username: elastic
password: "<%%= ENV['ELASTIC_PASSWORD'] %>"
Why ERB?
- Because I love Ruby!
- Because the erb command line comes with the ruby docker official image (no custom Dockerfile needed)
initContainer
Here is the Deployment with the initContainer config that will craft the config file from both the Secret passed as an environment variable and the ConfigMap template:
initContainers:
- name: config
image: ruby:2.7-alpine
command: ['sh', '-c', 'erb /tmp/config.tpl > /tmp/cfg/config.yaml']
env:
- name: ELASTIC_PASSWORD
valueFrom:
secretKeyRef:
name: quickstart-es-elastic-user
key: elastic
volumeMounts:
- name: config-tpl
mountPath: /tmp/config.tpl
subPath: config.tpl
- name: config
mountPath: /tmp/cfg
The main container can later use that generated file.