Search code examples
kuberneteskubernetes-helmconfigmapkubernetes-secrets

Approach for configmap and secret for a yaml file


I have a yaml file which needs to be loaded into my pods, this yaml file will have both sensitive and non-sensitive data, this yaml file need to be present in a path which i have included as env in containers.

        env:
          - name:  CONFIG_PATH
            value: /myapp/config/config.yaml

If my understanding is right, the configmap was the right choice, but i am forced to give the sensitive data like password as plain text in the values.yaml in helm chart.

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-config
  labels:
    app: {{ .Release.Name }}-config
data:
  config.yaml: |

    configuration: 
      settings: 
        Password: "{{.Values.config.password}}"
        Username: myuser

Values.yaml

config:
  password: "mypassword"

Mounted the above config map as follows

        volumeMounts:
          - name:  {{ .Release.Name }}-config
            mountPath:  /myapp/config/

So i wanted to try secret, If i try secret, it is loading as Environment Variables inside pod, but it is not going into this config.yaml file.

If i convert the above yaml file into secret instead of configmap , should i convert the entire config.yaml into base64 secret? my yaml file has more entries and it will look cumbersome and i dont think it as a solution. If i take secret as a stringdata then the base64 will be taken as it is.

How do i make sure that config.yaml loads into pods with passwords not exposed in the values.yaml Is there a way to combine configmap and secret I read about projected volumes, but i dont see a use case for merging configmap and secrets into single config.yaml Any help would be appreciated.


Solution

  • Kubernetes has no real way to construct files out of several parts. You can embed an entire (small) file in a ConfigMap or a Secret, but you can't ask the cluster to assemble a file out of parts in multiple places.

    In Helm, one thing you can do is to put the configuration-file data into a helper template

    {{- define "config.yaml" -}}
    configuration: 
      settings: 
        Password: "{{.Values.config.password}}"
        Username: myuser
    {{ end -}}
    

    In the ConfigMap you can use this helper template rather than embedding the content directly

    apiVersion: v1
    kind: ConfigMap
    metadata: { ... }
    data:
      config.yaml: |
    {{ include "config.yaml" . | indent 4 }}
    

    If you move it to a Secret you do in fact need to base64 encode it. But with the helper template that's just a matter of invoking the template and encoding the result.

    apiVersion: v1
    kind: Secret
    metadata: { ... }
    data:
      config.yaml: {{ include "config.yaml" . | b64enc }}
    

    If it's possible to set properties in this file directly via environment variables (like Spring properties) or to insert environment-variable references in the file (like a Ruby ERB file) that could let you put the bulk of the file into a ConfigMap, but use a Secret for specific values; you would need a little more wiring to also make the environment variables available.

    You briefly note a concern around passing the credential as a Helm value. This does in fact require having it in plain text at deploy time, and an operator could helm get values later to retrieve it. If this is a problem, you'll need some other path to inject or retrieve the secret value.