How to mount multiple files / secrets into common directory in kubernetes? - kubernetes

I've multiple secrets created from different files. I'd like to store all of them in common directory /var/secrets/. Unfortunately, I'm unable to do that because kubernetes throws 'Invalid value: "/var/secret": must be unique error during pod validation step. Below is an example of my pod definition.
apiVersion: v1
kind: Pod
metadata:
labels:
run: alpine-secret
name: alpine-secret
spec:
containers:
- command:
- sleep
- "3600"
image: alpine
name: alpine-secret
volumeMounts:
- name: xfile
mountPath: "/var/secrets/"
readOnly: true
- name: yfile
mountPath: "/var/secrets/"
readOnly: true
volumes:
- name: xfile
secret:
secretName: my-secret-one
- name: yfile
secret:
secretName: my-secret-two
How can I store files from multiple secrets in the same directory?

Projected Volume
You can use a projected volume to have two secrets in the same directory
Example
apiVersion: v1
kind: Pod
metadata:
labels:
run: alpine-secret
name: alpine-secret
spec:
containers:
- command:
- sleep
- "3600"
image: alpine
name: alpine-secret
volumeMounts:
- name: xyfiles
mountPath: "/var/secrets/"
readOnly: true
volumes:
- name: xyfiles
projected:
sources:
- secret:
name: my-secret-one
- secret:
name: my-secret-two

(EDIT: Never mind - I just noticed #Jonas gave the same answer earlier. +1 from me)
Starting with Kubernetes v1.11+ it is possible with projected volumes:
A projected volume maps several existing volume sources into the same
directory.
Currently, the following types of volume sources can be projected:
secret
downwardAPI
configMap
serviceAccountToken
This is an example for "... how to use a projected Volume to mount several existing volume sources into the same directory".

May be subPath (using subPath) will help.
Example:
volumeMounts:
- name: app-redis-vol
mountPath: /app/config/redis.yaml
subPath: redis.yaml
- name: app-config-vol
mountPath: /app/config/app.yaml
subPath: app.yaml
volumes:
- name: app-redis-vol
configMap:
name: config-map-redis
items:
- key: yourKey
path: redis.yaml
- name: app-config-vol
configMap:
name: config-map-app
items:
- key: yourKey
path: app.yaml
Here your configMap named config-map-redis created from file redis.yaml mounted in app/config/ as file redis.yaml.
Also configMap config-map-app mounted in app/config/ as app.yaml
There is nice article about this here: Injecting multiple Kubernetes volumes to the same directory

Edited:
#Jonas answer is correct!
However, if you use volumes as I did in the question then, short answer is you cannot do that, You have to specify mountPath to an unused directory - volumes have to be unique and cannot be mounted to common directory.
Solution:
What I did at the end was, instead keeping files in separate secrets, I created one secret with multiple files.

Related

mount through procfd: not a directory: unknown

I am trying to copy a file in Kubernetes to an existing directory. I am getting the error
caused: mount through procfd: not a directory: unknown
I looked at similar issues, but cannot seem to resolve it. These are the confs
Configmap
apiVersion: v1
kind: ConfigMap
metadata:
name: hdfs-yarn
data:
yarn-site.xml: |
<?xml version="1.0" encoding="UTF-8"?>
...
This is my deployment yaml
volumeMounts:
- mountPath: /opt/druid/conf/druid/cluster/_common/yarn-site.xml
name: hdfs-volume
subPath: yarn-site.xml
- mountPath: /druid/data
name: data-volume
...
volumes:
- name: hdfs-volume
configMap:
name: hdfs-yarn
items:
- key: yarn-site.xml
path: yarn-site.xml
...
Can anyone point out what could be wrong here? Thanks in advance for all the help.
The Kubernetes documentation states:
Volumes can not mount onto other volumes or have hard links to other
volumes
Instead of using one config map for volume hdf—--try using two config maps for each of the volems and let me know if this works.
volumeMounts:
- mountPath: /opt/druid/conf/druid/cluster/_common/yarn-site.xml
name: hdfs-volume
subPath: yarn-site.xml
- mountPath: /druid/data
name: data-volume
...
volumes:
- name: hdfs-volume
configMap:
name: hdfs-yarn
- name: data-volume
configMap:
name:data-yarn
Refer this Volumes and Configmap doc for more information

Confimap volume with defaultMode no working?

yaml file like below
apiVersion: v1
kind: Pod
metadata:
name: fortune-configmap-volume
spec:
containers:
- image: luksa/fortune:env
env:
- name: INTERVAL
valueFrom:
configMapKeyRef:
name: fortune-config
key: sleep-interval
name: html-generator
volumeMounts:
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
- name: config
mountPath: /etc/nginx/conf.d
volumes:
- name: html
emptyDir: {}
- name: config
configMap:
name: fortune-config
defaultMode: 0777
As you can see,I set the configMap volume defaultMode 0777, when I try to modify file in container path /etc/nginx/conf.d, it told me operation is not allowed, but why?
https://github.com/kubernetes/kubernetes/issues/62099
Secret, configMap, downwardAPI and projected volumes will be mounted as read-only volumes. Applications that attempt to write to these volumes will receive read-only filesystem errors. Previously, applications were allowed to make changes to these volumes, but those changes were reverted at an arbitrary interval by the system. Applications should be re-configured to write derived files to another location.

How can I put multi configmap in the same mount path in kubernetes?

I have two python files, testing_1.py and testing_2.py.
Then, I have created the configmap with testing-config1 to store testing_1.py and testing-config2 to store testing_2.py respectively.
In Kubernetes yaml,
...
containers:
- name: spark-master
image: bde2020/spark-master:2.4.4-hadoop2.7
volumeMounts:
- name: testing
mountPath: /jobs
- name: testing2
mountPath: /jobs
volumes:
- name: testing
configMap:
name: testing-config1
- name: testing2
configMap:
name: testing-config2
...
In the final result, the path only contains testing_1.py.
You can do it by providing subPath while specifying path. Change it as below:
containers:
- name: spark-master
image: bde2020/spark-master:2.4.4-hadoop2.7
volumeMounts:
- name: testing
mountPath: /jobs/testing_1.py
subPath: testing_1.py
- name: testing2
mountPath: /jobs/testing_2.py
subPath: testing_2.py
volumes:
- name: testing
configMap:
name: testing-config1
- name: testing2
configMap:
name: testing-config2
You can put both files in the same ConfigMap.
Or, use a projected volume:
A projected volume maps several existing volume sources into the same
directory.
Currently, the following types of volume sources can be projected:
secret
downwardAPI
configMap
serviceAccountToken

Local Persistent Volume in its own directory

I have got the local persistent volumes to work, using local directories as mount points, storage class, PVC etc, all using standard documentation.
However, when I use this PVC in a Pod, all the files are getting created in the base of the mount point, i.e if /data is my mount point, all my application files are stored in the /data folder. I see this creating conflicts in the future, with more than one application writing to the same folder.
Looking for any suggestions or advice to make each PVC or even application files of a Pod into separate directories in the PV.
If you store your data in different directories on your volume, you can use subPath to separate your data into different directories using multiple mount points.
E.g.
apiVersion: v1
kind: Pod
metadata:
name: podname
spec:
containers:
- name: containername
image: imagename
volumeMounts:
- mountPath: /path/to/mount/point
name: volumename
subPath: volume_subpath
- mountPath: /path/to/mount/point2
name: volumename
subPath: volume_subpath2
volumes:
- name: volumename
persistentVolumeClaim:
claimName: pvcname
Another approach is using subPathExpr.
Note:
The subPath and subPathExpr properties are mutually exclusive
apiVersion: v1
kind: Pod
metadata:
name: pod3
spec:
containers:
- name: pod3
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
image: busybox
command: [ "sh", "-c", "while [ true ]; do echo 'Hello'; sleep 10; done | tee -a /logs/hello.txt" ]
volumeMounts:
- name: workdir1
mountPath: /logs
subPathExpr: $(POD_NAME)
restartPolicy: Never
volumes:
- name: workdir1
persistentVolumeClaim:
claimName: pvc1
As described here.
In addition please follow Fixing the Subpath Volume Vulnerability in Kubernetes here and here
You can simply change the mount path and sperate the each application mount path so that files of POD into separate directories.

How do I use relative path for a secret mountPath in deployment configuration

I'm having hard time configuring mountPath as a relative path.
Let's say I'm running the deployment from /user/app folder and I want to create secret file under /user/app/secret/secret-volume as follows:
apiVersion: v1
kind: Pod
metadata:
name: secret-test-pod
spec:
containers:
- name: test-container
image: nginx
volumeMounts:
# name must match the volume name below
- name: secret-volume
mountPath: secret/secret-volume
# The secret data is exposed to Containers in the Pod through a Volume.
volumes:
- name: secret-volume
secret:
secretName: test-secret
For some reason the file secret-volume is created in the root directory /secret/secret-volume.
It's because you have mountPath: secret/secret-volume change it to mountPath: /user/app/secret/secret-volume
Check documentation here.