一、简介
Volume是Pod中能够被多个容器共享的磁盘目录。我们知道,默认情况下Docker容器中的数据都是非持久化的,在容器消亡后数据也会消失。因此Docker提供了Volume机制以便实现数据的持久化。Kubernetes中Volume的概念与Docker中的Volume类似,但不完全相同。具体区别如下:
- Kubernetes中的Volume与Pod的生命周期相同,但与容器的生命周期不相关。当容器终止或重启时,Volume中的数据也不会丢失。
- 当Pod被删除时,Volume才会被清理。并且数据是否丢失取决于Volume的具体类型,比如emptyDir类型的Volume数据会丢失,而PV类型的数据则不会丢失。
Kubernetes提供了非常丰富的Volume类型,下面是一些常用的Volume类型:
emptyDir、hostPath、gcePersistentDisk、awsElasticBlockStore、gitRepo、secret、nfs、iscsi、
glusterfs、persistentVolumeClaim、rbd、flexVolume、cinder、cephfs、flocker、downwardAPI、fc、azureFile、configMap、vsphereVolume
注意,这些 volume 并非全部都是持久化的,比如 emptyDir、secret、gitRepo 等,这些 volume 会随着 Pod 的消亡而消失。
二、本地存储
2.1 emptyDir
顾名思义,它的初始内容为空,在同一个Pod中的所有容器均可以读写这个emptyDir volume。
emptyDir类型的volume是在Pod分配到Node时创建的,kubernetes会在Node上自动分配一个目录,因此无需指定宿主机Node上对应的目录文件。这个目录的初始内容为空,当 Pod 从 Node 上被删除(Pod 被删除,或者 Pod 发生迁移),emptyDir 也会被删除,并且数据永久丢失。
一个简单的例子:
创建包含两个容器的busybox pod,每个容器都有映像busybox并运行“sleep 3600”命令。使两个容器都在‘/etc/foo‘处安装一个空的dir。 连接到第二个busybox,将‘/etc/passwd‘文件的第一列写入‘/etc/foo/passwd‘。连接到第一个busybox并将“/etc/foo/passwd”文件写入标准输出
kubectl run busybox --image=busybox --restart=Never --dry-run -o yaml -- /bin/sh -c "sleep 3600" > pod.yaml
复制粘贴容器定义并键入结尾有注释的行:
apiVersion: v1 kind: Pod metadata: creationTimestamp: null labels: run: busybox name: busybox spec: dnsPolicy: ClusterFirst restartPolicy: Never containers: - args: - /bin/sh - -c - sleep 3600 image: busybox name: busybox resources: {} volumeMounts: - name: myvolume mountPath: /etc/foo - args: - /bin/sh - -c - sleep 3600 image: busybox name: busybox2 ### 注意修改成其他名称,不要和上面的名称重复 volumeMounts: - name: myvolume mountPath: /etc/foo volumes: - name: myvolume emptyDir: {} status: {}
创建pod
[root@han-test ckad-test]# kubectl apply -f pod.yaml -n ckad-test pod/busybox created [root@han-test ckad-test]# kubectl get pod -n ckad-test NAME READY STATUS RESTARTS AGE busybox 2/2 Running 0 35s [root@han-test ckad-test]#
连接到第二个容器:
[root@han-test ckad-test]# kubectl -n ckad-test exec busybox -c busybox2 -it -- /bin/sh / # ls bin dev etc home proc root sys tmp usr var / # cat /etc/passwd |cut -f 1 -d ":" > /etc/foo/passwd / # cat /etc/foo/passwd root daemon bin sys sync mail www-data operator nobody / # exit
连接到第一个容器:
[root@han-test ckad-test]# kubectl -n ckad-test exec busybox -c busybox -it -- /bin/sh / # mount |grep foo /dev/vda1 on /etc/foo type xfs (rw,seclabel,relatime,attr2,inode64,noquota) / # cat /etc/foo/passwd root daemon bin sys sync mail www-data operator nobody / # exit [root@han-test ckad-test]#
emptyDir类型的volume适合于以下场景:
- 临时空间。某些应用程序无需永久保存的临时目录,无需永久保存。
- 一个容器需要从另一容器中获取数据的目录(多容器共享目录)
2.2 hostPath
挂载Node文件系统上的文件或者目录到pod中的容器
hostPath类型的volume允许用户挂在Node上的文件系统到Pod中,如果 Pod 需要使用 Node 上的文件,可以使用 hostPath。
一个简单的例子:
scp pod.yaml hostPath.yaml
这里不再重复,修改相应的volumes行:
vim hostPath.yaml ... volumes: - name: myvolume hostPath: path: /etc/foo ...
创建hostPath pod
[root@han-test ckad-test]# kubectl -n ckad-test delete pod busybox pod "busybox" deleted [root@han-test ckad-test]# kubectl apply -f hostPath.yaml -n ckad-test pod/busybox created [root@han-test ckad-test]# kubectl get pod -n ckad-test NAME READY STATUS RESTARTS AGE busybox 2/2 Running 0 35s [root@han-test ckad-test]#
重复上面操作
[root@han-test ckad-test]# kubectl -n ckad-test exec busybox -c busybox2 -it -- /bin/sh / # cat /etc/passwd | cut -f 1 -d ‘:‘ > /etc/foo/passwd / # cat /etc/foo/passwd root daemon bin sys sync mail www-data operator nobody / # exit [root@han-test ckad-test]# kubectl -n ckad-test exec busybox -c busybox -it -- /bin/sh / # cat /etc/foo/passwd root daemon bin sys sync mail www-data operator nobody / # exit [root@han-test ckad-test]#
访问宿主机上的目录文件
[root@han-test ckad-test]# cat /etc/foo/passwd root daemon bin sys sync mail www-data operator nobody
即使pod删除,文件还是会存在
hostPath volume通常用于以下场景:
- 容器中的应用程序产生的日志文件需要永久保存,可以使用宿主机的文件系统进行存储。
- 需要访问宿主机上Docker引擎内部数据结构的容器应用,通过定义hostPath为/var/lib/docker目录,使容器内应用可以直接访问Docker的文件系统。
在使用hostPath volume时,需要注意:
- 在不同的Node上具有相同配置的Pod,可能会因为宿主机上的目录和文件不同,而导致对Volume上目录和文件的访问结果不一致。
三、网络存储
nfs
NFS 是 Network File System 的缩写,即网络文件系统。Kubernetes 中通过简单地配置就可以挂载 NFS 到 Pod 中,而 NFS 中的数据是可以永久保存的,同时 NFS 支持同时写操作。
volumes: - name: nfs nfs: # FIXME: use the right hostname server: 10.254.234.223 path: "/"
关于静态存储、动态供给,请参考:Kubernetes对象之PersistentVolume,PersistentVolumeClaim和StorageClass
参考文章