k8s的pv和pvc概念

存储卷

  同一个pod内的所有容器共享存储 网络 用户等空间     pod内的容器都是以pause镜像为基础镜像来运行的
   k8s.gcr.io/pause 3.1 da86e6ba6ca1 17 mon 742 kB

emptyDir
     临时存储目录 pod删除 存储卷也随即会被删除

hostPath 主机目录
     pod所在主机上的目录

搭建NFS网络存储

nfs搭建
   yum install nfs-utils
   mkdir -pv /data/volumes
   vi /etc/exports
     /data/volumes 192.168.11.0/16(rw,no_root_squash)
   systemctl start nfs
  1.确保k8s集群中的所有节点都能驱动nfs 
    yum install nfs-utils
  2.[root@node2 ~]# mount -t nfs 192.168.11.157:/data/volumnes/ /mnt
mount.nfs: access denied by server while mounting 192.168.11.157:/data/volumnes/
  3.在nfs服务器查看/var/log/messages查看 volumnes单词拼写错误

  [root@node2 ~]# mount -t nfs 192.168.11.157:/data/volumes  /mnt

  [root@localhost ~]# vi /etc/exports
   /data/volumes/ 192.168.11.0/16(insecure,rw,async,no_root_squash)

  [root@localhost ~]# exportfs -r
  exportfs: Invalid prefix `24*' for 192.168.11.0/24*
  [root@localhost ~]# showmount -e
  Export list for localhost.localdomain:
  /data/volumes 192.168.11.0/16
nfs搭建
apiVersion: v1
kind: Pod
metadata:
  name: pod-vol-hostpath
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html/
  volumes:
  - name: html
    hostPath:
      path: /data/pod/volume1
      type: DirectoryOrCreate
hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-vol-nfs
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html/
  volumes:
  - name: html
    nfs:
      path: /data/volumes
      server: 192.168.11.157
nfs.yaml

  nfs远程文件存储并没有一个“存储设备”需要挂载在宿主机上 所以不需要attach阶段

  直接将远端 NFS 服务器的目录(比如:“/”目录)挂载到Volume的宿主机目录上即可 

  mount -t nfs <NFS服务器地址>:/ /var/lib/kubelet/pods/<Pod的ID>/volumes/kubernetes.io~<Volume类型>/<Volume名字> 

  通过这个挂载操作,Volume的宿主机目录就成为了一个远程 NFS 目录的挂载点,后面你在这个目录里写入的所有文件,都会被保存在远程 NFS 服务器上。

  所以,我们也就完成了对这个 Volume 宿主机目录的“持久化”

pv和pvc的使用

       存储工程师把分布式存储系统上的总空间划分成一个一个小的存储块

       k8s管理员根据存储块创建与之一一对应的pv资源

       pv属于集群级别资源  不属于任何名称空间 定义的时候不能指定名称空间

       用户在创建pod的时候同时创建与pv一一对应的pvc资源

       创建Pod的时候,系统里并没有合适的 PV 跟它定义的 PVC 绑定 也就是说此时容器想要使用的Volume不存在。这时候,Pod的启动就会报错

[root@localhost volumes]# mkdir v{1,2,3,4,5}
[root@localhost volumes]# ls
index.html  v1  v2  v3  v4  v5
[root@localhost volumes]# vi /etc/exports

/data/volumes/v1 192.168.11.0/16(insecure,rw,async,no_root_squash)
/data/volumes/v2 192.168.11.0/16(insecure,rw,async,no_root_squash)
/data/volumes/v3 192.168.11.0/16(insecure,rw,async,no_root_squash)
/data/volumes/v4 192.168.11.0/16(insecure,rw,async,no_root_squash)
/data/volumes/v5 192.168.11.0/16(insecure,rw,async,no_root_squash)


[root@localhost volumes]# exportfs -r
[root@localhost volumes]# showmount -e
Export list for localhost.localdomain:
/data/volumes/v5 192.168.11.0/16
/data/volumes/v4 192.168.11.0/16
/data/volumes/v3 192.168.11.0/16
/data/volumes/v2 192.168.11.0/16
/data/volumes/v1 192.168.11.0/16
创建小的存储块
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv001
  labels:
    name: pv001
spec:
  nfs:
   path: /data/volumes/v1
   server: 192.168.11.158
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv002
  labels:
    name: pv002
spec:
  nfs:
   path: /data/volumes/v2
   server: 192.168.11.158
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 5Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv003
  labels:
    name: pv003
spec:
  nfs:
   path: /data/volumes/v3
   server: 192.168.11.158
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv004
  labels:
    name: pv004
spec:
  nfs:
   path: /data/volumes/v4
   server: 192.168.11.158
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv005
  labels:
    name: pv005
spec:
  nfs:
   path: /data/volumes/v5
   server: 192.168.11.158
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 2Gi
创建pv资源
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
  namespace: default
spec:
  accessModes: ["ReadWriteMany"]
  resources:
    requests:
      storage: 4Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-vol-pvc
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: html
    persistentVolumeClaim:
      claimName: mypvc
创建pod和pvc资源
[root@k8s-master ~]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM           STORAGECLASS   REASON    AGE
pv001     2Gi        RWO,RWX        Retain           Available                                            8m
pv002     5Gi        RWO,RWX        Retain           Bound       default/mypvc                            8m
pv003     2Gi        RWO,RWX        Retain           Available                                            8m
pv004     2Gi        RWO,RWX        Retain           Available                                            8m
pv005     2Gi        RWO,RWX        Retain           Available                                            8m


[root@k8s-master ~]# kubectl get pvc
NAME      STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc     Bound     pv002     5Gi        RWO,RWX                       8m


[root@k8s-master ~]# kubectl get pods
NAME                             READY     STATUS    RESTARTS   AGE
myapp-deploy-67f6f6b4dc-2986w    1/1       Running   0          4h
myapp-deploy-67f6f6b4dc-czvq4    1/1       Running   0          4h
myapp-deploy-67f6f6b4dc-tpggj    1/1       Running   0          10d
pod-vol-pvc                      1/1       Running   0          9m
tomcat-deploy-588c79d48d-mdgml   1/1       Running   0          10d
tomcat-deploy-588c79d48d-mvttj   1/1       Running   0          4h
tomcat-deploy-588c79d48d-w2mxb   1/1       Running   0          10d


在创建pvc的时候如果后端没有合适的pv 那么挂载此pvc的pod将会一致处于等待状态直到pvc匹配到一个符合条件的pv
演示结果

pv和pvc的机制

pv和pvc绑定要求
     1.PV和PVC的spec字段。比如PV的存储(storage)大小
     2.PV和PVC的storageClassName字段必须一样

     3. PVC 可以理解为持久化存储的“接口”,它提供了对某种持久化存储的描述,但不提供具体的实现

     4. 持久化存储的实现部分则由PV负责完成

     5.PV与PVC进行“绑定”,其实就是将这个PV对象的名字,填在了 PVC 对象的 spec.volumeName 字段上

     pv对象转换成持久化volume的原理

          所谓容器的 Volume,其实就是将一个宿主机上的目录,跟一个容器里的目录绑定挂载在了一起

持久化宿主机目录

     远程存储服务,比如:远程文件存储(比如,NFS、GlusterFS)、远程块存储(比如,公有云提供的远程磁盘)

      “持久化”宿主机目录的过程,我们可以形象地称为“两阶段处理”

       先把远程存储设备附加到指定节点上  然后在节点上格式化存储设备再挂载到节点上的具体目录下  这样才能通过节点目录访问远程存储设备

     Attach阶段
         为虚拟机挂载远程磁盘的操作
         当一个Pod调度到一个节点上之后,kubelet就要负责为这个Pod创建它的 Volume 目录。默认情况下,kubelet为Volume创建的目录是一个宿主机上的路径如
         /var/lib/kubelet/pods/volumes/kubernetes.io~/
        这个目录是宿主机后面用来和远程存储服务mount的关联目录

       Kubernetes 提供的可用参数是 nodeName,即宿主机的名字

    Mount阶段
       将磁盘设备格式化并挂载到Volume宿主机目录的操作
       把格式化的磁盘mount到/var/lib/kubelet/pods/volumes/kubernetes.io~/

       Kubernetes 提供的可用参数是 dir,即 Volume 的宿主机目录

    经过了“两阶段处理” 我们就得到了一个“持久化”的 Volume 宿主机目录 但是还没有关联到docker容器

   接下来 kubelet 只要把这个 Volume目录通过 CRI 里的 Mounts 参数,传递给 Docker 然后就可以为 Pod 里的容器挂载这个“持久化”的 Volume 

   docker run -v /var/lib/kubelet/pods/<Pod的ID>/volumes/kubernetes.io~<Volume类型>/<Volume名字>:/<容器内的目标目录> 我的镜像 

   上面是Kubernetes 处理 PV 的具体原理

StorageClass自动创建pv 

      Kubernetes只会将StorageClass相同的PVC和PV 绑定起来

      自动创建PV的机制Dynamic Provisioning
     人工管理PV的方式就叫作Static Provisioning
     StorageClass对象就是创建PV的模板

 StorageClass对象会定义如下两个部分内容
    第一,PV的属性。比如,存储类型、Volume 的大小等等
    第二,创建这种PV需要用到的存储插件。比如Ceph 等等

   有了这样两个信息之后,Kubernetes 就能够根据用户提交的 PVC,找到一个对应的 StorageClass 了

   Kubernetes 就会调用该 StorageClass 声明的存储插件 创建出需要的 PV

   有了 Dynamic Provisioning 机制 运维人员只需要在 Kubernetes 集群里创建出数量有限的 StorageClass 对象就可以了

   当开发人员提交了包含 StorageClass 字段的 PVC 之后,Kubernetes 就会根据这个 StorageClass 创建出对应的 PV

   默认情况下运维人员对每个开发人员创建的pvc都要手动创建一个对应的pvc与其进行绑定

猜你喜欢

转载自www.cnblogs.com/yxh168/p/11031003.html