kubernetes PV和PVC持久卷
参考URL: https://baiyongjie.com/?p=552
PersistentVolume(pv)和PersistentVolumeClaim(pvc)是k8s提供的两种API资源,用于抽象存储细节,用于实现持久化存储.
PersistentVolume(PV)是集群中由管理员配置的一段网络存储。
是由管理员设置的存储,它是群集的一部分。就像节点是集群中的资源一样,PV 也是集群中的资源。 PV 是 Volume 之类的卷插件,但具有独立于使用 PV 的 Pod 的生命周期。此 API 对象包含存储实现的细节,即 NFS、iSCSI 或特定于云供应商的存储系统
PersistentVolumeClaim(PVC)是由用户进行存储的请求。
它与 Pod 相似。Pod 消耗节点资源,PVC 消耗 PV 资源。Pod 可以请求特定级别的资源(CPU 和内存)。PVC声明可以请求特定的大小和访问模式(如:读写或只读)
PV支持的类型 https://kubernetes.io/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes
总结:Persistent Volume(持久化卷)简称PV, 是一个K8S资源对象,我们可以单独创建一个PV, 它不和Pod直接发生关系, 而是通过Persistent Volume Claim, 简称PVC来实现动态绑定, 我们会在Pod定义里指定创建好的PVC, 然后PVC会根据Pod的要求去自动绑定合适的PV给Pod使用。
访问模式(accessModes)
#安装依赖包
yum -y install nfs-utils rpcbind
#创建要存放文件的目录
mkdir -p /data/app/share
chown -R nfsnobody.nfsnobody /data/app/share
#开机启动,
systemctl enable rpcbind.service
systemctl enable nfs-server.service
systemctl start rpcbind.service #端口是111
systemctl start nfs-server.service # 端口是 2049
# 将要共享的目录输入到 /etc/exports 配置文件
echo "/data/app/share 0.0.0.0/0(rw,sync,all_squash)" >> /etc/exports
#root_squash:在登入 NFS 主机使用分享之目录的使用者如果是 root 时,那么这个使用者的权限将被压缩成为匿名使用者,通常他的 UID 与 GID 都会变成 nobody 那个系统账号的身份。
#no_root_squash:登入 NFS 主机使用分享目录的使用者,如果是 root 的话,那么对于这个分享的目录来说,他就具有 root 的权限!这个项目『极不安全』,不建议使用!
#all_squash:登入 NFS 主机使用分享目录的使用者,所有用户均被压缩成为匿名使用者,即已nobody用户的身份登录。
#anonuid和anongid:明确指定匿名使用者使用指定的id值用户的权限,访问分享的目录。
#secure:限制客户端只能从小于1024的tcp/ip端口连接nfs服务器(默认设置)。
#insecure:允许客户端从大于1024的tcp/ip端口连接服务器。
exportfs -rv
# 查看配置
exportfs
上面是linux搭建nfs过程,这里我们需要测试k8s pv,所以改一下共享目录名,重新共享出去:
mkdir /data/pvdata
chown nfsnobody:nfsnobody /data/pvdata
echo "/data/pvdata 0.0.0.0/0(rw,sync,all_squash)" >> /etc/exports
exportfs -rv
cat /etc/exports
exportfs
# 修改完成后再重启一下nfs
systemctl start rpcbind.service #端口是111
systemctl start nfs-server.service # 端口是 2049
# 查看共享文件
[root@storage1 ~]# showmount -e 127.0.0.1
Export list for 127.0.0.1:
/data/pvdata 0.0.0.0/0
/data/app/share 0.0.0.0/0
[root@storage1 ~]#
查看挂载相关日志
cat /var/log/messages | grep mount
查看当前client端挂载的配置信息,可以通过如下命令:
$ mount|grep nfs
取消mount挂载:
$ umount /xxx/xxxx(client端的挂载目录)
vi pv.yaml 创建yaml文件
# cat pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-data #pv的名称
spec:
capacity: #容量
storage: 10Gi #pv可用的大小
accessModes: #访问模式
- ReadWriteOnce #PV以read-write挂载到一个节点
persistentVolumeReclaimPolicy: Recycle #持久卷回收策略
storageClassName: nfs #存储类名称 重要:需将来的PVC中定义的一样
nfs:
path: /data/pvdata #NFS的路径
server: 172.22.22.215 #NFS的IP地址
[root@kubernetes-master ~]# vi pv.yaml
[root@kubernetes-master ~]# kubectl apply -f pv.yaml
persistentvolume/pv-data created
[root@kubernetes-master ~]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-data 10Gi RWO Recycle Available nfs 10s
[root@kubernetes-master ~]#
在使用 PVC 之前,我们还得把其他节点上的 nfs 客户端给安装上,使用kubectl get nodes查看所有节点
kubectl get nodes
yum -y install nfs-utils rpcbind
vi pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-nfs #PVC的名称
spec:
accessModes:
- ReadWriteOnce #PVC以read-write挂载到一个节点
resources:
requests:
storage: 10Gi #PVC允许申请的大小
# kubectl apply -f pvc.yaml
persistentvolumeclaim/pvdata created
# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
nginx-log Bound pv-data 10Gi RWO 18m
经过测试,发现在k8s,PVC 也是namespace隔离的。这里没有指定,就是默认的namespace。pvc是命名空间隔离的,pv可以全局共享,不用指定命名空间。
pv是全局的,pvc可以指定namespace,在如下位置加入 namespace
metadata:
name: pvc-nfs #PVC的名称
namespace: mongo
[root@kubernetes-master ~]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mongo-storage Pending
使用命令查看详细信息
[root@kubernetes-master ~]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mongo-storage Pending 10m
[root@kubernetes-master ~]# kubectl describe pvc mongo-storage
Name: mongo-storage
Namespace: default
StorageClass:
Status: Pending
Volume:
Labels:
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"PersistentVolumeClaim","metadata":{"annotations":{},"name":"mongo-storage","namespace":"default"},"spec":{"acce...
Finalizers: [kubernetes.io/pvc-protection]
Capacity:
Access Modes:
VolumeMode: Filesystem
Mounted By:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal FailedBinding 118s (x42 over 12m) persistentvolume-controller no persistent volumes available for this claim and no storage class is set
[root@kubernetes-master ~]#
原因分析:
理论上,根据网上信息
并没有在 pvc-nfs 中指定关于 pv 的什么标志,它们之间是怎么就关联起来了的呢?
解答:其实这是系统自动帮我们去匹配的,它会根据我们的声明要求去查找处于 Available 状态的 PV,如果没有找到的话那么PVC 就会一直处于 Pending 状态,找到了的话当然就会把当前的 PVC 和目标 PV 进行绑定,这个时候状态就会变成 Bound 状态了。
根据网上描述:
创建PV、PVC二者后,如果能够自动绑定,说明NFS系统工作正常。在 PVC 绑定 PV 时通常根据两个条件来绑定,一个是存储的大小,另一个就是访问模式。
这里我一直是Pending。
k8s 如何关联pvc到特定的pv?
参考URL: https://www.jianshu.com/p/99e610067bc8
通过上面参考URL的分析,我们可以看到PVC和PV的绑定,不是简单的通过Label来进行。而是要综合storageClassName,accessModes,matchLabels以及storage来进行绑定。
根据PVC和PV绑定原理分析,我这里是PV指定了storageClassName: nfs #存储类名称,PVC里面又没有指定storageClassName导致。
因此,
[root@kubernetes-master ~]# vi pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongo-storage #PVC的名称 如 nginx-log 一般指出用途
spec:
accessModes:
- ReadWriteOnce #PVC以read-write挂载到一个节点
storageClassName: nfs
resources:
requests:
storage: 10Gi #PVC允许申请的大小
[root@kubernetes-master ~]#
先删除刚才没有绑定的pvc,在用新yaml生成新的pvc,命令如下:
[root@kubernetes-master ~]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mongo-storage Pending 76m
[root@kubernetes-master ~]# kubectl delete pvc mongo-storage
persistentvolumeclaim "mongo-storage" deleted
[root@kubernetes-master ~]# kubectl apply -f pvc.yaml
persistentvolumeclaim/mongo-storage created
[root@kubernetes-master ~]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mongo-storage Bound pv-data 10Gi RWO nfs 2s
[root@kubernetes-master ~]#
查看nfs日志
cat /var/log/messages | grep mount
报错
Feb 4 03:19:26 storage1 dockerd: time=“2020-02-04T03:19:26.861842395+08:00” level=warning msg=“Using pre-4.0.0 kernel for overlay2, mount failures may require kernel update” storage-driver=overlay2
Feb 4 03:22:32 storage1 rpc.mountd[960]: refused mount request from 192.168.13.101 for /data/app/share (/data/app/share): unmatched host
Kubernetes对象之PersistentVolume,StorageClass和PersistentVolumeClaim
参考URL: https://www.jianshu.com/p/99e610067bc8
k8s使用nfs动态存储
参考URL: https://www.cnblogs.com/cuishuai/p/9152277.html
有两种PV提供的方式:静态和动态。
静态
集群管理员创建多个PV,它们携带着真实存储的详细信息,这些存储对于集群用户是可用的。它们存在于Kubernetes API中,并可用于存储使用。
动态
当管理员创建的静态PV都不匹配用户的PVC时,集群可能会尝试专门地供给volume给PVC。这种供给基于StorageClass:PVC必须请求这样一个等级,而管理员必须已经创建和配置过这样一个等级,以备发生这种动态供给的情况。请求等级配置为“”的PVC,有效地禁用了它自身的动态供给功能。
上文中我们通过PersistentVolume描述文件创建了一个PV。这样的创建方式我们成为静态创建。这样的创建方式有一个弊端,那就是假如我们创建PV时指定大小为50G,而PVC请求80G的PV,那么此PVC就无法找到合适的PV来绑定。因此产生了了PV的动态创建。
PV的动态创建依赖于StorageClass对象。我们不需要手动创建任何PV,所有的工作都由StorageClass为我们完成。
一个例子如下:
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: slow
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
zones: us-east-1d, us-east-1c
iopsPerGB: "10"
这个例子使用AWS提供的插件( kubernetes.io/aws-ebs)创建了一个基于AWS底层存储的StorageClass。这意味着使用这个StorageClass,那么所有的PV都是AWSElasticBlockStore类型的。
StorageClass的定义包含四个部分:
手动创建的PV时,我们指定了storageClassName=slow的配置项,然后Pod定义中也通过指定storageClassName=slow,从而完成绑定。而通过StorageClass实现动态PV时,我们只需要指定StorageClass的metadata.name。
回到上文中创建PVC的例子,此时PVC指定了storageClassName=slow。那么Kubernetes会在集群中寻找是否存在metadata.name=slow的StorageClass,如果存在,此StorageClass会自动为此PVC创建一个accessModes = ReadWriteOnce,并且大小为8GB的PV。
通过StorageClass的使用,使我们从提前构建静态PV池的工作中解放出来。
Linux安装配置NFS方法
https://jingyan.baidu.com/article/e5c39bf5f3a8df39d660335e.html