前言
默认情况下容器的数据都是非持久化的, 在容器消亡以后数据也跟着丢失, 所以 Docker 提供了 Volume 机制以便将数据持久化存储。 类似的, Kubernetes 提供了更强大的 Volume 机制和丰富的插件, 解决了容器数据持久化和容器间共享数据的问题。 与 Docker 不同, Kubernetes Volume 的生命周期与 Pod 绑定容器挂掉后 Kubelet 再次重启容器时, Volume 的数据依然还在而 Pod 删除时, Volume 才会清理。 数据是否丢失取决于具体的 Volume 类型, 比如 emptyDir 的数据会丢失, 而 PV 的数据则不会丢 PersistentVolume(pv)和PersistentVolumeClaim(pvc)是k8s提供的两种API资源,用于抽象存储细节。管理员关注于如何通过pv提供存储功能而无需关注用户如何使用,同样的用户只需要挂载pvc到容器中而不需要关注存储卷采用何种技术实现。 pvc和pv的关系与pod和node关系类似,前者消耗后者的资源。pvc可以向pv申请指定大小的存储资源并设置访问模式。
pv pvc相关知识
生命周期
pv和pvc遵循以下生命周期:
- 1.供应准备。管理员在集群中创建多个pv供用户使用。
- 2.绑定。用户创建pvc并指定需要的资源和访问模式。在找到可用pv之前,pvc会保持未绑定状态。
- 3.使用。用户可在pod中像volume一样使用pvc。
- 4.释放。用户删除pvc来回收存储资源,pv将变成“released”状态。由于还保留着之前的数据,这些数据需要根据不同的策略来处理,否则这些存储资源无法被其他pvc使用。
- 5.回收。pv可以设置三种回收策略:保留(Retain),回收(Recycle)和删除(Delete)。
- 保留策略允许人工处理保留的数据。
- 删除策略将删除pv和外部关联的存储资源,需要插件支持。
- 回收策略将执行清除操作,之后可以被新的pvc使用,需要插件支持。
pv属性
pv拥有以下属性:
- 容量,目前仅支持存储大小,未来可能支持IOPS和吞吐量等。
- 访问模式,ReadWriteOnce:单个节点读写。ReadOnlyMany:多节点只读。ReadWriteMany:多节点读写。挂载时只能使用一种模式。
- 回收策略,目前NFS和HostPath支持回收。 AWS、EBS、GCE、PD和Cinder支持删除。
- 阶段,分为Available(未绑定pvc)、Bound(已绑定)、Released(pvc已删除但资源未回收)、Failed(自动回收失败)
pvc属性
- 访问模式,与pv的语义相同。在请求资源时使用特定模式。
- 资源,申请的存储资源数量
pv类型
- emptyDir
- hostPath
- gcePersistentDisk
- awsElasticBlockStore
- nfs
- iscsi
- flocker
- glusterfs
- rbd
- cephfs
- gitRepo
- secret
- persistentVolumeClaim
- downwardAPI
- azureFileVolume
- ................
- ........(以下省略)
目前常用Volume 类型
emptyDir
如果 Pod 设置了 emptyDir 类型 Volume, Pod 被分配到 Node 上时候, 会创建emptyDir, 只要 Pod 运行在 Node 上, emptyDir 都会存在( 容器挂掉不会导致emptyDir 丢失数据) , 但是如果 Pod 从 Node 上被删除( Pod 被删除, 或者 Pod 发生迁移) , emptyDir 也会被删除, 并且永久丢失。
hostPath
hostPath 允许挂载 Node 上的文件系统到 Pod 里面去。 如果 Pod 需要使用 Node 上的文件, 可以使用 hostPath
NFS
NFS 是 Network File Syste
m 的缩写, 即网络文件系统。 Kubernetes 中通过简单地配置就可以挂载 NFS 到 Pod 中, 而 NFS 中的数据是可以永久保存的, 同时 NFS 支持同时写操作。
gcePersistentDisk
gcePersistentDisk 可以挂载 GCE 上的永久磁盘到容器, 需要 Kubernetes 运行在 GCE的 VM 中
awsElasticBlockStore
awsElasticBlockStore 可以挂载 AWS 上的 EBS 盘到容器, 需要 Kubernetes 运行在AWS 的 EC2 上。
gitRepo
gitRepo volume 将 git 代码下拉到指定的容器路径中
Projected Volume
Projected volume 将多个 Volume 源映射到同一个目录中, 支持 secret、 downwardAPI和 configMap
简单示例
emptyDir (节点级存储,生命周期与pod相同)
pod中有两个container挂载同一个emptyDir,nginx提供web服务,busybox则循环向挂载目录下的index.html文件写入数据

apiVersion: v1
kind: Pod
metadata:
name: pod-demo
namespace: default
labels:
app: myapp
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: myapp
containerPort: 80
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
- name: busybox
image: busybox:latest
volumeMounts:
- name: html
mountPath: /data
command:
- "/bin/sh"
- "-c"
- "while true; do echo $(date) >> /data/index.html; sleep 2; done"
volumes:
- name: html
emptyDir: {}
查看pod是否运行
kubectl get pod -o wide

访问 pod
while true; do curl 10.32.0.6; sleep 1; done

hostPath (节点级存储,生命周期和node相同)

apiVersion: v1
kind: Pod
metadata:
name: pod-vol-hostpath
namespace: default
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html/
volumes:
- name: html
hostPath:
path: /data/pod/volume1
type: DirectoryOrCreate
部署 pod
kubectl apply -f pod-hostpath-vol.yaml
创建挂载的目录
cd /data/pod/volume1 #添加一个index.html测试文件 echo "node1" > /data/pod/volume1/index.html
测试访问 (pod 删除在重新部署,文件还在)
kubectl get pods pod-vol-hostpath -o wide curl 10.32.0.6

NFS(永久存储,生命周期与NFS server相同)
安装 nfs 服务
# cents os yum install -y nfs-utils # ubuntu apt install nfs-kernel-server mkdir -p /data/volumes
在节点192.168.228.138创建nfs共享目录/data/volumes 并共享给192.168.228.0(这个根据自己的集群节点进行设置)网段都可以使用,并且root用户也可压缩使用
vi /etc/exports

重启 nfs 服务
# centos systemctl start nfs # ubuntu service nfs-kernel-server restart
定义 pod 挂载 nfs 服务资源

KIND: Pod
VERSION: v1
RESOURCE: nfs <Object>
DESCRIPTION:
NFS represents an NFS mount on the host that shares a pod's lifetime More
info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
Represents an NFS mount that lasts the lifetime of a pod. NFS volumes do
not support ownership management or SELinux relabeling.
FIELDS:
path <string> -required- #nfs服务器上是哪个路径
Path that is exported by the NFS server. More info:
https://kubernetes.io/docs/concepts/storage/volumes#nfs
readOnly <boolean> #要不要挂载为只读,默认为false
ReadOnly here will force the NFS export to be mounted with read-only
permissions. Defaults to false. More info:
https://kubernetes.io/docs/concepts/storage/volumes#nfs
server <string> -required- #服务器地址
Server is the hostname or IP address of the NFS server. More info:
https://kubernetes.io/docs/concepts/storage/volumes#nfs

apiVersion: v1
kind: Pod
metadata:
name: pod-nfs
namespace: default
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
nfs:
path: /data/volumes
server: 192.168.228.138
部署 pod
kubectl apply -f pod-nfs-vol.yaml
写入数据到nfs中
echo "<h1>NFS stor01<h1>" >> /data/volumes/index.html echo "<h1>NFS zhangbiao<h1>" >> /data/volumes/index.html
查看 pod 的 ip 地址
kubectl get pods -o wide

访问 pod 中的 nginx 服务
curl 10.32.0.2

删除 pod 资源在重新创建,不论下载 pod 调度到那个节点上都能够正常的访问,从而实现持久话存储
kubectl delete -f pod-vol-nfs.yaml kubectl apply -f pod-vol-nfs.yaml curl 10.32.0.2

