k8s pv与pvc
k8s pv与pvc
概念
PV
我们想要持久化k8s pod中的数据,就需要用到存储,找一个地方,存放数据。不然一旦pod被删除,则数据就丢失了。
在k8s中,pv就是存储数据的地方,可以理解为pv就是存储后端。
pv可以由多种存储系统提供,如NFS,GFS,本地,CIFS,云存储集群等
PVC
用户想要使用PV,就需要申请,说明要多大的空间,以及其他属性(例如读写属性:只读,只写,读写。速度属性:快、中、慢)。用户把这些需要的信息通过PVC进行申明,然后由k8s选择合适的PV,然后绑定在一起。这样就可以在pod中挂载PVC,然后使用PV,把数据存起来。
A:为什么用户不直接申请PV,直接使用PV
Q:①降低用户使用门槛
假设直接使用PV,则用户需要知道PV是怎么产生的,有哪些属性。
要使用PV时,就需要把属性传递给PV,PV才能通过存储系统来生成需要的空间。
这就要求用户需要了解那些存储后端。然后才能合理使用,不然就无法生成需要的空间。
用户只需要关心自己需要多大的空间以及一些自己想要的属性。仅此而已!
②管理员方便管理
管理员可以把存储后端给更专业的存储后端人员处理。然后混合使用不同的存储后端。这样存储就多样化了。能应对用户不同的存储需求。
PV参数
举个例子,然后说明定义PV的参数
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv1
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
nfs:
server: 172.17.134.126
path: "/data/k8s"
capacity
capacity 表示存储能力
capacity.storage 表示空间大小, 例如5Gi
accessModes
accessModes 表示访问模式,用于描述用户应用对存储资源的访问权限,有以下几个选项
值 | 缩写 | 说明 |
---|---|---|
ReadWriteOnce | RWO | 读写权限,但是只能被单个节点挂载 |
ReadOnlyMany | ROX | 只读权限,可以被多个节点挂载 |
ReadWriteMany | RWX | 读写权限,可以被多个节点挂载 |
persistentVolumeReclaimPolicy
指定回收策略,有以下几个选项
值 | 说明 |
---|---|
Retain | K8S什么也不做,等待用户手动去处理PV里的数据,处理完后,再手动删除PV。 |
Delete | K8S会自动删除该PV及里面的数据 |
Recycle(已废弃) | K8S会将PV里的数据删除,然后把PV的状态变成Available,又可以被新的PVC绑定使用 |
生命周期
PV的生命周期有以下几个选项
值 | 说明 |
---|---|
Available | 表示可用状态,还未被任何 PVC 绑定 |
Bound | 表示 PV 已经被 PVC 绑定 |
Released | PVC 被删除,但是资源还未被集群重新声明,数据还存在 |
Failed | 表示该 PV 的自动回收失败 |
PVC参数
举个例子,然后说明定义PVC的参数
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc1
spec:
accessModes:
- ReadWriteOnce
storageClassName: sc-name
resources:
requests:
storage: 5Gi
accessModes
和PV一样
resources.requests.storage
表示用户想要申请的PV的大小
storageClassName
指定storageClass的名称,后续会根据这个名称,找到匹配的pv
说明
创建PVC后,k8s会根据resources.requests.storage和accessModes、storageClassName属性,与所有PV进行配对,选出一个合适的PV,来与PVC进行绑定。
如果没有匹配的PV,则会绑定失败
静态创建PV
静态创建PV,就是管理员首先创建出一些PV,然后用户根据PVC进行申请,使用PV。
使用nfs作为后端存储,测试pv和pvc
虚机信息
IP | 功能 | ||
---|---|---|---|
172.17.134.134 | k8s master节点 | ||
172.17.139.162 | k8s worker节点 | ||
172.17.140.87 | k8s worker节点 | ||
172.17.134.126 | nfs服务器 |
k8s信息
版本:1.22.0
部署NFS服务
在172.17.134.126执行以下命令,部署NFS服务
关闭防火墙
systemctl stop firewalld.service && systemctl disable firewalld.service && systemctl status firewalld.service
下载nfs和rpc服务
yum -y install nfs-utils rpcbind
创建数据目录
mkdir -p /data/k8s/
chmod 755 /data/k8s/
暴露数据目录
编辑/etc/exports
文件,输入以下内容
/data/k8s *(rw,sync,no_root_squash)
nfs权限说明
- ro 只读
- rw 可读写
- sync 同步写数据,保证数据不丢失
- async 异步写数据,在写入持久化存储之前进行请求响应,如果服务器重启可能会导致文件丢失或者损坏
- root_squash 将root用户(uid/gid 0)的请求映射为匿名用户(anonymous uid/gid)
- no_root_squash 禁用root_squash规则
- all_squash 将所有用户都映射为匿名用户
- no_all_squash 禁用all_squash规则,默认选项
- anonuid 指定要映射为匿名用户的uid,例如:anonuid=150
- anongid 指定要映射为匿名用户的gid,例如:anongid=100
启动rpc服务
systemctl start rpcbind && systemctl enable rpcbind && systemctl status rpcbind
启动nfs服务
systemctl start nfs && systemctl enable nfs && systemctl status nfs
验证服务是否可用
-
本地验证
rpcinfo -p|grep nfs
cat /var/lib/nfs/etab
-
客户端挂载验证
在172.17.140.87执行以下命令,验证是否可以使用nfs服务
showmount -e 172.17.134.126
mkdir -p /home/nfs_from_126/data
mount -t nfs 172.17.134.126:/data/k8s /home/nfs_from_126/data
cd /home/nfs_from_126/data
echo i am 172.17.139.162 host file >> 162.txt
在nfs服务器中查看,是否有该文件,有则OK,否则nfs服务搭建失败,需要排查,重新搭建
定义pv
nfs-pv1.yml
创建5Gi大小,访问属性是ReadWriteOnce的PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv1
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
nfs:
server: 172.17.134.126
path: "/data/k8s"
nfs-pv2.yml
创建1Gi大小,访问属性是ReadWriteOnce的PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv2
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
nfs:
server: 172.17.134.126
path: "/data/k8s"
nfs-pv3.yml
创建5Gi大小,访问属性是ReadWriteMany的PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv3
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
server: 172.17.134.126
path: "/data/k8s"
nfs-pv4.yml
创建1Gi大小,访问属性是ReadWriteMany的PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv4
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
server: 172.17.134.126
path: "/data/k8s"
应用pv
kubectl apply -f nfs-pv1.yml
kubectl apply -f nfs-pv2.yml
kubectl apply -f nfs-pv3.yml
kubectl apply -f nfs-pv4.yml
查看pv
kubectl get pv -o wide
定义PVC
nfs-pvc1.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc1
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
应用PVC
kubectl apply -f nfs-pvc1.yml
查看PVC
kubectl get pvc -o wide
查看pv与pvc的关系
kubectl get pv -o wide
可以看到,PVC:nfs-pvc1与PV:nfs-pv1绑定在一起了
注意事项
假设,我要申请的PVC的大小超过了5Gi,则PVC与PV会绑定失败,会一直等待绑定
提示信息 no persistent volumes available for this claim and no storage class is set
使用PVC
- 定义pod
nfs-pvc1.yml
apiVersion: v1
kind: Pod
metadata:
name: nfs-pod1
spec:
containers:
- name: nginx
image: nginx:1.14.2
imagePullPolicy: IfNotPresent
command: ["/bin/bash","-c","echo begin;sleep 3600;echo end"]
volumeMounts:
- mountPath: "/home/nfs-pod1" #挂载的路径
name: nfs-pod1 #要与①相同
volumes:
- name: nfs-pod1 #要与①相同
persistentVolumeClaim:
claimName: nfs-pvc1 # 使用kubectl get pvc 获取到的 pvc
- 应用pod
kubectl apply -f nfs-pod1.yml
在pod中创建文件,在nfs上就能看到
nfs中查看
删除PVC
kubectl delete pvc nfs-pvc1
删除PV
kubectl delete pv nfs-pv1
kubectl delete pv nfs-pv2
kubectl delete pv nfs-pv3
kubectl delete pv nfs-pv4
动态创建PV
静态创建有个弊端,就是必须管理员先手动创建PV,然后用户创建PVC,然后才能申请PV使用。
作为管理员,面对多样的场景,也不能做很多PV来用,也做不了那么多。做了的PV也会存在浪费的情况,例如PV是50Gi,但用户申请PVC未5Gi,此时没有其他可用的PV,则该PVC与PV绑定了,就浪费了45Gi。
因此,需要k8s根据用户提交的PVC,自动创建PV且绑定。这就引入了动态创建PV
说明
先删除之前的所有PVC和PV,然后再测试
原理
【待填充】
创建RBAC
rbac.yml
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner #与②相同
namespace: default #根据实际环境设定namespace,下面类同
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner #与①相同
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner #与②相同
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner #与①相同
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner #与③相同
# replace with namespace where provisioner is deployed
namespace: default
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner #与②相同
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner #与③相同
apiGroup: rbac.authorization.k8s.io
创建nfs-client-provisioner
nfs-client-provisioner.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default #与RBAC文件中的namespace保持一致
spec:
replicas: 1
selector:
matchLabels:
app: nfs-client-provisioner
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: master-nfs-storage #provisioner名称,请确保该名称与StorageClass的provisioner名称保持一致
- name: NFS_SERVER
value: 172.17.134.126 #NFS Server IP地址
- name: NFS_PATH
value: /data/k8s #NFS挂载卷
volumes:
- name: nfs-client-root
nfs:
server: 172.17.134.126 #NFS Server IP地址
path: /data/k8s #NFS 挂载卷
创建StorageClass
storageclass.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: master-nfs-storage
provisioner: master-nfs-storage #这里的名称要和的provisioner配置文件中的环境变量PROVISIONER_NAME保持一致
parameters:
archiveOnDelete: "false"
reclaimPolicy: Retain
应用配置
kubectl apply -f rbac.yml
kubectl apply -f nfs-client-provisioner.yml
kubectl apply -f storageclass.yml
查看配置
kubectl get deployments
kubectl get pod
kubectl get sc
测试
创建pvc,使用pod挂载pvc,测试是否可以自动创建pv
创建PVC
nfs-dy-pvc1.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-dy-pvc1
spec:
accessModes:
- ReadWriteOnce #表示该volume只能被单个节点以读写的方式映射
resources:
requests:
storage: 5Gi
storageClassName: master-nfs-storage #指定storageclass 与StorageClass中的provisioner一致
kubectl apply -f nfs-dy-pvc1.yml
查看PVC和PV
kubectl get pvc
kubectl get pv
kubectl describe pv pvc-78ce936e-a001-4881-a030-ae9465f8e252
可以看到,已经自动创建了PV,且和PVC绑定了
nfs创建的路径是 /data/k8s/default-nfs-dy-pvc1-pvc-78ce936e-a001-4881-a030-ae9465f8e252
创建pod
nfs-dy-pod1.yml
apiVersion: v1
kind: Pod
metadata:
name: nfs-dy-pod1
spec:
containers:
- name: nginx
image: nginx:1.14.2
imagePullPolicy: IfNotPresent
command: ["/bin/bash","-c","echo begin;sleep 3600;echo end"]
volumeMounts:
- mountPath: "/home/nfs-dy-pod1" #挂载的路径
name: volume1 #要与①相同
volumes:
- name: volume1 #要与①相同
persistentVolumeClaim:
claimName: nfs-dy-pvc1 # 使用kubectl get pvc 获取到的 pvc
kubectl apply -f nfs-dy-pod1.yml
查看Pod
kubectl get pod
kubectl logs nfs-dy-pod1
在pod中测试
kubectl exec -it nfs-dy-pod1 -- bash
cd /home/nfs-dy-pod1/
echo nfs-dy-pod1-1 > nfs-dy-pod1-1.txt
echo nfs-dy-pod1-2 > nfs-dy-pod1-2.txt
echo nfs-dy-pod1-3 > nfs-dy-pod1-3.txt
在nfs上查看
路径 /data/k8s/default-nfs-dy-pvc1-pvc-78ce936e-a001-4881-a030-ae9465f8e252
删除pod
kubectl delete pod nfs-dy-pod1
删除PVC
kubectl delete pvc nfs-dy-pvc1
删除PV
kubectl get pv
kubectl delete pv pvc-78ce936e-a001-4881-a030-ae9465f8e252
删除PV后,nfs的数据依旧存在
备注
保护的PVC和PV
如果用户删除被某 Pod 使用的 PVC 对象,该 PVC 申领不会被立即移除。 PVC 对象的移除会被推迟,直至其不再被任何 Pod 使用。 此外,如果管理员删除已绑定到某 PVC 申领的 PV 卷,该 PV 卷也不会被立即移除。 PV 对象的移除也要推迟到该 PV 不再绑定到 PVC。
你可以看到当 PVC 的状态为 Terminating
且其 Finalizers
列表中包含 kubernetes.io/pvc-protection
时,PVC 对象是处于被保护状态的。
链接
【精选】k8s搭建nfs创建pv、pvc_创建基于nfs的pv pvc_zhoujianhui008的博客-CSDN博客
k8s 使用StorageClass+NFS动态创建pv - yg0070 - 博客园 (cnblogs.com)