一、概述:
官方文档:https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/
在kubernetes集群中,使用subPath,有时,在单个Pod中共享卷以供多方使用是很有用的。volumeMounts.subPath 属性可用于指定所引用的卷内的子路径,而不是其根路径。
1、subPath是在挂载的卷的子路径,而不是被挂载的容器目录的子路径(volumeMounts)。
2、使用subPath既可以将卷的子目录挂载到容器的指定目录,也可以将文件挂载到容器内指定的目录下的文件。
3、将目录B挂载到容器内指定的目录A,容器的目录A下的所有内容会被目录B覆盖。
4、将目录B内的文件b挂载到容器内指定的目录A,容器的目录A内容不会被覆盖,而且容器目录A还存在挂载来的文件b;挂载文件的前提是需要使用到subPath指令。
二、subpath总结
使用subPath指令,当挂载的卷(volumes)存在subPath(文件或目录),则卷不会自动创建subPath(目录);当卷(volumes)存在subPath(文件)是实现挂载文件的关键,否则就是挂载目录。
解释:对于subPath总结可以理解为(使用subPath指令),假如:
volumeMount:/usr/bin/test
subPath: readme.txt
volunme: /opt/
情景1:没有提前在卷(/opt/ 目录)创建readme.txt文件或者readme.txt目录,启动容器的时候,会自动在卷内创建readme.txt目录(注意是readme.txt目录,而不是readme.txt文件)此刻:
volumeMount:/usr/bin/test
volunme: /opt/readme.txt
说明: test 和 readme.txt 都是目录
情景2:提前在卷(/opt/ 目录)创建readme.txt目录,启动容器的时候,会直接挂载readme.txt目录,此刻:
volumeMount:/usr/bin/test
volunme: /opt/readme.txt
说明: test 和 readme.txt 都是目录
情景3:提前在卷(/opt/ 目录)创建readme.txt文件,即启动容器的时候,会直接挂载卷的readme.txt文件(不但实现将文件挂载到容器的/usr/bin目录,且不会覆盖容器内/usr/bin目录下的内容),此刻:
volumeMount:/usr/bin/test
volunme: /opt/readme.txt
说明: test 和 readme.txt 都是文件,且test 的内容和 readme.txt 内容一致。
情景4:提前在卷(/opt/ 目录)创建readme.txt文件,且
volumeMount:/usr/bin/readme.txt
subPath: readme.txt
volunme: /opt/
说明:情景4 是k8s挂载 readme.txt 文件的常用写法,将readme.txt文件挂载到容器的/usr/bin/目录;同理,configMap和secret的key可以理解为subPath文件,而configMap和secret本身作为挂载卷的根目录。
三、实操验证
创建用于测试subpath指令的负载:
## 创建用于测试 subPath 的负载
cd /opt/
cat > test.yaml << EOF
---
## 创建用于测试 subPath 的负载
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: test
name: test
spec:
replicas: 1
selector:
matchLabels:
app: test
template:
metadata:
labels:
app: test
spec:
containers:
- command:
- tail
- -f
- /etc/hosts
image: centos:centos7.9.2009
imagePullPolicy: IfNotPresent
name: centos
volumeMounts:
- name: test
mountPath: /usr/bin/test
subPath: readme.txt
volumes:
- name: test
hostPath:
path: /opt/
---
EOF
1、使用subPath实现挂载文件验证
[root@zhou opt]# # 在卷 /opt 目录下提前创建readme.txt文件
[root@zhou opt]# pwd
/opt
[root@zhou opt]# ls
cni containerd readme.txt test.yaml
[root@zhou opt]# cat readme.txt
aa=1234566789
[root@zhou opt]#
[root@zhou opt]# cat test.yaml
---
## 创建用于测试 subPath 的负载
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: test
name: test
spec:
replicas: 1
selector:
matchLabels:
app: test
template:
metadata:
labels:
app: test
spec:
containers:
- command:
- tail
- -f
- /etc/hosts
image: centos:centos7.9.2009
imagePullPolicy: IfNotPresent
name: centos
volumeMounts:
- name: test
mountPath: /usr/bin/test
subPath: readme.txt
volumes:
- name: test
hostPath:
path: /opt/
---
[root@zhou opt]#
[root@zhou opt]# kubectl apply -f test.yaml
deployment.apps/test created
[root@zhou opt]#
[root@zhou opt]#
[root@zhou opt]# kubectl get po
NAME READY STATUS RESTARTS AGE
test-9d9df7d5-s4k4v 1/1 Running 0 105s
[root@zhou opt]#
[root@zhou opt]# # 查看 容器内挂载的 test 是否是 文件
[root@zhou opt]#
[root@zhou opt]# kubectl exec -it test-9d9df7d5-s4k4v -- ls -l /usr/bin/test
-rw-r--r-- 1 root root 14 May 7 15:00 /usr/bin/test
[root@zhou opt]#
[root@zhou opt]# # 查看 容器内 test 文件是否和 /opt 目录的 readme.txt 文件一致
[root@zhou opt]# pwd
/opt
[root@zhou opt]# ls
cni containerd readme.txt test.yaml
[root@zhou opt]#
[root@zhou opt]# cat readme.txt
aa=1234566789
[root@zhou opt]#
[root@zhou opt]# kubectl exec -it test-9d9df7d5-s4k4v -- cat /usr/bin/test
aa=1234566789
[root@zhou opt]#
[root@zhou opt]# ## 从上面的结果可以知道,容器内的 挂载的 /usr/bin/test 是文件,且内容和 卷 /opt目录的 readme.txt文件内容一致
[root@zhou opt]#
[root@zhou opt]#
[root@zhou opt]# # 查看 容器的 /usr/bin/ 目录下得内容 是否会被覆盖
[root@zhou opt]#
[root@zhou opt]# kubectl exec -it test-9d9df7d5-s4k4v -- ls -l /usr/bin/ | head -n 10
total 40196
-rwxr-xr-x 1 root root 41488 Aug 20 2019 [
-rwxr-xr-x 1 root root 29104 Oct 1 2020 addr2line
-rwxr-xr-x 1 root root 29 Apr 1 2020 alias
-rwxr-xr-x 1 root root 62680 Oct 1 2020 ar
-rwxr-xr-x 1 root root 33080 Aug 20 2019 arch
-rwxr-xr-x 1 root root 386424 Oct 1 2020 as
lrwxrwxrwx 1 root root 4 Nov 13 2020 awk -> gawk
-rwxr-xr-x 1 root root 37360 Aug 20 2019 base64
-rwxr-xr-x 1 root root 29032 Aug 20 2019 basename
[root@zhou opt]#
[root@zhou opt]# # 从上面的结果可以知道,容器内 /usr/bin/ 目录的二进制文件还存在,没有因为挂载而被覆盖
[root@zhou opt]#
[root@zhou opt]#
结论: 使用subPath指令,并且提前在卷(/opt 目录)创建 subPath指定的 readme.txt 文件,可以实现将文件挂载到容器内,且不会覆盖容器内响应目录的内容。
2、使用 subPath 挂载,且卷 /opt 目录下不存在 subpath 指定文件)
[root@zhou opt]#
[root@zhou opt]# # 卷 /opt/ 目录下,不存在 readme.txt 文件
[root@zhou opt]# pwd
/opt
[root@zhou opt]# ls
cni containerd test.yaml
[root@zhou opt]#
[root@zhou opt]#
[root@zhou opt]# # 卷 /opt/ 目录下,不存在 readme.txt 文件, 且test.yaml 内容不变
[root@zhou opt]# pwd
/opt
[root@zhou opt]# ls
cni containerd test.yaml
[root@zhou opt]# cat test.yaml
---
## 创建用于测试 subPath 的负载
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: test
name: test
spec:
replicas: 1
selector:
matchLabels:
app: test
template:
metadata:
labels:
app: test
spec:
containers:
- command:
- tail
- -f
- /etc/hosts
image: centos:centos7.9.2009
imagePullPolicy: IfNotPresent
name: centos
volumeMounts:
- name: test
mountPath: /usr/bin/test
subPath: readme.txt
volumes:
- name: test
hostPath:
path: /opt/
---
[root@zhou opt]#
[root@zhou opt]#
[root@zhou opt]# ls
cni containerd test.yaml
[root@zhou opt]#
[root@zhou opt]# kubectl get po
No resources found in default namespace.
[root@zhou opt]#
[root@zhou opt]# ## 使用 相同的 test.yaml 文件创建负载
[root@zhou opt]#
[root@zhou opt]# kubectl apply -f test.yaml
deployment.apps/test created
[root@zhou opt]#
[root@zhou opt]#
[root@zhou opt]# # 查看是否生成 pod 实例
[root@zhou opt]#
[root@zhou opt]# kubectl get po
NAME READY STATUS RESTARTS AGE
test-9d9df7d5-lgjwt 0/1 CrashLoopBackOff 3 (51s ago) 97s
[root@zhou opt]#
[root@zhou opt]# ## 先不要纠结为什么,这次使用相同的 test.yaml 文件创建的 pod 失败了,原因可能 挂载 /usr/bin 目录 导致二进制文件异常
[root@zhou opt]#
[root@zhou opt]# ## 查看 卷 /opt/ 目录是否自动创建了 readme.txt 目录, 注意此时是目录, 而不是文件
[root@zhou opt]# pwd
/opt
[root@zhou opt]# ls
cni containerd readme.txt test.yaml
[root@zhou opt]# ls -l
总用量 4
drwxr-xr-x. 3 kube root 17 7月 17 2022 cni
drwx--x--x. 4 root root 28 7月 17 2022 containerd
drwxr-xr-x 2 root root 6 5月 7 23:33 readme.txt
-rw-r--r-- 1 root root 630 5月 7 23:30 test.yaml
[root@zhou opt]#
[root@zhou opt]# ## 从结果可以知道 卷 /opt/ 目录 下自动创建了 subPath 指定名字的目录,而不是文件
[root@zhou opt]#
[root@zhou opt]#
结论:当 卷 /opt/ 目录 下没有提前创建 subPath 指定readme.txt文件,会自动在卷 /opt/ 目录创建 readme.txt 目录(创建的是目录而不是文件),且会覆盖容器挂载目录的内容。
3、由于挂载 容器的 /usr/bin 目录会导致容器启动失败,所以我们将mountPath 修改为/tmp/test,其他内容保持不变,则test.yaml变成 test01.yaml
[root@zhou opt]#
[root@zhou opt]# kubectl get po
No resources found in default namespace.
[root@zhou opt]#
[root@zhou opt]# ## 将容器内挂载的 目录 /usr/bin/test 替换成 /tmp/test
[root@zhou opt]#
[root@zhou opt]# pwd
/opt
[root@zhou opt]# ls
cni containerd test.yaml
[root@zhou opt]#
[root@zhou opt]# cp test.yaml test01.yaml
[root@zhou opt]#
[root@zhou opt]# sed -i 's+/usr/bin+/tmp+g' test01.yaml
[root@zhou opt]#
[root@zhou opt]# diff test.yaml test01.yaml
31c31
< mountPath: /usr/bin/test
---
> mountPath: /tmp/test
[root@zhou opt]#
[root@zhou opt]#
[root@zhou opt]# ## 通过 diff 可以知道 test.yaml 和test01.yaml 不同的地方是容器挂载目录
[root@zhou opt]#
[root@zhou opt]# # 使用 test01.yaml 创建测试负载
[root@zhou opt]#
[root@zhou opt]# kubectl apply -f test01.yaml
deployment.apps/test created
[root@zhou opt]#
[root@zhou opt]# kubectl get po
NAME READY STATUS RESTARTS AGE
test-687dc4c848-727kd 1/1 Running 0 18s
[root@zhou opt]# ls
cni containerd readme.txt test01.yaml test.yaml
[root@zhou opt]# pwd
/opt
[root@zhou opt]# ls -l
总用量 8
drwxr-xr-x. 3 kube root 17 7月 17 2022 cni
drwx--x--x. 4 root root 28 7月 17 2022 containerd
drwxr-xr-x 2 root root 6 5月 8 00:21 readme.txt
-rw-r--r-- 1 root root 626 5月 8 00:19 test01.yaml
-rw-r--r-- 1 root root 630 5月 8 00:17 test.yaml
[root@zhou opt]#
[root@zhou opt]# ## 创建完成 测试负载后,卷 /opt/ 目录下自动产生 subpath 指定的 readme.txt, 且自动生成的是目录而不是文件
[root@zhou opt]#
[root@zhou opt]# # 查看容器 挂载情况
[root@zhou opt]#
[root@zhou opt]# # 查看 卷 /opt/ 目录下得 readme.txt 目录不存在文件
[root@zhou opt]# ls -l /opt/readme.txt/
总用量 0
[root@zhou opt]# # 查看容器的挂载情况
[root@zhou opt]#
[root@zhou opt]# kubectl exec -it test-687dc4c848-727kd -- ls -l /tmp/
total 4
-rwx------ 1 root root 836 Nov 13 2020 ks-script-DrRL8A
drwxr-xr-x 2 root root 6 May 7 16:21 test
-rw------- 1 root root 0 Nov 13 2020 yum.log
[root@zhou opt]#
[root@zhou opt]# kubectl exec -it test-687dc4c848-727kd -- ls -l /tmp/test/
total 0
[root@zhou opt]#
[root@zhou opt]# # 从容器挂载结果得知,test 为 目录,并且是 volumeMounts.mountPath 的值
[root@zhou opt]#
[root@zhou opt]#
[root@zhou opt]# # 在卷 /opt/readme.txt/ 目录创建 一个测试文件 1.txt
您在 /var/spool/mail/root 中有新邮件
[root@zhou opt]#
[root@zhou opt]# echo "1111111111111" > /opt/readme.txt/1.txt
[root@zhou opt]#
[root@zhou opt]# cat /opt/readme.txt/1.txt
1111111111111
[root@zhou opt]#
[root@zhou opt]# # 查看容器内也存在 1.txt 文件
[root@zhou opt]#
[root@zhou opt]# kubectl exec -it test-687dc4c848-727kd -- ls -l /tmp/test/1.txt
-rw-r--r-- 1 root root 14 May 7 16:31 /tmp/test/1.txt
[root@zhou opt]#
[root@zhou opt]# kubectl exec -it test-687dc4c848-727kd -- cat /tmp/test/1.txt
1111111111111
[root@zhou opt]#
[root@zhou opt]# # 从结果可知,volumeMounts.mountPath 的 test 目录 和 卷的 subpath 的 readme.txt 目录内容一致
[root@zhou opt]#
结论: 当卷 /opt/ 目录下没有提前创建和 subpath 指定readme.txt 文件时候, 挂载的是目录而不是文件,此刻 volumeMounts 的值 /tmp/test 中的 test 和 卷 subpath 的值 readme.txt 都是目录,而不是文件。
四、挂载configMap文件例子
以文件形式挂载configMap以及挂载secret和挂载普通文件同样道理,可以把 configMap和secret当做卷的根目录,configMap和secret中的key作为 subpath 指定的文件名。此时若是 configMap和secret中key名称为subpath的值,以及和volumeMounts.mountPath文件名保持一致那么容器中看到挂载的文件就是configMap和secret的key。
# 创建配置文件,以文件形式 挂载到 容器内指定目录,并且不会覆盖 容器内目录
---
# 创建configMap , 其key 时文件,且文件是: key.txt
apiVersion: v1
data:
key.txt: |
aa=12345
bb=123456789
cc=qwerty
kind: ConfigMap
metadata:
name: test
---
---
## 创建用于测试 subPath 的负载
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: test
name: test
spec:
replicas: 1
selector:
matchLabels:
app: test
template:
metadata:
labels:
app: test
spec:
containers:
- command:
- tail
- -f
- /etc/hosts
image: centos:centos7.9.2009
imagePullPolicy: IfNotPresent
name: centos
volumeMounts:
- name: test
mountPath: /usr/bin/key.txt # 挂载为configMap 中的文件 key.txt
subPath: key.txt # 名字和mountPath 文件名字一致,同时和configMap的 文件一致
# 假如 subPath 不是 confgimap的 key文件名,则会被挂载成目录,且为子目录,容器就会找不到 configmap的key文件key.txt。 毕竟 comfigmap是卷的根目录,key.txt文件是在 configmap的根目录下,而不是在自定义的子目录下,则容器就会在subPath子目录找不到配置文件 key.txt
volumes:
- name: test
configMap:
name: test
---
[root@zhou opt]# # 查看是挂载的 comfigMap 文件
[root@zhou opt]#
[root@zhou opt]# kubectl get po
NAME READY STATUS RESTARTS AGE
test-5cfbc4f486-5xc72 1/1 Running 0 2m36s
[root@zhou opt]#
[root@zhou opt]# kubectl exec -it test-5cfbc4f486-5xc72 -- cat /usr/bin/key.txt
aa=12345
bb=123456789
cc=qwerty
[root@zhou opt]#
[root@zhou opt]#
[root@zhou opt]# kubectl exec -it test-5cfbc4f486-5xc72 -- ls -l /usr/bin/key.txt
-rw-r--r-- 1 root root 32 May 7 17:11 /usr/bin/key.txt
[root@zhou opt]#
[root@zhou opt]#
[root@zhou opt]#
[root@zhou opt]# kubectl exec -it test-5cfbc4f486-5xc72 -- ls -l /usr/bin/ |head -n 10
total 40236
-rwxr-xr-x 1 root root 41488 Aug 20 2019 [
-rwxr-xr-x 1 root root 29104 Oct 1 2020 addr2line
-rwxr-xr-x 1 root root 29 Apr 1 2020 alias
-rwxr-xr-x 1 root root 62680 Oct 1 2020 ar
-rwxr-xr-x 1 root root 33080 Aug 20 2019 arch
-rwxr-xr-x 1 root root 386424 Oct 1 2020 as
lrwxrwxrwx 1 root root 4 Nov 13 2020 awk -> gawk
-rwxr-xr-x 1 root root 37360 Aug 20 2019 base64
-rwxr-xr-x 1 root root 29032 Aug 20 2019 basename
[root@zhou opt]#
[root@zhou opt]#
[root@zhou opt]#
[root@zhou opt]# # 容器挂载目录 没有被覆盖,二进制文件还在
[root@zhou opt]#
[root@zhou opt]# kubectl exec -it test-5cfbc4f486-5xc72 -- ls -l /usr/bin/ |head -n 10
total 40236
-rwxr-xr-x 1 root root 41488 Aug 20 2019 [
-rwxr-xr-x 1 root root 29104 Oct 1 2020 addr2line
-rwxr-xr-x 1 root root 29 Apr 1 2020 alias
-rwxr-xr-x 1 root root 62680 Oct 1 2020 ar
-rwxr-xr-x 1 root root 33080 Aug 20 2019 arch
-rwxr-xr-x 1 root root 386424 Oct 1 2020 as
lrwxrwxrwx 1 root root 4 Nov 13 2020 awk -> gawk
-rwxr-xr-x 1 root root 37360 Aug 20 2019 base64
-rwxr-xr-x 1 root root 29032 Aug 20 2019 basename
[root@zhou opt]#
————————————————
版权声明:本文为CSDN博主「@土豆」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44770684/article/details/130547766