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. PV描述的是持久化存储卷 这个API对象主要定义的是一个持久化存储在宿主机上的目录,如一个NFS的挂载目录

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

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

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

       当PV和PVC成功绑定后 Pod就能像使用hostPath等常规类型的Volume一样 在YAML文件中使用PVC

     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一般包含Name,后端使用存储插件类型,存储插件需要使用到的参数等信息 定义好之后相当于定义了一块巨大的存储磁盘

    当pvc中定义的storageClassName和StorageClass的Name相同的时候那么StorageClass会自动从巨大的存储磁盘创建一个指定storage大小的pv,创建的pv和pvc进行绑定

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

    k8s根据用户提交的PVC中指定的storageClassName的属性值找到对应的StorageClass.然后调用该StorageClass声明的存储插件创建出需要的PV

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

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

   在没有StorageClass的情况下运维人员对开发人员定义的每一个pvc都要手动创建一个对应的pv与其进行绑定 这样就会大大的增加创建pv的工作量

 

posted @ 2020-01-15 10:08  不懂123  阅读(22065)  评论(0编辑  收藏  举报