• Kubernetes入门 十四、存储管理


    临时存储

    Kubernetes 支持很多类型的卷。 Pod可以同时使用任意数目的卷类型。

    临时卷类型的生命周期与 Pod 相同,但持久卷可以比 Pod 的存活期长。

    但是Kubernetes 不会销毁 持久卷

    hostPath

    hostPath 允许挂载 Node 上的文件系统到 Pod 里面去。如果 Pod 需要使用 Node 上的文件,可以使用 hostPath。

    即使 Pod 被删除后重启,也可以重新加载到保存在 Node 主机上的该目录,该目录下的文件不会丢失。

    注意:hostPath 之所以被归为临时存储,是因为实际开发中,我们一般都是通过 Deployment 部署 Pod 的,一旦 Pod 被 Kubernetes 杀死或重启拉起等,并不一定会部署到原来的 Node 节点中。

    除了必需的 path 属性之外,用户可以选择性地为 hostPath 卷指定 type

    取值行为
    空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。
    DirectoryOrCreate如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。
    Directory在给定路径上必须存在的目录。
    FileOrCreate如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。
    File在给定路径上必须存在的文件。
    Socket在给定路径上必须存在的 UNIX 套接字。
    CharDevice在给定路径上必须存在的字符设备。
    BlockDevice在给定路径上必须存在的块设备。

    hostPath 的典型应用就是时间同步:通常而言,Node 节点的时间是同步的(云厂商提供的云服务器的时间都是同步的),但是,Pod 中的容器的时间就不一定了,有 UTC 、CST 等;同一个 Pod ,如果部署到中国,就必须设置为 CST 了。

    创建文件hostPath-pod.yaml,内容如下:

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-host-path
      namespace: default
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx    
        image: nginx:1.20.2
        resources:
          limits:
            cpu: 200m
            memory: 500Mi
          requests:
            cpu: 100m
            memory: 200Mi
        ports:
        - containerPort:  80
          name:  http
        volumeMounts:
        - name: localtime
          mountPath: /etc/localtime
      volumes:
        - name: localtime
          hostPath: # hostPath
            path: /usr/share/zoneinfo/Asia/Shanghai
      restartPolicy: Always
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    上面示例就是把node上的目录的时区文件挂载到容器中。

    EmptyDir

    emptyDir 主要用于一个 Pod 中不同的 Container 共享数据使用的,由于只是在 Pod 内部使用,因此与其他 volume 比较大的区别是,当 Pod 如果被删除了,那么 emptyDir 也会被删除。

    存储介质可以是任意类型,如 SSD、磁盘或网络存储。可以将 emptyDir.medium 设置为 Memory 让 k8s 使用 tmpfs(内存支持文件系统),速度比较快,但是重启 tmpfs 节点时,数据会被清除,且设置的大小会计入到 Container 的内存限制中。

    emptyDir 的一些用途:

      • 临时空间,例如用于某些应用程序运行时所需的临时目录,且无须永久保留。
      • 一个容器需要从另一个容器中获取数据的目录(多容器共享目录)。

    emptyDir 卷存储在该节点的磁盘或内存中,如果设置 emptyDir.medium = Memory ,那么就告诉 Kubernetes 将数据保存在内存中,并且在 Pod 被重启或删除前,所写入的所有文件都会计入容器的内存消耗,受到容器内存限制约束。

    在这里插入图片描述

    示例:

    创建两个pod,挂载同一个emptyDir。

    第一个:

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-pd1
    spec:
      containers:
      - image: nginx
        name: nginx-emptydir
        volumeMounts:
        - mountPath: /cache
          name: cache-volume
      volumes:
      - name: cache-volume
        emptyDir: {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    第二个:

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-pd2
    spec:
      containers:
      - image: nginx
        name: nginx-emptydir
        volumeMounts:
        - mountPath: /cache
          name: cache-volume
      volumes:
      - name: cache-volume
        emptyDir: {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    这样如果在一个容器中修改了文件夹,另一个容器也会跟着修改。具体效果不再演示。

    NFS 挂载

    NFS是持久化数据卷的方式之一。

    NFS 的简介:网络文件系统,英文Network File System(NFS),是由 SUN公司研制的UNIX表示层协议(presentation layer protocol),能使使用者访问网络上别处的文件就像在使用自己的计算机一样。

    NFS 卷能将 NFS挂载到 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

    在这里插入图片描述

    注意:实际开发中,不建议使用 NFS 作为 Kubernetes 集群持久化的驱动。

    安装NFS

    • 本次以 Master (192.168.65.100)节点作为 NFS 服务端:
    yum install -y nfs-utils
    
    • 1
    • 在 Master(192.168.65.100)节点创建 /etc/exports 文件:
    # * 表示暴露权限给所有主机;* 也可以使用 192.168.0.0/16 代替,表示暴露给所有主机
    echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
    
    • 1
    • 2
    • 在 Master(192.168.65.100)节点创建 /nfs/data/ (共享目录)目录,并设置权限:
    mkdir -pv /nfs/data/
    chmod 777 -R /nfs/data/
    
    • 1
    • 2
    • 在 Master(192.168.65.100)节点启动 NFS :
    systemctl enable rpcbind
    systemctl enable nfs-server
    systemctl start rpcbind
    systemctl start nfs-server
    
    • 1
    • 2
    • 3
    • 4
    • 在 Master(192.168.65.100)节点加载配置:
    exportfs -r
    
    • 1
    • 在 Master(192.168.65.100)节点检查配置是否生效:
    exportfs
    # /nfs/data/
    
    • 1
    • 2
    • 在 Node(192.168.65.101、192.168.65.102)节点安装 nfs-utils :
    # 服务器端防火墙开放111、662、875、892、2049的 tcp / udp 允许,否则远端客户无法连接。
    yum install -y nfs-utils
    
    • 1
    • 2
    • 在 Node(192.168.65.101、192.168.65.102)节点,执行以下命令检查 nfs 服务器端是否有设置共享目录:
    # showmount -e $(nfs服务器的IP)
    showmount -e 192.168.65.100
    
    • 1
    • 2
    • 在 Node(192.168.65.101、192.168.65.102)节点,执行以下命令挂载 nfs 服务器上的共享目录到本机路径 /root/nd
    mkdir /nd
    
    • 1
    # mount -t nfs $(nfs服务器的IP):/root/nfs_root /root/nfsmount
    mount -t nfs 192.168.65.100:/nfs/data /nd
    
    • 1
    • 2
    • 在 Node (192.168.65.101)节点写入一个测试文件:
    echo "hello nfs server" > /nd/test.txt
    
    • 1
    • 在 Master(192.168.65.100)节点验证文件是否写入成功:
    cat /nfs/data/test.txt
    
    • 1

    配置文件

    使用时,配置如下:

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      namespace: default
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.20.2
        resources:
          limits:
            cpu: 200m
            memory: 500Mi
          requests:
            cpu: 100m
            memory: 200Mi
        ports:
        - containerPort: 80
          name:  http
        volumeMounts:
        - name: localtime
          mountPath: /etc/localtime
        - name: html  
          mountPath: /usr/share/nginx/html/ # / 一定是文件夹
      volumes:
        - name: localtime
          hostPath:
            path: /usr/share/zoneinfo/Asia/Shanghai
        - name: html 
          nfs: # 使用 nfs 存储驱动
            path: /nfs/data  # nfs 共享的目录
            server:  192.168.65.100  # nfs 服务端的 IP 地址或 hostname 
      restartPolicy: Always
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    PV和PVC

    概述

    前面我们已经学习了使用 NFS 提供存储,此时就要求用户会搭建 NFS 系统,并且会在 yaml 配置 NFS,这就带来的一些问题:

    • ① 开发人员对 Pod 很熟悉,非常清楚 Pod 中的容器那些位置适合挂载出去。但是,由于 Kubernetes 支持的存储系统非常之多,开发人员并不清楚底层的存储系统,而且要求开发人员全部熟悉,不太可能(术业有专攻,运维人员比较熟悉存储系统)。

    • ② 在 yaml 中配置存储系统,就意味着将存储系统的配置信息暴露,非常不安全(容易造成泄露)。

    为了能够屏蔽底层存储实现的细节,方便用户使用,Kubernetes 引入了 PV 和 PVC 两种资源对象。

    持久卷(PersistentVolume,PV) 是集群中的一块存储,可以由管理员事先制备, 或者使用存储类(Storage Class)来动态制备。 持久卷是集群资源,就像节点也是集群资源一样。PV 持久卷和普通的 Volume 一样, 也是使用卷插件来实现的,只是它们拥有独立于任何使用 PV 的 Pod 的生命周期。 此 API 对象中记述了存储的实现细节,无论其背后是 NFS、iSCSI 还是特定于云平台的存储系统。

    持久卷声明(PersistentVolumeClaim,PVC) 表达的是用户对存储的请求。概念上与 Pod 类似。 Pod 会耗用节点资源,而 PVC 申领会耗用 PV 资源。Pod 可以请求特定数量的资源(CPU 和内存);同样 PVC 申领也可以请求特定的大小和访问模式 (例如,可以要求 PV 卷能够以 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany 模式之一来挂载,参见访问模式)。

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    PV 的缺点:

    ① 需要运维事先准备好 PV 池。

    ② 资源浪费:没有办法预估合适的 PV,假设运维向 k8s 申请了 20m 、50m、10G 的 PV,而开发人员申请 2G 的 PVC ,那么就会匹配到 10G 的PV ,这样会造成 8G 的空间浪费。

    也有人称 PV 为静态供应。

    PV 的回收策略

    1. 保留(Retain)

    回收策略 Retain 使得用户可以手动回收资源。当 PersistentVolumeClaim 对象被删除时,PersistentVolume 卷仍然存在,对应的数据卷被视为"已释放(released)"。 由于卷上仍然存在这前一声明人的数据,该卷还不能用于其他申领。 管理员可以通过下面的步骤来手动回收该卷:

    1. 删除 PersistentVolume 对象。与之相关的、位于外部基础设施中的存储资产 (例如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)在 PV 删除之后仍然存在。
    2. 根据情况,手动清除所关联的存储资产上的数据。
    3. 手动删除所关联的存储资产。

    如果你希望重用该存储资产,可以基于存储资产的定义创建新的 PersistentVolume 卷对象。

    1. 删除(Delete)

    对于支持 Delete 回收策略的卷插件,删除动作会将 PersistentVolume 对象从 Kubernetes 中移除,同时也会从外部基础设施(如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)中移除所关联的存储资产。 动态制备的卷会继承其 StorageClass 中设置的回收策略, 该策略默认为 Delete。管理员需要根据用户的期望来配置 StorageClass; 否则 PV 卷被创建之后必须要被编辑或者修补。

    1. 回收(Recycle)

    警告: 回收策略 Recycle 已被废弃。取而代之的建议方案是使用动态制备。

    如果下层的卷插件支持,回收策略 Recycle 会在卷上执行一些基本的擦除 (rm -rf /thevolume/*)操作,之后允许该卷用于新的 PVC 申领。

    PV 的访问模式

    访问模式(accessModes):用来描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:

      • ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载。
      • ReadOnlyMany(ROX):只读权限,可以被多个节点挂载。
      • ReadWriteMany(RWX):读写权限,可以被多个节点挂载。

    PV 的状态

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

      • Available(可用):表示可用状态,还未被任何 PVC 绑定。
      • Bound(已绑定):表示 PV 已经被 PVC 绑定。
      • Released(已释放):表示 PVC 被删除,但是资源还没有被集群重新释放。
      • Failed(失败):表示该 PV 的自动回收失败。

    使用PV和PVC

    1. 创建 PV (一般是运维人员操作)

    先创建文件夹:

    mkdir -pv /nfs/data/10m
    mkdir -pv /nfs/data/20m
    mkdir -pv /nfs/data/500m
    mkdir -pv /nfs/data/1Gi
    
    • 1
    • 2
    • 3
    • 4

    创建PV的资源文件 k8s-pv.yaml,内容如下:

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: nfs-pv-10m
    spec:
      storageClassName: nfs-storage # 创建pv的存储类名,用于分组,要与pvc的相同
      capacity:  # 容量配置
        storage: 10m  # 容量
      accessModes:  #访问模式
        - ReadWriteOnce
      persistentVolumeReclaimPolicy: Retain  #回收策略
      nfs: # 使用 nfs 存储驱动
        path: /nfs/data/10m # nfs 共享的目录,mkdir -pv /nfs/data/10m
        server: 192.168.65.100 # nfs 服务端的 IP 地址或 hostname
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: nfs-pv-20m
    spec:
      storageClassName: nfs-storage # 用于分组
      capacity:
        storage: 20m
      accessModes:
        - ReadWriteOnce
      nfs: # 使用 nfs 存储驱动
        path: /nfs/data/20m # nfs 共享的目录,mkdir -pv /nfs/data/20m
        server: 192.168.65.100 # nfs 服务端的 IP 地址或 hostname
    --- 
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: nfs-pv-500m
    spec:
      storageClassName: nfs-storage # 用于分组
      capacity:
        storage: 500m
      accessModes:
        - ReadWriteOnce
      nfs: # 使用 nfs 存储驱动
        path: /nfs/data/500m # nfs 共享的目录,mkdir -pv /nfs/data/500m
        server: 192.168.65.100 # nfs 服务端的 IP 地址或 hostname
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: nfs-pv-1g
    spec:
      storageClassName: nfs-storage # 用于分组
      capacity:
        storage: 1Gi
      accessModes:
        - ReadWriteOnce
      nfs: # 使用 nfs 存储驱动
        path: /nfs/data/1Gi # nfs 共享的目录,mkdir -pv /nfs/data/1Gi
        server: 192.168.65.100 # nfs 服务端的 IP 地址或 hostname
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    执行文件:

    kubectl apply -f k8s-pv.yaml
    
    • 1
    1. 创建PVC (一般是开发人员)

    一般PVC是随着Pod一起创建,编辑资源文件k8s-pvc.yaml:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: nginx-pvc-500m  # pvc的名字
      namespace: default
      labels:
        app: nginx-pvc-500m  # pvc的label
    spec:
      storageClassName: nfs-storage  # 与pv的一致
      accessModes:  # 访问模式,与pv的一致
      - ReadWriteOnce
      resources:  # 资源定义
        requests:
          storage: 500m  # 最大存储500m,资源可以小于pv,但是不能大于pv,否则匹配不上
    ---
    apiVersion: v1
    kind: Pod  # 创建pod
    metadata:
      name: nginx
      namespace: default
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.20.2
        resources:
          limits:
            cpu: 200m
            memory: 500Mi
          requests:
            cpu: 100m
            memory: 200Mi
        ports:
        - containerPort:  80
          name:  http
        volumeMounts:  # 定义挂载数据卷
        - name: html  # 要挂载的数据卷的名字
          mountPath: /usr/share/nginx/html/   # 挂载大屏容器的目录
      volumes:  # 定义数据卷
        - name: html  # 数据卷的名字
          persistentVolumeClaim:  # 这个使用pvc作为存储卷
            claimName:  nginx-pvc-500m  # 要关联的pvc的名字,与定义pvc的一 致
            readOnly: false  
      restartPolicy: Always
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    执行文件:

    kubectl apply -f k8s-pvc.yaml
    
    • 1

    成功部署之后,这样就完成了

    生命周期

    在这里插入图片描述

    PVC 和 PV 是一一对应的,PV 和 PVC 之间的相互作用遵循如下的生命周期:

    • ① 资源供应:管理员手动创建底层存储和 PV。

    • ② 资源绑定:

      • 用户创建 PVC ,Kubernetes 负责根据 PVC 声明去寻找 PV ,并绑定在用户定义好 PVC 之后,系统将根据 PVC 对存储资源的请求在以存在的 PV 中选择一个满足条件的。
        • 一旦找到,就将该 PV 和用户定义的 PVC 进行绑定,用户的应用就可以使用这个 PVC 了。
        • 如果找不到,PVC 就会无限期的处于 Pending 状态,直到系统管理员创建一个符合其要求的 PV 。
      • PV 一旦绑定到某个 PVC 上,就会被这个 PVC 独占,不能再和其他的 PVC 进行绑定了。
    • ③ 资源使用:用户可以在 Pod 中像 Volume 一样使用 PVC ,Pod 使用 Volume 的定义,将 PVC 挂载到容器内的某个路径进行使用。

    • ④ 资源释放:

      • 用户删除 PVC 来释放 PV 。
      • 当存储资源使用完毕后,用户可以删除 PVC,和该 PVC 绑定的 PV 将会标记为 已释放 ,但是还不能立刻和其他的 PVC 进行绑定。通过之前 PVC 写入的数据可能还留在存储设备上,只有在清除之后该 PV 才能再次使用。
    • ⑤ 资源回收:

      • Kubernetes 根据 PV 设置的回收策略进行资源的回收。
      • 对于 PV,管理员可以设定回收策略,用于设置与之绑定的 PVC 释放资源之后如何处理遗留数据的问题。只有 PV 的存储空间完成回收,才能供新的 PVC 绑定和使用。

    动态供应

    StorageClass

    上面通过手动的方式创建了一个 NFS Volume,这在管理很多 Volume 的时候不太方便。Kubernetes 还提供了 StorageClass 来动态创建 PV,不仅节省了管理员的时间,还可以封装不同类型的存储供 PVC 选用。

    StorageClass 包括四个部分

    • provisioner:指定 Volume 插件的类型,包括内置插件(如 kubernetes.io/glusterfs)和外部插件(如 external-storage 提供的 ceph.com/cephfs)。
    • mountOptions:指定挂载选项,当 PV 不支持指定的选项时会直接失败。比如 NFS 支持 hardnfsvers=4.1 等选项。
    • parameters:指定 provisioner 的选项,比如 kubernetes.io/aws-ebs 支持 typezoneiopsPerGB 等参数。
    • reclaimPolicy:指定回收策略,同 PV 的回收策略。

    在使用 PVC 时,可以通过 DefaultStorageClass 准入控制设置默认 StorageClass, 即给未设置 storageClassName 的 PVC 自动添加默认的 StorageClass。而默认的 StorageClass 带有 annotation storageclass.kubernetes.io/is-default-class=true

    在这里插入图片描述

    动态供应流程

    在这里插入图片描述

    • ① 集群管理员预先创建存储类(StorageClass)。

    • ② 用户创建使用存储类的持久化存储声明(PVC:PersistentVolumeClaim)。

    • ③ 存储持久化声明通知系统,它需要一个持久化存储(PV: PersistentVolume)。

    • ④ 系统读取存储类的信息。

    • ⑤ 系统基于存储类的信息,在后台自动创建 PVC 需要的 PV 。

    • ⑥ 用户创建一个使用 PVC 的 Pod 。

    • ⑦ Pod 中的应用通过 PVC 进行数据的持久化。

    • ⑧ PVC 使用 PV 进行数据的最终持久化处理。

    NFS 动态供应案例

    注意:不一定需要设置 NFS 动态供应,可以直接使用云厂商提供的 StorageClass 。

    部署 NFS 动态供应:

    创建文件k8s-nfs-provisioner.yaml:

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: nfs-client
    provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # 指定一个供应商的名字 
    # or choose another name, 必须匹配 deployment 的 env PROVISIONER_NAME'
    parameters:
      archiveOnDelete: "false" # 删除 PV 的时候,PV 中的内容是否备份
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nfs-client-provisioner
      labels:
        app: nfs-client-provisioner
      namespace: default
    spec:
      replicas: 1
      strategy:
        type: Recreate
      selector:
        matchLabels:
          app: nfs-client-provisioner
      template:
        metadata:
          labels:
            app: nfs-client-provisioner
        spec:
          serviceAccountName: nfs-client-provisioner  # 账号的名字,用来管理权限
          containers:
            - name: nfs-client-provisioner
              image: ccr.ccs.tencentyun.com/gcr-containers/nfs-subdir-external-provisioner:v4.0.2
              volumeMounts:
                - name: nfs-client-root
                  mountPath: /persistentvolumes
              env:
                - name: PROVISIONER_NAME
                  value: k8s-sigs.io/nfs-subdir-external-provisioner
                - name: NFS_SERVER
                  value: 192.168.65.100 # NFS 服务器的地址
                - name: NFS_PATH
                  value: /nfs/data # NFS 服务器的共享目录
          volumes:
            - name: nfs-client-root
              nfs:
                server: 192.168.65.100
                path: /nfs/data
    # 下面都是权限相关的配置了
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: nfs-client-provisioner
      namespace: default
    ---
    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: nfs-client-provisioner-runner
    rules:
      - apiGroups: [""]
        resources: ["nodes"]
        verbs: ["get", "list", "watch"]
      - 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: ["create", "update", "patch"]
    ---
    kind: ClusterRoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: run-nfs-client-provisioner
    subjects:
      - kind: ServiceAccount
        name: nfs-client-provisioner
        namespace: default
    roleRef:
      kind: ClusterRole
      name: nfs-client-provisioner-runner
      apiGroup: rbac.authorization.k8s.io
    ---
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: leader-locking-nfs-client-provisioner
      namespace: default
    rules:
      - apiGroups: [""]
        resources: ["endpoints"]
        verbs: ["get", "list", "watch", "create", "update", "patch"]
    ---
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: leader-locking-nfs-client-provisioner
      namespace: default
    subjects:
      - kind: ServiceAccount
        name: nfs-client-provisioner
        namespace: default
    roleRef:
      kind: Role
      name: leader-locking-nfs-client-provisioner
      apiGroup: rbac.authorization.k8s.io
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112

    上面涉及到Role和RoleBinding等权限相关的资源,这里可以不用管,后面还会介绍,只需要知道他是负责创建和管理权限的即可。因为我们要创建StorageClass必须要制定一个provisioner(制备器,可存储供应商),要让provisioner帮我们管理pv,那就要给他一定的权限。

    部署上面文件即可:

    kubectl apply -f k8s-nfs-provisioner.yaml
    
    • 1

    这样就让provisioner通过StorageClass帮我们管理PV了。

    下面使用时,指定StorageClass的名字:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: nginx-pvc
      namespace: default
      labels:
        app: nginx-pvc
    spec:
      storageClassName: nfs-client # 注意此处
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 2Gi
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      namespace: default
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.20.2
        resources:
          limits:
            cpu: 200m
            memory: 500Mi
          requests:
            cpu: 100m
            memory: 200Mi
        ports:
        - containerPort:  80
          name:  http
        volumeMounts:
        - name: localtime
          mountPath: /etc/localtime
        - name: html
          mountPath: /usr/share/nginx/html/ 
      volumes:
        - name: localtime
          hostPath:
            path: /usr/share/zoneinfo/Asia/Shanghai
        - name: html    
          persistentVolumeClaim:
            claimName:  nginx-pvc
            readOnly: false  
      restartPolicy: Always
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    目前,只需要运维人员部署好各种 storageclass,开发人员在使用的时候,创建 PVC 即可;但是,存储系统太多太多,运维人员也未必会一一掌握,可以 Rook 来统一管理。

  • 相关阅读:
    基于SSM的农业信息管理系统的设计与实现(有报告)。Javaee项目。ssm项目。
    JS中的前后端交互技术ajax
    Spring MVC ViewResolver原理解析
    图片上的字怎么去掉?尝试下这几种简单操作方法
    Python面试题:解释 Python 中的类型提示(type hinting)
    2022年比若依更香的开源项目
    eggjs的mvc模式demo(纯静态)
    SpriteRenderer和Image组件的区别
    Ubuntu开机自动挂载SD卡到指定挂载点并将Docker默认存储路径改为SD卡
    Vue组件小tips
  • 原文地址:https://blog.csdn.net/qq_43745578/article/details/132731451