K8s中的PV和PVC

PV 的全称是:PersistentVolume(持久化卷),是对底层的共享存储的一种抽象,PV 由管理员进行创建和配置,它和具体的底层的共享存储技术的实现方式有关,比如 Ceph、GlusterFS、NFS 等,都是通过插件机制完成 与共享存储的对接。

PVC 的全称是:PersistentVolumeClaim(持久化卷声明),PVC 是用户存储的一种声明,PVC 和 Pod 比较类似,Pod 消耗的是节点,PVC 消耗的是 PV 资源,Pod 可以请求 CPU 和内存,而 PVC 可以请求特定的存储空间 和访问模式。对于真正使用存储的用户不需要关心底层的存储实现细节,只需要直接使用 PVC 即可。

但是通过 PVC 请求到一定的存储空间也很有可能不足以满足应用对于存储 设备的各种需求,而且不同的应用程序对于存储性能的要求可能也不尽相 同,比如读写速度、并发性能等,为了解决这一问题,Kubernetes 又引入 了一个新的资源对象:StorageClass,通过 StorageClass 的定义,管理员 可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,用 户根据 StorageClass 的描述就可以非常直观的知道各种存储资源的具体特 性了,就可以根据应用的特性去申请合适的存储资源。

安装NFS

#k8s-master安装
yum -y install nfs-utils rpcbind

#创建共享目录
mkdir -p /usr/local/work/
chmod 755 /usr/local/work/

#配置nfs权限
vim /etc/exports
/usr/local/work *(rw,sync,no_root_squash)

/usr/local/work:是共享的数据目录
*:表示任何人都有权限连接,当然也可以是一个网段,一个 IP,也可
以是域名
rw:读写的权限
sync:表示文件同时写入硬盘和内存
no_root_squash:当登录 NFS 主机使用共享目录的使用者是 root 时,
其权限将被转换成为匿名使用者,通常它的 UID 与 GID,都会变成
nobody 身份 

#启动
systemctl restart rpcbind.service
systemctl enable rpcbind
systemctl start nfs.service
systemctl enable nfs

showmount -e  #可以验证一下

PV

注:有PV才可以创建PVC否则PVC会一直处于pending状态

有了上面的 NFS 共享存储,下面我们就可以来使用 PV 和 PVC 了。PV 作为 存储资源,主要包括存储能力、访问模式、存储类型、回收策略等关键信 息,下面新建一个PV对象,使用 nfs 类型的后端存储,1G 的存储空间,访问模式为 ReadWriteOnce,回收策略为 Recyle,对应的 YAML 文件如下

Kubernetes 支持的 PV 类型有很多,比如常见的 Ceph、GlusterFs、 NFS,甚至 HostPath也可以,不过 HostPath 仅仅可以用于单机测试,更多的支持类型可以前往 Kubernetes PV 官方文档进行查看,因为每种存储类型都有各自的特点,所以我们在使用的时候可以去查看相应的文档来设置对应的参数。

vim pv.yaml 

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nginx-pv
  namespace: work
spec:
  capacity:    #容量叫做capacity 
    storage: 2Gi    #容量为2G
  accessModes:     #访问模式
  - ReadWriteOnce        #只能可读可写挂载在一个pod
  persistentVolumeReclaimPolicy: Recycle      #回收策略
  storageClassName: nginx-pv  
  nfs:              #定义后端使用nfs
    path: /usr/local/work
    server: 192.168.11.11 

kubectl apply -f pv.yaml
#查看
kubectl get pv
NAME        CAPACITY         ACCESS MODES         RECLAIM POLICY                STATUS                  CLAIM         STORAGECLASS   REASON   AGE
nginx-pv     2Gi #容量2G         RWO  #模式          Recycle #回收策略         Available #当前状态     #有没有被使用                          18s

#删除
kubectl delete pv nginx-pv -n work
#如果删除pv卡着
kubectl patch pv nginx-pv -p '{"metadata":{"finalizers":null}}'   #nginx-pv这里为pv名字

Capacity(存储能力) 一般来说,一个 PV 对象都要指定一个存储能力,通过 PV 的 capacity属性 来设置的,目前只支持存储空间的设置,就是 storage=1Gi,不过未来可能会加入 IOPS、吞吐量等指标的配置。

AccessModes(访问模式)

AccessModes 是用来对 PV 进行访问模式的设置,用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:

ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载

ReadOnlyMany(ROX):只读权限,可以被多个节点挂载

ReadWriteMany(RWX):读写权限,可以被多个节点挂载

persistentVolumeReclaimPolicy(回收策略)

Retain(保留)- 保留数据,需要管理员手工清理数据

Recycle(回收)- 清除 PV 中的数据,效果相当于执行 rm -rf /work/*

Delete(删除)- 与 PV 相连的后端存储完成 volume 的删除操作,当然这常见于云服务商的存储服务,比如 ASW EBS

不过需要注意的是,目前只有 NFS 和 HostPath 两种类型支持回收策略。 当然一般来说还是设置为 Retain 这种策略保险一点

一个 PV 的生命周期中,可能会处于4中不同的阶段:

Available(可用):表示可用状态,还未被任何 PVC 绑定

Bound(已绑定):表示 PVC 已经被 PVC 绑定

Released(已释放):PVC 被删除,但是资源还未被集群重新声明

Failed(失败): 表示该 PV 的自动回收失败

PVC

在使用 PVC 之前,我们还得把其他节点上的 nfs 客户端给安装上,否则可能会导致 PV 挂载不上的问题

vim pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc
  namespace: work
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
  storageClassName: nginx-pv

kubectl create -f pvc.yaml
kubectl get pvc

#删除
kubectl delete pvc nginx-pvc -n work

系统自动去匹配,他会根据我们的声明要求去查找处于 Available 状态的 PV,如果没有找到的话那么我们的 PVC 就会一直处于 Pending 状态,找到了的话当然就会把当前的 PVC 和目标 PV 进行绑定,这个时候状态就会变成 Bound 状态了

示例:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nginx-pv
  namespace: work
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nginx-pv
  nfs:
    path: /usr/local/work
    server: 192.168.11.11
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc
  namespace: work
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
  storageClassName: nginx-pv
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-web
  namespace: work
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      hostNetwork: true
      containers:
        - name: nginx
          image: nginx:1.18
          ports:
            - containerPort: 80
          volumeMounts:
          - name: work
            mountPath: /work
          livenessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 15
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 10
            periodSeconds: 15
      volumes:
      - name: work
        persistentVolumeClaim:
          claimName: nginx-pvc

 kubectl exec -it -n work nginx-web-7fd9d67bcf-2pm2r -- /bin/bash

#注意不能删除pvc一般情况将pv和pvc单独去写,一旦删除pvc宿主机目录下的文件也会删除