Pod 的生命周期是短暂的,会频繁被销毁和创建。由于沙盒机制,旧Pod 被销毁后,会伴随容器里的所有资源都被清空。在服务运行过程,或多或少有需要持久化存储的资源(图片、多媒体、文档),我们都肯定不希望看到Pod没了这些资源也跟着被销毁。
另外同性质的Pod,资源之间应该允许共享,而不是被当独作为服务来远程访问。
Volume使用
Volume的生命周期独立于容器,它是一个目录,Volume会被mount到Pod,Pod中的所有容器都可以访问这个Volume,和Docker Volume类似。
Volume支持的类型:emptyDir、hostPath、AWS Elastic Block Store、NFS、Ceph等。
emptyDir(临时存储卷)
emptyDir属于Pod内的临时挂载的目录。 当Volume 选择类型为emptyDir时,它的特性只是一个临时挂载的目录,Pod删除后,该目录也会在node节点上被删除;但是如果容器崩溃或者Kubenetes 重启,该目录仍然存在,通过Pod 关联的容器均能访问该目录。
1)创建示例应用
#本地终端,进入server节点容器的命令
multipass shell server
#进入容器后,先创建文件:volume-test.yml
sudo vi volume-test.yml
#volume-test.yml 的内容
apiVersion: v1
kind: Pod
metadata:
name: shared-pod
spec:
containers:
- image: busybox
name: write-container
volumeMounts:
- mountPath: /write_directory
name: shared-volume
args:
- /bin/sh
- -c
- echo "hello K3s" >/write_directory/test; sleep 120000
- image: busybox
name: read-container
volumeMounts:
- mountPath: /read_directory
name: shared-volume
args:
- /bin/sh
- -c
- cat /read_directory/test; sleep 120000
volumes:
- name: shared-volume
emptyDir: {}
2)示例讲解
所有的示例均在Multipass内执行。
上述代码,首先声明一个叫shared-volume 的volume。同时为了方便下面对pod 的目录共享的验证,示例在Pod 内创建了两个容器,均通过volumeMounts 指向shared-volume 的shared_directory目录。
容器:write-container 负责在shared_directory 目录写入test文件(内容:hello K3s),read-container 则在启动后,读取/shared_directory 的test 文件。
2)示例验证
#先通过kubectl 引入volume-test.yml 文件
ubuntu@server:~/$ sudo kubectl apply -f volume-test.yml
pod/shared-pod created
#验证pod 是否成功创建
ubuntu@server:~/$ sudo kubectl get pod
NAME READY STATUS RESTARTS AGE
shared-pod 2/2 Running 0 37s
#验证 read-container 容器读取结果
ubuntu@server:~/demo-volume$ sudo kubectl logs shared-pod read-container
#验证成功
hello K3s
上述显示容器read-container成功读到了write-container容器写入的数据,验证了两个容器共享emptyDir Volume,其效果相当于执行了docker run -v /write_directory 和/docker run -v /read_directory。
HostPath(节点存储卷)
hostPath类型的存储卷是指将工作节点上某个文件系统的目录或文件挂载于Pod中的一种存储卷,它独立于Pod资源的生命周期,因而具有持久性。但由于这样的特征增加了了Pod与工作节点的耦合,在实际的场景应用中都不会选择此项。作为分布式的应用部署,更应该把持久化的目标独立于工作节点之外。
HostPath 与emptyDir 的使用方法相似,同时网上的资料也较多,这里就不再做示例演示。
PV & PVC
使用外部存储作为资源持久化目标是最理想方案,如果kubenetes部署在阿里云、AWS、Azure等公有云上,可以直接使用云盘作为Volume。 同样我们也可以创建NFS(网络文件系统),使用PV把NFS引入到Pod去。
①NFS for PV
先准备NFS网络盘,NFS服务具体部署请参照:https://www.jianshu.com/p/a5d5d9afa1eb
在此,笔者已经准备好NFS服务器:,可分享目录路径:
。
②部署示例应用
#本地终端,进入server节点容器的命令
multipass shell server
#进入容器后,先创建文件:nfs-pv.yml
sudo vi nfs-pv.yml
#nfs-pv.yml 的内容
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
spec:
capacity:
storage: 1Gi #指定PV的容量为1GB
accessModes:
- ReadWriteOnce #表示PV能为read-write模式mount到单个节点,ReadOnlyMany表示只读,mount到多个节点,ReadWriteMany表示读写可以mount到多节点
persistentVolumeReclaimPolicy: Recycle #PV的回收策略,清除PV中的数据,Retain表示管理员手工回收
storageClassName: nfs-storage #指定PV的class为nfs-storage,相当于为PV设置了一个分类,PVC可以指定class申请相应的PV
nfs:
path: /nfsdata/share #指定PV在NFS服务器上对应的目录
server: 192.168.64.12
引用PV,并且验证。
#引入
ubuntu@server:~$ sudo kubectl apply -f nfs-pv.yml
#输出成功结果
persistentvolume/nfs-pv created
#验证
ubuntu@server:~$ sudo kubectl get pv -o wide
#输出结果
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
nfs-pv 1Gi RWO Recycle Available nfs-storage 36s Filesystem
创建PVC
sudo vi nfs-pvc.yml
#nfs-pvc.yml 的内容
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pv
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: nfs-storage #与之前PV的storageClassName 一致
引用PVC,并且验证。
#引入
ubuntu@server:~$ sudo kubectl apply -f nfs-pvc.yml
#输出成功结果
persistentvolumeclaim/nfs-pvc created
#验证
ubuntu@server:~$ sudo kubectl get pvc -o wide
#输出结果
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
nfs-pv Bound nfs-pv 1Gi RWO nfs-storage 38s Filesystem
那么,可以创建新的Pod 进行验证了。
③在Pod 中使用PVC
sudo vi nfs-pod.yml
#nfs-pod.yml 的内容
apiVersion: v1
kind: Pod
metadata:
name: pv-pod
spec:
containers:
- name: pv-pod
image: busybox
args:
- /bin/sh
- -c
- sleep 180000
volumeMounts:
- mountPath: "/pod_data"
name: nfs-storage
volumes:
- name: nfs-storage
persistentVolumeClaim:
claimName: nfs-pv
最后测试验证
#引入
ubuntu@server:~$ sudo kubectl apply -f nfs-pod.yml
#输出结果
pod/pv-pod created
[root@k8s-node1 nfs-pv]# sudo kubectl get pod -o wide
#输出结果
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pv-pod 0/1 Running 0 34s <none> <none> <none> <none>
#类似docker exec 的执行操作,直接进入pod 的sh
ubuntu@server:~$ sudo kubectl exec -it pv-pod /bin/sh
#在容器中,执行如下命令
/ # cat /pod_data/text.txt
#输出结果
Hello NFS!
#在部署NFS网络文件系统一章
#地址:https://www.jianshu.com/p/a5d5d9afa1eb
#笔者已在NFS服务器:192.168.64.12 的目录/nfsdata/share创建了text.txt文件。
不需要使用PV时,可用删除PVC回收PV
ubuntu@server:~$# kubectl delete pvc pv-pod
persistentvolumeclaim "pv-pod" deleted
因PV的回收策略设置为Recycle,所以数据会被清除,如想保存数据,可以将策略设置为Retain。
本章结束!