17

I am having two different config maps test-configmap and common-config. I tried to mount them at the same location, but one config map overwrote the other. Then I read about subPath and did not work.

deploy.yaml

apiVersion: apps/v1beta1 # for versions before 1.8.0 use apps/v1beta1
kind: Deployment
metadata:
  name: testing
spec:
  replicas: 1
  template:
    metadata:
      name: testing
      labels:
        app: testing
    spec:
      containers:
      - name: testing-container
        image: testing
        imagePullPolicy: IfNotPresent
      ports:
      - containerPort: __PORT__
      volumeMounts:
      - name: commonconfig-volume
        mountPath: /usr/src/app/config/test.config
        subPath: test.config
    volumes:
      - name: commonconfig-volume
        configMap:
          name: test-configmap
      - name: commonconfig-volume
        configMap:
          name: common-config

Error :

The Deployment "testing" is invalid: spec.template.spec.volumes[1].name: Duplicate value: "commonconfig-volume"

I am not sure if merging two config map achievable of not. And if yes then how should I do it.

Nicholas Sizer
  • 3,490
  • 3
  • 26
  • 29
jack
  • 321
  • 1
  • 5
  • 20

5 Answers5

31

You have to use special projected volumes for achieve that. Example your deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: testing
spec:
  replicas: 1
  selector:
    matchLabels:
      app: testing
  template:
    metadata:
      name: testing
      labels:
        app: testing
    spec:
      containers:
      - name: testing-container
        image: testing
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: __PORT__
        volumeMounts:
        - name: commonconfig-volume
          mountPath: /usr/src/app/config
      volumes:
        - name: commonconfig-volume
          projected:
            sources:
            - configMap:
                name: test-configmap
            - configMap:
                name: common-config

You can use secret same as configMap

kvaps
  • 2,589
  • 1
  • 21
  • 20
10

You cannot mount two ConfigMaps to the same location.

But mentioning subPath and key for every item in each configmaps will let you get items from both configmaps in the same location. You'll have to write mount points for each file manually:

apiVersion: v1
kind: Pod
metadata:
  name: config-single-file-volume-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh", "-c", "cat /etc/special-key" ]
      volumeMounts:
      - name: config-volume-1
        mountPath: /etc/special-key1
        subPath: path/to/special-key1
      - name: config-volume-2
        mountPath: /etc/special-key2
        subPath: path/to/special-key2
  volumes:
    - name: config-volume-1
      configMap:
        name: test-configmap1
        items:
        - key: data-1
          path: path/to/special-key1
    - name: config-volume-2
      configMap:
        name: test-configmap2
        items:
        - key: data-2
          path: path/to/special-key2
restartPolicy: Never

Another way is to mount them under same directory, but different subPath so that you don't have to specify items by hand. But, here keys from each configmap will be put into two different directories:

apiVersion: v1
kind: Pod
metadata:
  name: config-single-file-volume-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh", "-c", "cat /etc/special-key" ]
      volumeMounts:
      - name: config-volume-1
        mountPath: /etc/special-keys
        subPath: cm1
      - name: config-volume-2
        mountPath: /etc/special-keys
        subPath: cm2
  volumes:
    - name: config-volume-1
      configMap:
        name: test-configmap1
    - name: config-volume-2
      configMap:
        name: test-configmap2
restartPolicy: Never

cm1 and cm2 will be two directories containing files derived from keys in test-configmap1 and test-configmap2 respectively.

Shahidh
  • 2,472
  • 1
  • 18
  • 18
  • I guess in the first example, to answer the question, `volumeMounts.[].mountPath` values should be the same but subPaths different? – Petr Gladkikh Nov 19 '18 at 10:56
  • Make sure you have no out commented lines (# something) in your file as that for some reason will make the double volumeMounts fail. Please add that to your answer. – Christoffer May 17 '19 at 08:29
4

Another example of how this can be done for mounting multiple configmaps. This for an nginx dock were you want to both replace the main /etc/nginx/nginx.conf and the files in /etc/nginx/conn.f. This also deletes the default.conf file in conf.d

 containers:
    - name: nginx-proxy
      image: nginx:1.16-alpine
      imagePullPolicy: Always
      ports:
        - containerPort: 443
        - containerPort: 80
      volumeMounts:
        - name: nginx-main-conf-file
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
        - name: nginx-site-conf-file
          mountPath: /etc/nginx/conf.d
  volumes:
    - name: nginx-main-conf-file
      configMap:
        name: nginx-main-conf
    - name: nginx-site-conf-file
      configMap:
        name: nginx-site-conf

And one very important point. If you have any out commented lines (# something) in your yaml file, then this will not work. It's a bug. Tested in kubectl v1.14

Christoffer
  • 7,436
  • 4
  • 40
  • 42
4

NOTE: This approach is good if you have less amount of data in configmaps

Let's say you have two configmaps

test-confimap

apiVersion: v1
kind: ConfigMap
metadata:
  name: test-configmap
data:
  test-1.conf: |
    test-property-1=test-value-1

common-confimap

apiVersion: v1
kind: ConfigMap
metadata:
  name: common-configmap
data:
  common-1.conf: |
    common-property-1=common-value-1

Instead of having different configmaps you can have same data in single configmap like below.

apiVersion: v1
kind: ConfigMap
metadata:
  name: single-configmap
data:
  common-1.conf: |
    property-1=value-1
  test-1.conf: |
    property-1=value-1

Now create a volume from above configmap and mount to container with mounhPath like below

volume from configmap

volumes:
- configMap:
    defaultMode: 420
    name: single-cofigmap
  name: my-single-config

volumeMount

volumeMounts:
- mountPath: /path/to/config/folder/
  name: my-single-config

Now you can see two files at the /path/to/config/folder/ location inside the container. Tell to your application to use which one it need.

Mohan Sai
  • 43
  • 6
  • Thank you. I was trying to figure out how to stack the volumes and volumeMounts for way too long. Just outputting multiple data elements makes sense ... now. – Lodlaiden Jan 23 '22 at 16:45
0

One way would be to mount them at different points but in the same emptyDir volume, mounting that same volume into an init container and including a short script in the init container to merge the two files using whatever tools you install at the start of the script. Scripts can easily be included in the pod manifest using the technique in this answer.

dippynark
  • 2,743
  • 20
  • 58