基于NFS实现pod数据持久化
PV和PVC
概念
PersistentVolume(PV):是集群中由管理员配置的一段网络存储。它是集群中的资源,就像节点是集群资源一样。PV是容量插件,如Volumes,但其生命周期独立于使用PV的任何单个pod。此API对象捕获存储实现的详细信息,包括NFS,iSCSI或特定于云提供程序的存储系统。
PersistentVolumeClaim(PVC):是由用户进行存储的请求。它类似于pod。 Pod消耗节点资源,PVC消耗PV资源。Pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式(例如,可以一次读/写或多次只读)。
虽然PersistentVolumeClaims允许用户使用抽象存储资源,但是PersistentVolumes对于不同的问题,用户通常需要具有不同属性(例如性能)。群集管理员需要能够提供各种PersistentVolumes不同的方式,而不仅仅是大小和访问模式,而不会让用户了解这些卷的实现方式。对于这些需求,有StorageClass 资源。
pvc用于实现pod和storage的解耦,修改storage的时候不需要修改pod。与NFS的区别,可以在PV和pVC层面实现对存储服务器的空间分配、存储的访问权限管理灯。
PV是属于集群资源,pvc是属于namespace中的资源。
StorageClass为管理员提供了一种描述他们提供的存储的“类”的方法。不同的类可能映射到服务质量级别,或备份策略,或者由群集管理员确定的任意策略。Kubernetes本身对于什么类别代表是不言而喻的。这个概念有时在其他存储系统中称为“配置文件”。
PV访问模式
PersistentVolume卷可以用资源提供者所支持的任何方式挂载到宿主系统上。 如下表所示,提供者(驱动)的能力不同,每个PV卷的访问模式都会设置为对应卷所支持的模式值。例如,NFS可以支持多个读写客户,但是某个特定的 NFS PV卷可能在服务器上以只读的方式导出。每个PV卷都会获得自身的访问模式集合,描述的是特定PV卷的能力。每个卷同一时刻只能以一种访问模式挂载,即使该卷能够支持多种访问模式。
accessModes 访问模式有:
root@deploy:~# kubectl explain PersistentVolume.spec.accessModes
ReadWriteOnce
卷可以被一个节点以读写方式挂载。 ReadWriteOnce 访问模式也允许运行在同一节点上的多个 Pod 访问卷。
ReadOnlyMany
卷可以被多个节点以只读方式挂载。
ReadWriteMany
卷可以被多个节点以读写方式挂载。
ReadWriteOncePod
卷可以被单个 Pod 以读写方式挂载。 如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC, 请使用ReadWriteOncePod 访问模式。这只支持 CSI 卷以及需要 Kubernetes 1.22 以上版本。
在命令行接口(CLI)中,访问模式也使用以下缩写形式:
RWO - ReadWriteOnce
ROX - ReadOnlyMany
RWX - ReadWriteMany
RWOP - ReadWriteOncePo
说明:
Kubernetes 使用卷访问模式来匹配PersistentVolumeClaim和PersistentVolume。在某些场合下,卷访问模式也会限制PersistentVolume可以挂载的位置。卷访问模式并不会在存储已经被挂载的情况下为其实施写保护。即使访问模式设置为ReadWriteOnce、ReadOnlyMany或ReadWriteMany,它们也不会对卷形成限制。例如,即使某个卷创建时设置为ReadOnlyMany,也无法保证该卷是只读的。如果访问模式设置为ReadWriteOncePod,则卷会被限制起来并且只能挂载到一个Pod上。
PV阶段
每个卷会处于以下阶段(Phase)之一:
Available(可用)-- 卷是一个空闲资源,尚未绑定到任何申领;
Bound(已绑定)-- 该卷已经绑定到某申领;
Released(已释放)-- 所绑定的申领已被删除,但是资源尚未被集群回收;
Failed(失败)-- 卷的自动回收操作失败。
命令行接口能够显示绑定到某 PV 卷的 PVC 对象。
PV回收策略
persistentVolumeReclaimPolicy目前的回收策略有:
root@deploy:~# kubectl explain PersistentVolume.spec.persistentVolumeReclaimPolicy
Retain -- 手动回收,默认策略,pvc回收后,PV卷的状态为released,卷上仍然保留上一次关联的pvc信息,无法绑定给任何pvc。使用命令kubectl edit pv pvname手动清理卷上claimRef信息,删除完成后,pv可以与其他pvc绑定。
Recycle -- 基本擦除 (rm -rf /thevolume/*),pvc回收后,pv的状态为Available,pv可以绑定给其他pvc,pv后端存储中数据被清空。(实际操作过程是:Kubernetes使用busybox镜像创建容器,挂载卷,并清空卷数据。)
Delete -- 诸如AWS EBS、GCE PD、Azure Disk或OpenStack Cinder卷这类关联存储资产也被删除
目前,仅NFS和HostPath支持回收(Recycle)。AWS EBS、GCE PD、Azure Disk和Cinder卷都支持删除(Delete)。
PVC与PV匹配规则
PV的mode必须高于PVC申请的最低要求:mode优先级,可简单理解为ROX<RWO<RWX。例如,用户请求RWO模式PV,但是目前只有NFS PV(RWO+ROX+RWX),PVC将匹配NFS。
容量满足最低要求:具有相同modes卷会被分组,然后根据size分类(由小到大)。
pv storage classes:用于对pv进行分类,pvc可以根据storageClassName参数申请特定类型pv。如果pv设置了storageClassName,那么pvc申请资源的时候也要指定storageClassName。例如,storageClassName指定为ns1-storage,ns1中pvc申请也指定storageClassName为ns1-storage。
PV卷类型
定义存储卷使用的类型:分块设备block和文件系统Filesystem。默认为文件系统
root@deploy:~# kubectl explain PersistentVolume.spec.volumeMode
PV挂载选项
mountOptions附加的挂载选项列表,实现更精细的权限控制
root@deploy:~# kubectl explain PersistentVolume.spec.mountOptions
emptyDir
默认情况下,当Pod分配到Node上时,将会创建emptyDir,只要Node上的Pod一直运行,Volume就会一直存在。当Pod(不管任何原因)从Node上
被删除时,emptyDir也同时会删除,存储的数据也将永久删除。
Pod使用示例:(2个容器在一个pod,使用emptydir)
cat pod_storage.yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox
labels:
app: busybox
spec:
volumes:
- name: datavolume
emptyDir: {}
containers:
- name: busybox1
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data
name: datavolume
- name: busybox2
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data
name: datavolume
配置说明:
spec.volumes:定义卷,是默认卷类型。
spec.containers.volumeMounts:引用卷
hostPath
hostPath允许Pod将Node的文件系统挂载到Pod内部。pod删除后,hostPath卷数据保留。
Pod的hostpath示例:
cat pod-hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox
labels:
app: busybox
spec:
volumes:
- name: datavolume
hostPath:
path: /busyboxdir
containers:
- name: busybox1
image: busybox
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data
name: datavolume
- name: busybox2
image: busybox
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data
name: datavolume
#设置readOnly,控制读写,默认值是false,也就是读写访问。
readOnly: false
NFS存储
NFS卷允许将现有的NF挂载到容器中,且不想emptyDir会丢失数据,当删除pod时,nfs卷的内容被保留,卷仅仅是被卸载,这意味着NFS卷可以预先上传好的数据待pod启动后即可直接使用,并且网络存储可以再多个pod之间共享同一份数据,即NFS可以被多个Pod同时挂载和读写。
Ubuntu准备NFS
root@harbor:~# apt install nfs-server -y
root@harbor:~# vim /etc/exports
/data/k8sdata *(rw,sync,no_root_squash)
root@harbor:~# mkdir /data/k8sdata
root@harbor:~# exportfs -r
#k8s节点安装nfs-common
root@node1:~# apt install nfs-common -y
volume示例:
1、单卷挂载使用
root@deploy:~# cat nfs-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- image: nginx
name: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs
mountPath: "/usr/share/nginx/html"
volumes:
- name: nfs
nfs:
server: 192.168.100.15
path: "/data/k8sdata"
---
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: web-svc
name: web-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
nodePort: 30010
selector:
app: web
type: NodePort
NFS server创建站点文件
root@deploy:~# kubectl apply -f nfs-deployment.yaml
root@harbor:~# cd /data/k8sdata/
root@harbor:/data/k8sdata# echo test > index.html
查看node节点容器具体挂载nfs
2、多卷挂载使用
root@deploy:~# cat nfs-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- image: nginx
name: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs1
mountPath: "/usr/share/nginx/html/data1"
- name: nfs2
mountPath: "/usr/share/nginx/html/data2"
volumes:
- name: nfs1
nfs:
server: 192.168.100.15
path: "/data/k8sdata/data1"
- name: nfs2
nfs:
server: 192.168.100.15
path: "/data/k8sdata/data2"
---
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: web-svc
name: web-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
nodePort: 30010
selector:
app: web
type: NodePort
nfs添加站点文件
root@harbor:/data/k8sdata# echo "data1" >> data1/index.html
root@harbor:/data/k8sdata# echo "data2" >> data2/index.html
访问测试
查看node挂载
PV示例:
注意:PV资源属于集群全局资源,不归属于某个namespace
查看支持的卷存储类型
root@node1:~# kubectl explain deployment.spec.template.spec.volumes
示例:nfs类型pv
root@deploy:~# vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0001
labels:
type: nfs001
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
nfs:
path: "/data/k8sdata/staticdata"
server: 192.168.100.15
NFS创建目录共享
root@harbor:/data/k8sdata# mkdir staticdata
root@harbor:/data/k8sdata# showmount -e localhost
Export list for localhost:
/data/k8sdata *
创建pv
root@deploy:~# kubectl apply -f pv.yaml
PVC示例:
注意:创建的pvc属于namespace下的资源,其他pod想要使用必须与pvc处于一个namespace下。
pvc创建参数:
1、accesModes:PVC访问模式
root@master1:~# kubectl explain PersistentVolumeClaim.spec.accessModes
ReadWriteOnce
卷可以被一个节点以读写方式挂载。 ReadWriteOnce 访问模式也允许运行在同一节点上的多个 Pod 访问卷。
ReadOnlyMany
卷可以被多个节点以只读方式挂载。
ReadWriteMany
卷可以被多个节点以读写方式挂载。
2、resources定义PVC创建存储卷的大小
root@master1:~# kubectl explain PersistentVolumeClaim.spec.resources
3、Selector标签选择器
root@master1:~# kubectl explain PersistentVolumeClaim.spec.selector
matchExpressions
使用正则表达式匹配
matchLabels
匹配标签名称
4、volumeName指定要绑定的pv的名称
root@master1:~# kubectl explain PersistentVolumeClaim.spec.volumeName
5、volumeMode 卷的类型,文件系统|块存储,默认为文件系统
root@master1:~# kubectl explain PersistentVolumeClaim.spec.volumeMode
示例:创建申请nfs的pvc
创建pv
root@deploy:~# vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0001
labels:
type: nfs001
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
nfs:
path: "/data/k8sdata/staticdata"
server: 192.168.100.15
使用matchLabels指定pv
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc-nfs
namespace: default
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
selector:
matchLabels:
type: nfs001
创建后,验证pvc对pv的绑定
root@deploy:~# kubectl get pvc -n default
root@deploy:~# kubectl get pv
查看创建后的pvc详细信息
root@deploy:~# kubectl describe pvc pvc-nfs -n default
Name: pvc-nfs
Namespace: default #所处的namespace
StorageClass:
Status: Bound #pvc的状态
Volume: pv0001 #绑定对应pv的名称
Labels: <none>
Annotations: pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 10Gi #pvc申请的容量
Access Modes: RWO #pvc访问模式为RWO,允许一台节点读写
VolumeMode: Filesystem #卷类型为文件系统
Used By: <none>
Events: <none>
创建deployment绑定pvc
root@deploy:~# cat nfs-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- image: nginx
name: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs-pvc
mountPath: "/usr/share/nginx/html/staticdata"
volumes:
- name: nfs-pvc
persistentVolumeClaim:
claimName: pvc-nfs
---
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: web-svc
name: web-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
nodePort: 30111
selector:
app: web
type: NodePort
创建deployment
root@deploy:~# kubectl apply -f nfs-deployment.yaml
确保deployment和pvc处于同一个namespace中
NFS创建站点文件
root@harbor:/data/k8sdata/staticdata# echo "Testing pvc" >> index.html
验证客户端访问:
验证节点容器挂载卷
验证pod挂载卷
本文来自博客园,作者:PunchLinux,转载请注明原文链接:https://www.cnblogs.com/punchlinux/p/16551285.html