当前位置: 首页>编程语言>正文

多容器公用目录 多容器公用目录有哪些

pod容器共享Volume
 同一个pod中的多个容器能够共享Pod级别的存储卷Volume。即定义一个卷,然后将该卷挂在为多个容器的内部目录。
 如下pod实例,pod-volume.yml内容如下:
 apiVersion: v1
 kind: Pod
 metadata:
  name: volume-pod
 spec:
 s:
  - name: tomcat
   image: tomcat
   ports:
   -Port: 8080
   volumeMounts:
   - name: app-logs #使用名称为app-logs的卷
    mountPath: /usr/local/tomcat/logs #将卷挂载到该路径,这个路径是容器内的绝对路径
  - name: busybox
   image: busybox
   command: ["sh", "-c", "tail -f /logs/catalinz*.log"]
   volumeMounts:
   - name: app-logs
    mountPath: /logs
  volumse: #定义pod中的公共volume
  - name: app-logs #volume名称为app-logs
   emptyDir: {} #
 说明:pod中定义了名称为app-logs的卷,然后应用到多个pod中。emptyDir:k8s不显式声明宿主机目录的 Volume。所以,Kubernetes 也会在宿主机上创建一个临时目录,这个目录将来就会被绑定挂载到容器所声明的 Volume 目录上。此时并不关心卷定义在宿主机的哪个目录,主要是通过该目录,实现Pod中多个容器对卷的共享。
Kubernetes 也提供了显式的 Volume 定义,它叫作 hostPath。比如下面的这个 YAML 文件:
  ...   
     volumes:
       - name: nginx-vol
         hostPath: 
           path:  " /var/data"Kubernetes 中,有几种特殊的 Volume:
 存在的意义不是为了存放容器里的数据,也不是用来进行容器和宿主机之间的数据交换。这些特殊 Volume 的作用,是为容器提供预先定义好的数据,现在支持四种:
 Secret; pod中创建保密信息
 ConfigMap; 获取一般配置
 Downward API;让 Pod 里的容器能够直接获取到这个 Pod API 对象本身的信息。
 ServiceAccountToken。
  pv pvc storageClass
 PVC 是 Pod 所希望使用的持久化存储的属性。
 PV 是持久化存储数据卷。定义的是一个持久化存储在宿主机上的目录,比如一个 NFS 的挂载目录。pvc定义
 apiVersion: v1
 kind: PersistentVolumeClaim
 metadata:
   name: nfs
 spec:
   accessModes:
     - ReadWriteMany
   storageClassName: manual
   resources:
     requests:
       storage: 1Gi
 pv定义:
 apiVersion: v1
 kind: PersistentVolume
 metadata:
   name: nfs
 spec:
   storageClassName: manual
   capacity:
     storage: 1Gi
   accessModes:
     - ReadWriteMany
   nfs:
     server: 10.244.1.4
     path: "/"
 pod中使用pvc:
 apiVersion: v1
 kind: Pod
 metadata:
   labels:
     role: web-frontend
 spec:
  s:
   - name: web
     image: nginx
     ports:
       - name: web
        Port: 80
     volumeMounts:
         - name: nfs
           mountPath: "/usr/share/nginx/html"
   volumes:
   - name: nfs
     persistentVolumeClaim:
       claimName: nfs #pvc名称
 Pod创建之后,kubelet 就会把这个 PVC 所对应的 PV,也就是一个 NFS 类型的 Volume,挂载在这个 Pod 容器内的目录上。pv和pvc的设计思想:
 pvc:持久化存储的描述,类似“接口”
 pv:持久化存储的实现部分,类似”实现类“
 好处:作为开发者,我们只需要跟 PVC 这个“接口”打交道,而不必关心具体的实现是 NFS 还是 Ceph。PVC 要真正被容器使用起来,就必须先和某个符合条件的 PV 进行绑定。
 这里要检查的条件,包括两部分:
 第一个条件,当然是 PV 和 PVC 的 spec 字段。比如,PV 的存储(storage)大小,就必须满足 PVC 的要求。
 第二个条件,则是 PV 和 PVC 的 storageClassName 字段必须一样。这个机制我会在本篇文章的最后一部分专门介绍。如果系统里并没有合适的 PV 跟它定义的 PVC 绑定,那会发生什么?
 Pod 的启动就会报错。
 然后如果创建了符合条件的PV,Kubernetes 能够再次完成 PVC 和 PV 的绑定操作,从而启动 Pod。实现原理:k8s存在一个Volume Controller,查看当前每一个PVC,是不是已经处于 Bound(已绑定)状态。如果不是,那它就会遍历所有的、可用的 PV,并尝试将其与这个“单身”的 PVC 进行绑定。
 PV 对象,又是如何变成容器里的一个持久化存储的呢?
 容器的 Volume,其实就是将一个宿主机上的目录,跟一个容器里的目录绑定挂载在了一起。
 “持久化 Volume”,指的就是这个宿主机上的目录,具备“持久性”,既不会因为容器的删除而被清理掉,也不会跟当前的宿主机绑定。这样,当容器被重启或者在其他节点上重建出来之后,它仍然能够通过挂载这个 Volume,访问到这些内容。
 所以 hostPath 和 emptyDir 类型的 Volume不是持久化的。
 持久化 Volume 的实现,往往依赖于一个远程存储服务,比如:远程文件存储(比如,NFS、GlusterFS)、远程块存储(比如,公有云提供的远程磁盘)等等。以远程块存储为实例看pv实现原理
 1)kubelet为Pod在宿主机上创建Volume目录,路径:
 /var/lib/kubelet/pods/<Pod的ID>/volumes/kubernetes.io~<Volume类型>/<Volume名字>
 2)将 远程块存储 挂载到pod所在的宿主机
 以Google Cloud 的 Persistent Disk为例,调用如下api:
 $ gcloud compute instances attach-disk <虚拟机名字> --disk <远程磁盘名字>
 3)格式化这个磁盘设备,然后将它挂载到宿主机指定的挂载点上,这个挂载点就是步骤一中volume的宿主机目录
 4)kubelet 只要把这个 Volume 目录通过 CRI 里的 Mounts 参数,传递给 Docker;类似执行如下指令:
 $ docker run -v /var/lib/kubelet/pods/<Pod的ID>/volumes/kubernetes.io~<Volume类型>/<Volume名字>:/<容器内的目标目录> 我的镜像 ... StorageClass
 一个大规模的 Kubernetes 集群里很可能有成千上万个PVC,这就意味着运维人员必须得事先创建出成千上万个 PV。浪费资源,且难以维护。Kubernetes为我们提供了一套可以自动创建PV的机制,即:Dynamic Provisioning,核心,在于一个名叫 StorageClass 的 API 对象。
storageClass的对象定义包含两部分:
 第一,PV 的属性。比如,存储类型、Volume 的大小等等。
 第二,创建这种 PV 需要用到的存储插件。比如,Ceph 等等。
 Kubernetes 就能够根据用户提交的 PVC,找到一个对应的 StorageClass 了。然后,Kubernetes 就会调用该 StorageClass 声明的存储插件,创建出需要的 PV。实例如下:sc.yaml
 apiVersion: storage.k8s.io/v1
 kind: StorageClass
 metadata:
   name: block-service
 provisioner: kubernetes.io/gce-pd
 parameters:
   type: pd-ssd
 provisioner 字段的值是:kubernetes.io/gce-pd,这正是 Kubernetes 内置的 GCE PD 存储插件的名字。
 parameters 字段,就是 PV 的参数。比如:上面例子里的 type=pd-ssd,指的是这个 PV 的类型是“SSD 格式的 GCE 远程磁盘”。创建StorageClass
 $ kubectl create -f sc.yamlPVC 里指定要使用的 StorageClass 名字,pvc定义如下:
 apiVersion: v1
 kind: PersistentVolumeClaim
 metadata:
   name: claim1
 spec:
   accessModes:
     - ReadWriteOnce
   storageClassName: block-service
   resources:
     requests:
       storage: 30Gi
 Google Cloud 为例。当我们通过 kubectl create 创建上述 PVC 对象之后,Kubernetes 就会调用 Google Cloud 的 API,创建出一块 SSD 格式的 Persistent Disk。然后,再使用这个 Persistent Disk 的信息,自动创建出一个对应的 PV 对象。有了 Dynamic Provisioning 机制,运维人员只需要在 Kubernetes 集群里创建出数量有限的 StorageClass 对象就可以了。当开发人员提交了包含 StorageClass 字段的 PVC 之后,Kubernetes 就会根据这个 StorageClass 创建出对应的 PV。
pod pv pvc storageClass之间的关系如下图:
在这个体系中:
 PVC 描述的,是 Pod 想要使用的持久化存储的属性,比如存储的大小、读写权限等。
 PV 描述的,则是一个具体的 Volume 的属性,比如 Volume 的类型、挂载目录、远程存储服务器地址等。
 而 StorageClass 的作用,则是充当 PV 的模板。并且,只有同属于一个 StorageClass 的 PV 和 PVC,才可以绑定在一起。还有是指定 PV 的 Provisioner(存储插件)。这时候,如果你的存储插件支持 Dynamic Provisioning 的话,Kubernetes 就可以自动为你创建 PV 了。 本地持久化存储
 好处:Volume 直接使用的是本地磁盘,尤其是 SSD 盘,它的读写性能相比于大多数远程存储来说,要好得多。
 Local Persistent Volume 并不适用于所有应用。事实上,它的适用范围非常固定,比如:高优先级的系统应用,需要在多个不同节点上存储数据,并且对 I/O 较为敏感。典型的应用包括:分布式数据存储比如 MongoDB、Cassandra 等,分布式文件系统比如 GlusterFS、Ceph 等,以及需要在本地磁盘上进行大量数据缓存的分布式应用。本地模拟过程:
 1)在名叫 node-1 的宿主机上创建一个挂载点,比如 /mnt/disks;然后,用几个 RAM Disk 来模拟本地磁盘
 # 在node-1上执行
 $ mkdir /mnt/disks
 $ for vol in vol1 vol2 vol3; do
     mkdir /mnt/disks/$vol
     mount -t tmpfs $vol /mnt/disks/$vol
 done2)为这些本地磁盘定义对应的 PV 
 apiVersion: v1
 kind: PersistentVolume
 metadata:
   name: example-pv
 spec:
   capacity:
     storage: 5Gi
   volumeMode: Filesystem
   accessModes:
   - ReadWriteOnce
   persistentVolumeReclaimPolicy: Delete
   storageClassName: local-storage
   local:
     path: /mnt/disks/vol1
   nodeAffinity:
     required:
       nodeSelectorTerms:
       - matchExpressions:
         - key: kubernetes.io/hostname
           operator: In
           values:
           - node-1
 local 字段,指定了它是一个 Local Persistent Volume;
 而 path 字段,指定的正是这个 PV 对应的本地磁盘的路径,即:/mnt/disks/vol1;Pod要想使用这个PV,那它就必须运行在 node-1 上。所以,在这个 PV 的定义里,需要有一个 nodeAffinity 字段指定 node-1 这个节点的名字。
 调度器在调度 Pod 的时候,就能够知道一个 PV 与节点的对应关系,从而做出正确的选择3)创建pv
 $ kubectl create -f local-pv.yaml 
 persistentvolume/example-pv created$ kubectl get pv
 NAME         CAPACITY   ACCESS MODES   RECLAIM POLICY  STATUS      CLAIM             STORAGECLASS    REASON    AGE
 example-pv   5Gi        RWO            Delete           Available                     local-storage             16s4)创建一个 StorageClass 来描述这个 PV
 kind: StorageClass
 apiVersion: storage.k8s.io/v1
 metadata:
   name: local-storage
 provisioner: kubernetes.io/no-provisioner
 volumeBindingMode: WaitForFirstConsumer说明:
 provisioner 字段,我们指定的是 no-provisioner。这是因为 Local Persistent Volume 目前尚不支持 Dynamic Provisioning,
 StorageClass 还定义了一个 volumeBindingMode=WaitForFirstConsumer 的属性。它是 Local Persistent Volume 里一个非常重要的特性,即:延迟绑定。因为按照一般流程: PV 和 PVC 的 YAML 文件之后,Kubernetes 就会根据它们俩的属性,以及它们指定的 StorageClass 来进行绑定。只有绑定成功后,Pod 才能通过声明这个 PVC 来使用对应的 PV。
 但 Local Persistent Volume 的话,就会发现,这个流程根本行不通,实例如下:
 pod只能运行在node2上,pod使用pvc名称是pvc-1。
 第一个pv名称是pv-1,在node1上;第二个pv名称是pv-2,在node2上。且pv-1和pv-2都符合pvc-1的要求;
 如果提前绑定,则pvc-1可以和pv-1绑定;
 那使用pvc-1的pod只能裕兴在node1上了。
 最终不符合我们要求。解决方案就是延迟绑定:即被声明了WaitForFirstConsumer的pv等到实际需要的时候再和pvc绑定,按照上面的实例即:pod被创建到了node2上,此时该pod需要使用pvc-1,pvc-1再和node2上的pv-2绑定.
k8s支持编写自己的存储插件
 FlexVolume 和 CSI

https://www.xamrdz.com/lan/5em1924582.html

相关文章: