'kubernetes - Configmap - Existing files are removed

When using a ConfigMap as a mounted volume, all the existing files and folders inside the mounted location of the pod are deleted.

The ConfigMap is created using the command :

$ kubectl create configmap tomcat-configmap --from-file=./config/tomcat-config.xml

The deployement yaml file :

kind: Service
apiVersion: v1
metadata:
  name: tomcat-svc
spec:
  selector:
    app: tomcat-container
  ports:
  - protocol: TCP
    port: 83
    targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-deployment
spec:
  selector:
    matchLabels:
      app: tomcat-container
  replicas: 1
  template:
    metadata:
      labels:
        app: tomcat-container
    spec:
      containers:
      - name: tomcat
        image: bitnami/tomcat:latest
        ports:
        - containerPort: 8080
        volumeMounts:
        - name: tomcat-configmap-volume
          mountPath: /usr/local/tomcat/webapps/examples/WEB-INF/classes/com/test/app-conf.xml
          subPath: app-conf.xml
      volumes:
        - name: tomcat-configmap-volume
          configMap:
            name: tomcat-configmap

I tried different config but without success :(

Any suggestion would be very helpful

I am using kubernetes provided with docker for windows :

Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.3", GitCommit:"2bba0127d85d5a46ab4b778548be28623b32d0b0", GitTreeState:"clean", BuildDate:"2018-05-21T09:17:39Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"windows/amd64"}

Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.3", GitCommit:"2bba0127d85d5a46ab4b778548be28623b32d0b0", GitTreeState:"clean", BuildDate:"2018-05-21T09:05:37Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}


Solution 1:[1]

kind: Service
apiVersion: v1
metadata:
  name: tomcat-svc
spec:
  selector:
  app: tomcat-container
  ports:
  - protocol: TCP
    port: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-deployment
spec:
  selector:
    matchLabels:
      app: tomcat-container
  replicas: 1
  template:
    metadata:
      labels:
        app: tomcat-container
    spec:
  containers:
  - name: tomcat
    image: bitnami/tomcat:latest
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: tomcat-configmap-volume
      mountPath: /usr/local/tomcat/webapps/examples/WEB-INF/classes/com/test
      #subPath: app-conf.xml
  volumes:
    - name: tomcat-configmap-volume
      configMap:
        name: tomcat-configmap

The answer provided above by Rico should work, anyways I am providing the implementation result below :

Comment out the subpath, subpath is really useful when you want to override an existing config file. Also, your tomcat path is /opt/bitnami/tomcat in the image that you are using, and you are mounting a file in a custom dynamically created location in /usr/local/tomcat/ , not sure what you mean by it is overriding the contents

Screenshot

Solution 2:[2]

The problem here is that you are using subPath and that's meant to be a directory and you are thinking app-conf.xml should be created as a file.

What you really want is just this:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-deployment
spec:
  selector:
    matchLabels:
      app: tomcat-container
  replicas: 1
  template:
    metadata:
      labels:
        app: tomcat-container
    spec:
      containers:
      - name: tomcat
        image: bitnami/tomcat:latest
        ports:
        - containerPort: 8080
        volumeMounts:
        - name: tomcat-configmap-volume
          mountPath: /usr/local/tomcat/webapps/examples/WEB-INF/classes/com/test
      volumes:
        - name: tomcat-configmap-volume
          configMap:
            name: tomcat-configmap

And name your file app-conf.xml so when you create the ConfigMap it gets assigned the data key app-conf.xml in your ConfigMap itself:

$ kubectl create configmap tomcat-configmap --from-file=./app-conf.xml

Then your ConfigMap will look like this:

$ kubectl describe cm tomcat-configmap
Name:         tomcat-configmap
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
app-conf.xml:
----
<xml>
...
...
</xml>

Events:  <none>

Solution 3:[3]

you did it right, you just missed the key parameter in your volume. as you're trying to replace just one file with another, what I mean is that you're using subPath to replace just one file which in your case the file is "app-conf.xml" but you're not specifying which key in your configMap that would replace this file. each configMap key is treated as an independent configuration file

kind: Service
apiVersion: v1
metadata:
  name: tomcat-svc
spec:
  selector:
    app: tomcat-container
  ports:
  - protocol: TCP
    port: 83
    targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-deployment
spec:
  selector:
    matchLabels:
      app: tomcat-container
  replicas: 1
  template:
    metadata:
      labels:
        app: tomcat-container
    spec:
      containers:
      - name: tomcat
        image: bitnami/tomcat:latest
        ports:
        - containerPort: 8080
        volumeMounts:
        - name: tomcat-configmap-volume
          mountPath: /usr/local/tomcat/webapps/examples/WEB-INF/classes/com/test/app-conf.xml
          subPath: app-conf.xml
      volumes:
        - name: tomcat-configmap-volume
          configMap:
            name: tomcat-configmap
            key: <enter the key here>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Sherif Hamdy