一、Volume
一般来说,容器一旦被删除后,容器运行时内部产生的所有文件数据也会被清理掉,因此,Docker提供了 Volume 这种方式来将数据持久化存储。
可以说,Volume 是Pod与外部存储设备进行数据传递的通道,也是Pod内部容器间、Pod与Pod间、Pod与外部环境进行数据共享的方式。
实际上,这个 Volume 也只是宿主机上本地磁盘中的一个目录,也就是说,volume方式是将容器里面的数据都保存到宿主机上。除此之外,还能保存到外部存储上。
在k8s中,支持多种类型的Volume:本地存储(emptyDir / hostPath)、外部存储(如NFS)。
1、emptyDir
若pod使用了emptyDir类型的volume,则在创建pod时,emptyDir volume随着pod也会一同被创建出来。emptyDir volume 会在pod所在的node节点上生成一个空目录,而这个空目录的默认路径是在/var/lib/kubelet/pods/下。
emptyDir 类型相当于执行【docker run -v /CONTAINER/DIR】。
emptyDir Volume与Pod生命周期一致,只要Pod一直运行,该Volume就一直存在,而当Pod被删除时,该Volume也同时会删除,即Node上对应目录也会被删掉。
一个Volume可被Pod中的所有容器共享,且可被挂载到容器的指定路径下。
示例:
说明:创建一个Pod,Pod有两个容器,它们共享一个Volume,busybox容器负责往 Volume 中写数据,myapp容器则是从 Volume 读取数据
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
spec:
volumes: # 定义emptyDir类型的Volume
- name: myweb
emptyDir: {}
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: myweb
mountPath: /usr/share/nginx/html/
- name: busybox
image: busybox:latest
volumeMounts: # 将名为myweb的volume挂载到容器里的/web目录下
- name: myweb
mountPath: /web
command: [ "/bin/sh", "-c", "while true; do echo $(date) >> /web/index.html; done" ]
查看volume信息:
$ docker inspect 020799d427ae -f "{
{.Mounts}}"
"Mounts": [
{
"Type": "bind",
"Source": "/var/lib/kubelet/pods/bb66b0cd-979d-4356-92a9-492d420fc613/volumes/kubernetes.io~empty-dir/html",
"Destination": "/usr/share/nginx/html",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
尝试将pod删除,node上的volume目录也会被删除:
$ kubectl delete pod pod-demo
$ ls /var/lib/kubelet/pods/bb66b0cd-979d-4356-92a9-492d420fc613
2、hostPath
该类型是将Node上指定的文件或目录挂载到Pod中。当Pod被删除时,Node上对应的该Volume的文件或目录不会被删除,会保留下来,从这点来看,hostPath的持久性比emptyDir强。不过一旦node节点崩溃了,hostPath也就没法访问了。
hostPath 类型相当于执行【docker run -v /HOST/DIR:/CONTAINER/DIR】。
apiVersion: v1
kind: Pod
metadata:
name: pod-demo2
spec:
volumes:
- name: myweb
hostPath:
path: /data/www/ # 指定node上的目录
type: Directory
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: myweb
mountPath: /usr/share/nginx/html/ #要挂载到容器的哪个目录下
3、外部存储(以NFS为例)
除了将数据存放在本地node节点上,为了更安全,我们也可以将数据存储到外部的远程磁盘上,比如放到NFS服务器上,IP为192.168.100.172。
1)搭建NFS服务器
yum -y install nfs-utils
mkdir -p /data/testvol
echo "NFS Test Data" > /data/testvol/index.html
echo "/data/testvol 192.168.100.0/24(rw,no_root_squash)" >> /etc/exports
systemctl start nfs
2)创建NFS存储卷
# 在k8s集群的节点上,安装nfs-utils工具
$ yum -y install nfs-utils
# 验证是否能成功挂载
$ mount -t nfs 192.168.100.172:/data/testvol /mnt
# yaml文件如下:
$ cat vol-nfs-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: vol-nfs
spec:
volumes:
- name: myweb
nfs:
path: /data/testvol # NFS共享目录
server: 192.168.100.172 # NFS服务器IP
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: myweb
mountPath: /usr/share/nginx/html/
二、PV与PVC
除了Volume之外,kubernetes 还提供了 Persistent Volume 的方法持久化数据。
它与普通Volume的区别是, 普通Volume和Pod之间是一种静态绑定关系,也就是,在定义pod时,同时要将pod所使用的Volume一并定义好,Volume是Pod的附属品。volume会随着pod创建而被创建,我们无法单独创建一个Volume,因为它不是一个独立的K8S资源对象。
而Persistent Volume则是一个K8S资源对象,它是独立于Pod的,能单独创建。Persistent Volume 不与Pod发生直接关系,而是通过 Persistent Volume Claim(PVC) 来与Pod绑定关系。在定义Pod时,为Pod指定一个PVC,Pod在创建时会根据PVC要求,从现有集群的PV中,选择一个合适的PV绑定,或动态建立一个新的PV,再与其进行绑定。
Persistent Volume(PV):用于定义各种存储资源的配置信息,一个PV对应一个volume,定义一个PV内容包括了 存储类型、存储大小和访问模式等。
Persistent Volume Claim(PVC):描述对PV的一个请求。请求信息包含存储大小、访问模式等。PVC只会选择符合自己要求的PV进行绑定,然后在定义pod时指定使用哪个PVC就可以了。
原理:
PVC和PV的设计,其实跟面