一、概述
Kubernetes Volume(数据卷)主要解决以下两方面问题:
(1)数据持久性:容器运行起来后,容器内部文件系统的文件是暂时性的,当容器崩溃后,kubelet会重启容器,但容器会以干净的状态重启,也就是原容器运行后写入的文件将丢失。
(2)数据共享:如果多个容器运行在同一个Pod中,经常会存在共享文件的需求。比较常见的是日志平台容器对于应用程序容器产生的日志进行收集,比如在同一个Pod中,部署Java应用程序容器以及配套的Loki容器,这时需要把Java应用程序容器输出到Volume中,让Loki去采集。
(1)一个Pod可以包含多个数据卷、多个容器。
(2)一个容器通过挂载点决定某一个数据卷被挂载到容器中的什么路径。
(3)不同类型的数据卷对应不同的存储介质。
二、Volume类型
kubernetes支持20多种数据卷类型,具体可以查阅官网文档:https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/
1. emptyDir
emptyDir类型的数据卷在Pod被创建时分配给该Pod,并且直到Pod被移除时,该数据卷才被释放,通过emptyDir创建的卷是一个空目录,当Pod中的多个容器需要共享文件夹时,比如Pod中包括应用容器和日志收集容器,可以采用此类型的数据卷。
当共享的数据量不大,且对速度有较高要求时,emptyDir的存储介质可以设置为内容,即设置emptyDir.medium为Memory。
(1)定义一个emptyDir配置
apiVersion: v1
kind: Pod
metadata:
name: volume-emptydir
spec:
containers:
- image: busybox:1.28
name: busybox1
imagePullPolicy: IfNotPresent
command:
- sleep
- "3600"
volumeMounts:
- mountPath: /cache
name: cache-volume
- image: busybox:1.28
name: busybox2
imagePullPolicy: IfNotPresent
command:
- sleep
- "3600"
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir:
sizeLimit: 500Mi
说明: 上面创建的Pod包含两个busybox容器,分别叫busybox1和busybox2,并共享emptyDir数据卷,挂载到容器的/cache目录。
(2)测试
执行Pod创建:kubectl apply -f
进入到容器busybox1,并创建文件
kubectl exec -it pod volume-emptydir -c busybox1 – sh
进入到容器busybox2,查看/cache下是否有刚才创建的文件
kubectl exec -it pod volume-emptydir -c busybox2 – sh
[root@test-99 volumes]# kubectl get pods
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 5 5h13m
volume-emptydir 2/2 Running 0 61s
[root@test-99 volumes]# kubectl exec -it volume-emptydir -c busybox1 -- sh
/ # ls
bin cache dev etc home proc root sys tmp usr var
/ # cd cache/
/cache # ls
/cache # echo 123 > test.txt
/cache # cat test.txt
123
/cache # exit
[root@test-99 volumes]# kubectl exec -it volume-emptydir -c busybox2 -- sh
/ # cat /cache/test.txt
123
/ # exit
[root@test-99 volumes]#
2. hostPath
hostPath数据卷能将宿主机文件系统上的文件或者目录挂载到Pod中,绝大多数的情况下,Pod并不需要使用hostPath数据卷,只有少数特殊情况下,hostPath数据卷非常有用,例如:Pod内的容器需要访问到Docker,可以使用hostPath挂载宿主节点的/var/lib/docker。
警告:hostPath数据卷存在许多安全风险,尽可能不采用hostPath,如果必须使用该方式,它的范围应限于所需的文件或目录,并以只读方式挂载。
(1)定义一个hostPath配置
apiVersion: v1
kind: Pod
metadata:
name: volume-hostpath
spec:
containers:
- image: busybox:1.28
name: busybox1
imagePullPolicy: IfNotPresent
command:
- sleep
- "3600"
volumeMounts:
- mountPath: /tmpdata
name: host-volume
volumes:
- name: host-volume
hostPath:
# 宿主上目录位置
path: /tmpdata
# 此字段为可选
type: Directory
说明:上面创建的Pod共享宿主机的/data目录。
(2)测试
通过kubectl apply -f 创建Pod之后,并查看Pod所部署的宿主机,然后在对应的宿主机上创建/tmpdata目录并写入文件。
[root@test-99 volumes]# kubectl apply -f 02-volume-hostpath.yml
pod/volume-hostpath created
[root@test-99 volumes]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 5 5h44m 192.168.252.66 test-99 <none> <none>
volume-emptydir 2/2 Running 0 32m 192.168.43.65 develop <none> <none>
volume-hostpath 1/1 Running 0 2m56s 192.168.43.68 develop <none> <none>
[root@test-99 volumes]# kubectl exec volume-hostpath -- cat /tmpdata/test.txt
123
[root@test-99 volumes]#
3. configMap
configMap数据卷提供了向Pod注入数据的方法,ConfigMap对象中存储的数据可以被configMap类型的数据卷引用。
主要的应用场景是:使用ConfigMap中的某一个key作为文件名,对应value作为文件内容,例如把nginx的配置文件通过ConfigMap挂载。
(1)准备测试数据
cat <<EOF > /home/k8s/volumes/application.properties
username=zhangsan
password=123456
EOF
kubectl create configmap app-config --from-file=application.properties
(2)定义一个configMap数据卷配置
apiVersion: v1
kind: Pod
metadata:
name: volume-configmap
spec:
containers:
- name: test
image: busybox:1.28
imagePullPolicy: IfNotPresent
command:
- sleep
- "3600"
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: app-config
说明:上面的配置是把app-config ConfigMap的配置挂载到容器的/etc/config目录下,其中配置项key application.properties作为文件名,配置项value作为文件的内容。
(3)测试
[root@test-99 volumes]# kubectl apply -f 03-volume-configmap.yml
pod/volume-configmap created
[root@test-99 volumes]# kubectl get pods
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 16 16h
volume-configmap 1/1 Running 0 4s
volume-emptydir 2/2 Running 22 11h
volume-hostpath 1/1 Running 10 11h
[root@test-99 volumes]# kubectl exec -it volume-configmap -- sh
/ # ls
bin dev etc home proc root sys tmp usr var
/ # cd /etc/config/
/etc/config # ls
application.properties
/etc/config # cat application.properties
username=zhangsan
password=123456
创建Pod后,通过kubectl exec -it Pod名称 – sh命令进入到容器内容,查看/etc/config文件夹下的文件以及文件内容,可以发现ConfigMap已经挂载成功。