0
点赞
收藏
分享

微信扫一扫

Kubernetes——pv(静态+动态storageclass)与pvc

凉夜lrs 2022-04-06 阅读 57

PVC和PV

PV概念

  1. PersistentVolume(PV)是集群中已由管理员配置的一段网络存储。集群中的资源就像一个节点是一个集群资源,可以从远程的NFS或分布式对象存储系统中创建得来(pv存储空间大小、访问方式)
  2. Pv是诸如卷之类的卷插件,但是只有独立于使用Pv的任何单个pod的生命周期。
  3. 该API对象捕获存储的实现细节,即NFS,isCSI或云提供商特定的存储系统
  4. PV就是从存储设备中的空间创建出一个存储资源

PVC概念

  1. PersistentVolumeClaim (Pvc)是用户存储的请求。Pvc的使用逻辑:在podt中定义一个存储卷(该存储卷类型为pvc),定义的时候直按指定大小,pvc必须与对应的pv建立关系,pvc会根据定义去pv申请,而pv是由存储空间创建出来的。pr和pvc是kubernetes抽象出来的一种存储资源
  2. 虽然PersistentVolumeClaims允许用户使用抽象存储资源,但是常见的需求是,用户需要根据不同的需求去创建pv,用于不同的场景。而此时需要集群管理员提供不同需求的Pv,而不仅仅是Pv的大小和访问模式,但又不需要用户了解这些卷的实现细节
  3. 对于这样的需求,此时可以采用storageclass资源

PV与PVC之间的关系

  1. PV是集群中的资源。
  2. Pvc是对这些资源的请求,也是对资源的索引检查。
  3. PV和Pvc之间的相互作用遵循这个生命周期:Provisioning(配置)---> Binding(绑定)--->Using(使用)--->Releasing(释放)--->Recycling(回收)
  • Provisioning,即 PV的创建,可以直接创建PV(静态方式),也可以使用StorageClass动态创建
  • Binding,将PV 分配给pvc
  • using,Pod通过 Pvc使用该Volume,并可以通过准入控制StorageProtection (1.9及以前版本为PVCProtection〉阻止删除正在使用的 Pvc
  • Releasing,Pod 释放volume并删除pvc
  • Reclaiming,回收 PV,可以保留PV以便下次使用,也可以直接从云存储中删除

根据这5个阶段,PV状态有以下4种:

  • Available (可用):表示可用状态,还未被任何PVC绑定B
  • ound (己绑定):表示PV 己经绑定到Pvc
  • Released(己释放):表示PVC被删掉,但是资源尚未被集群回收
  • Failed(失败):表示该 PV的自动回收失败

12.png

13.png

14.png

一个PV从创建到销毁的具体流程如下:

1、一个PV创建完后状态会变成Available,等待被PVc绑定。
2、一旦被PVC邦定,v的状态会变成Bound,就可以被定义了相应Pvd的Pod使用。
3、Pod使用完后会释放PV,PV的状态变成Released。
4、变成Released的PV会根据定义的回收策略做相应的回收工作。有三种回收策略,Retain、Delete和Recycle。Betain就是保留现场,RBs集群什么也不做,等待用户手动去处理FV里的数据,处理完后,再手动删除PV。Delete策略,KS8会自动删除该Pv及里面的数据。Recycle方式,K08会将Pv里的数据删除,然后把Pv的状态变成Available,又可以被新的PVc绑定使用。

两种PV的提供方式

  • 这里有两种PV的提供方式: 静态或者动态
  1. 静态-->直接固定存储空间:
    集群管理员创建一些PV。它们携带可供集群用户使用的真实存储的详细信息。它们存在于Ktbernetes API中,可用于消费
  2. 动态-->通过存储类进行动态创建存储空间:
    当管理员创建的静态PV都不匹配用户的 PvC时,集群可能会尝试动态地为 Pvc配置卷。此配置基于StorageClasses: PvC必须请求存储类,并且管理员必须已创建并配置该类才能进行动态配置。要求该类的声明有效地为自己禁用动态配置

查看pv和pvc的定义方式

使用explain 查看pv的定义方式

查看pv的定义方式

kubectl  explain pv  #查看pv的定义方式

FIELDS:
  apiVersion
  kind
  metadata  #由PV是集群级别的资源,即Pv可以跨namespace使用,所以PV的 metadata中不用配置. namespace
  spec

查看pv定义的规格

[root@master ~]# kubectl  explain pv.spec
spec:
  nfs (定义存储类型)
    path (定义挂载卷路径)
    server (定义服务器名称)
  accessModes (定义访问模型,有以下三种访问模型,以列表的方式存在,也就是说可以定义多个访问模式)
    ReadwriteOnce (RWO) 单节点读写
    ReadonlyMany (ROX) 多节点只读
    ReadwriteMany (RWX) 多节点读写
  capacity (定义PV空间的大小)
    storage (指定大小)

image-20220405115603073

使用explain 查看pvc的定义方式

查看pvc的定义方式

kubectl  explain  pvc  #查看pvc的定义方式
KIND:  PersistentVolumeClaim
VERSION:  v1
FIELDS:
    apiVersion: <string>
    kind <string>
    metadata <Object>
    spec <Object>

查看pvc的规格

kubectl  explain pvc.spec  #查看pvc的规格

spec:
    accessModes (定义访问模式,必须是pv的访问模式的子集)
    resources (定义申请资源的大小)
      requests:  
      storage:

配置nfs使用pv和pvc

配置nfs存储

yum -y install nfs-utils rpcbind
mkdir -p /data/volumes/v{1..5}
ls -R /data/
chmod  -R 777 /data/*
#配置nfs共享的目录
for i in {1..5}
do 
echo "/data/volumes/v$1 192.168.80.0/24(rw,no_root_squash,sync)" >> /etc/exports
done 

#写入网页内容
[root@nfs ~]# for i in {1..5}
do
echo "this is pv00$i" > /data/volumes/v$i/index.html
done
systemctl  start rpcbind
systemctl start nfs
exportfs  -arv
showmount  -e

定义pv

定义5个 pv,并且定义挂载的路径及访问模式,pv划分大小

vim pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv001
  labels:
    name: pv001
spec:
  nfs:
    path: /data/volumes/v1
    server: stor01
  accessModes: 
    - ReadWriteMany
    - ReadWriteOnce
  capacity:
    storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv002
  labels:
    name: pv002
spec:
  nfs:
    path: /data/volumes/v2
    server: stor01
  accessModes: 
    - ReadWriteOnce
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv003
  labels:
    name: pv003
spec:
  nfs:
    path: /data/volumes/v3
    server: stor01
  accessModes: 
    - ReadWriteMany
    - ReadWriteOnce
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv004
  labels:
    name: pv004
spec:
  nfs:
    path: /data/volumes/v4
    server: stor01
  accessModes: 
    - ReadWriteMany
    - ReadWriteOnce
  capacity:
    storage: 4Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv005
  labels:
    name: pv005
spec:
  nfs:
    path: /data/volumes/v5
    server: stor01
  accessModes: 
    - ReadWriteMany
    - ReadWriteOnce
  capacity:
    storage: 5Gi

kubectl  apply  -f pv-demo.yaml 
kubectl  get pv

搭建 StorageClass + NFS,实现 NFS 的动态 PV 创建

Kubernetes 本身支持的动态 PV 创建不包括 NFS,所以需要使用外部存储卷插件分配PV。详见:https://kubernetes.io/zh/docs/concepts/storage/storage-classes/

卷插件称为 Provisioner(存储分配器),NFS 使用的是 nfs-client,这个外部卷插件会使用已经配置好的 NFS 服务器自动创建 PV。
Provisioner:用于指定 Volume 插件的类型,包括内置插件(如 kubernetes.io/aws-ebs)和外部插件(如 external-storage 提供的 ceph.com/cephfs)。

1、在stor01节点上安装nfs,并配置nfs服务

mkdir /opt/k8s
chmod 777 /opt/k8s/

vim /etc/exports
/opt/k8s 192.168.80.0/24(rw,no_root_squash,sync)

systemctl restart nfs

image-20220406094728917

2、创建 Service Account

用来管理 NFS Provisioner 在 k8s 集群中运行的权限,设置 nfs-client 对 PV,PVC,StorageClass 等的规则

vim nfs-client-rbac.yaml
#创建 Service Account 账户,用来管理 NFS Provisioner 在 k8s 集群中运行的权限
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
---
#创建集群角色
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nfs-client-provisioner-clusterrole
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: ["list", "watch", "create", "update", "patch"]
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
---
#集群角色绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: nfs-client-provisioner-clusterrolebinding
subjects:
- kind: ServiceAccount
  name: nfs-client-provisioner
  namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-clusterrole
  apiGroup: rbac.authorization.k8s.io

kubectl apply -f nfs-client-rbac.yaml

3、使用 Deployment 来创建 NFS Provisioner

NFS Provisione(即 nfs-client),有两个功能:一个是在 NFS 共享目录下创建挂载点(volume),另一个则是将 PV 与 NFS 的挂载点建立关联。

#由于 1.20 版本启用了 selfLink,所以 k8s 1.20+ 版本通过 nfs provisioner 动态生成pv会报错,解决方法如下:
vim /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
  containers:
  - command:
    - kube-apiserver
    - --feature-gates=RemoveSelfLink=false       #添加这一行
    - --advertise-address=192.168.80.20
......

kubectl apply -f /etc/kubernetes/manifests/kube-apiserver.yaml

kubectl get pods -n kube-system | grep apiserver
kubectl delete pods kube-apiserver -n kube-system 

#创建 NFS Provisioner
vim nfs-client-provisioner.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nfs-client-provisioner
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-client-provisioner
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner      #指定Service Account账户
      containers:
        - name: nfs-client-provisioner
          image: quay.io/external_storage/nfs-client-provisioner:latest
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: nfs-storage       #配置provisioner的Name,确保该名称与StorageClass资源中的provisioner名称保持一致
            - name: NFS_SERVER
              value: stor01           #配置绑定的nfs服务器
            - name: NFS_PATH
              value: /opt/k8s          #配置绑定的nfs服务器目录
      volumes:              #申明nfs数据卷
        - name: nfs-client-root
          nfs:
            server: stor01
            path: /opt/k8s

kubectl apply -f nfs-client-provisioner.yaml 

kubectl get pod
NAME                                   READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-cd6ff67-sp8qd   1/1     Running   0          14s

4、创建 StorageClass

创建 StorageClass,负责建立 PVC 并调用 NFS provisioner 进行预定的工作,并让 PV 与 PVC 建立关联

vim nfs-client-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client-storageclass
provisioner: nfs-storage     #这里的名称要和provisioner配置文件中的环境变量PROVISIONER_NAME保持一致
parameters:
  archiveOnDelete: "false"   #false表示在删除PVC时不会对数据进行存档,即删除数据

kubectl apply -f nfs-client-storageclass.yaml

kubectl get storageclass
NAME                      PROVISIONER   AGE
nfs-client-storageclass   nfs-storage   43s

5、创建 PVC 和 Pod 测试

vim test-pvc-pod.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-nfs-pvc
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: nfs-client-storageclass    #关联StorageClass对象
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: test-storageclass-pod
spec:
  containers:
  - name: busybox
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    command:
    - "/bin/sh"
    - "-c"
    args:
    - "sleep 3600"
    volumeMounts:
    - name: nfs-pvc
      mountPath: /mnt
  restartPolicy: Never
  volumes:
  - name: nfs-pvc
    persistentVolumeClaim:
      claimName: test-nfs-pvc      #与PVC名称保持一致

kubectl apply -f test-pvc-pod.yaml

//PVC 通过 StorageClass 自动申请到空间
kubectl get pvc
NAME            STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS              AGE
test-nfs-pvc   Bound    pvc-11670f39-782d-41b8-a842-eabe1859a456   1Gi        RWX            nfs-client-storageclass   2s

//查看 NFS 服务器上是否生成对应的目录,自动创建的 PV 会以 ${namespace}-${pvcName}-${pvName} 的目录格式放到 NFS 服务器上
ls /opt/k8s/
default-test-nfs-pvc-pvc-11670f39-782d-41b8-a842-eabe1859a456

//进入 Pod 在挂载目录 /mnt 下写一个文件,然后查看 NFS 服务器上是否存在该文件
kubectl exec -it test-storageclass-pod sh
/ # cd /mnt/
/mnt # echo 'this is test file' > test.txt

//发现 NFS 服务器上存在,说明验证成功
cat /opt/k8s/test.txt
举报

相关推荐

0 条评论