说明【必看】

在这里插入图片描述

  • 总数将近11万,存储一共有4大类,本地卷、网络卷、持久性存储和动态卷供应 ,为了能够直观理解,所以我分成了3篇来发布;
    初次看的时候,建议3篇都打开,按顺序学习和使实验,有助于理解哈。 后面查阅的时候看标题,点进相应的文章哈
  • 这篇是第三篇

本地卷&网络卷【必看】【1】

持久性存储 【必看】【2】

动态卷供应概念等说明

动态卷和持久性存储的区别

  • 前面讲持久性存储的时候,是要先创建pv 然后才能创建pvc。如果不同的命名空间里同时要创建不同的pvc,那么就需要提前把pv 创建好,这样才能为pvc 提供存储。这种操作方式太过于麻烦,所以可以通过storageClass(简称为sc)来解决这个问题。
  • 最终的效果是,管理员不需要提前创建pv,只要创建好storageClass 之后就不用管pv 了,用户创建pvc 的时候,storageClass 会自动创建创建出来一个pv 和这个pvc 进行关联。

动态卷概念说明

  • 动态卷供应允许按需创建存储卷。 如果没有动态供应,集群管理员必须手动地联系他们的云或存储提供商来创建新的存储卷, 然后在 Kubernetes 集群创建 PersistentVolume 对象来表示这些卷。 动态供应功能消除了集群管理员预先配置存储的需要。 相反,它在用户请求时自动供应存储。

运行逻辑

  • 动态卷供应的实现基于 storage.k8s.io API 组中的 StorageClass API 对象。 集群管理员可以根据需要定义多个 StorageClass 对象,每个对象指定一个卷插件(又名 provisioner), 卷插件向卷供应商提供在创建卷时需要的数据卷信息及相关参数。

  • 集群管理员可以在集群中定义和公开多种存储(来自相同或不同的存储系统),每种都具有自定义参数集。 该设计也确保终端用户不必担心存储供应的复杂性和细微差别,但仍然能够从多个存储选项中进行选择。

  • 用口水话的方式说流程,就是持久性存储中,我们需要自己定义pv,然后pvc绑定pv,最后通过pvc创建pod嘛
    而动态卷呢,实际上就是,我们只需要定义pvc即可,pv不需要我们定义,由storageClass自动定义pv。
    如下图,能知道运行逻辑最好,不能知道就当这个图不存在,看下面实例再理解。
    在这里插入图片描述

storageClass 的工作流程【必看】

  • 定义storageClass 时必须要包含一个分配器(provisioner),不同的分配器指定了动态创建pv时使用什么后端存储。先看下面的3 个例子
  • 第一个例子,分配器使用aws 的ebs 作为pv 的后端存储
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs
provisioner: kubernetes.io/aws-ebs
parameters:
  type: io1
  iopsPerGB: "10"
  fsType: ext4
  • 第二个例子,分配器使用lvm 作为pv 的后端存储
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: csi-lvm
provisioner: lvmplugin.csi.alibabacloud.com
parameters:
  vgName: volumegroup1
  fsType: ext4
  reclaimPolicy: Delete
  • 第三个例子,使用hostPath 作为pv 的后端存储
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-hostpath-sc
provisioner: hostpath.csi.k8s.io
reclaimPolicy: Delete
#volumeBindingMode: Immediate
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
  • 我这提供一下相关包吧,想折腾的可以根据下面nfs的方式折腾一下
    动态 storageClass.rar
    在这里插入图片描述

  • 这三个例子里,分别使用了不同的分配器,这些分配器有的是以aws-ebs 做pv 的后端存储,有的是以lv 作为pv 后端存储,有的是以hostPath 作为pv 后端存储。

  • 上面3 个例子里所使用的分配器中,有一些是kubernetes 内置的分配器,比如kubernetes.io/aws-ebs,其他两个分配器不是kubernetes 自带的。kubernetes 自带的分配器包括:

    • kubernetes.io/aws-ebs
    • kubernetes.io/gce-pd
    • kubernetes.io/glusterfs
    • kubernetes.io/cinder
    • kubernetes.io/vsphere-volume
    • kubernetes.io/rbd
    • kubernetes.io/quobyte
    • kubernetes.io/azure-disk
    • kubernetes.io/azure-file
    • kubernetes.io/portworx-volume
    • kubernetes.io/scaleio
    • kubernetes.io/storageos
    • kubernetes.io/no-provisioner
  • 在动态创建pv 的时候,根据使用不同的后端存储,应该选择一个合适的分配器。但是像lvmplugin.csi.alibabacloud.com 和hostpath.csi.k8s.io 这样的分配器既然不是kubernetes 自带的,那是哪里来的呢?

    • 这些非内置的分配器咱们暂且称之为外部分配器,这些外部分配器由第三方提供,是通过自定义CSIDriver(容器存储接口驱动)来实现的分配器。
    • 所以整个流程就是,管理员创建storageClass 时会通过.provisioner 字段指定分配器。管理员创建好storageClass 之后,用户在定义pvc 时需要通过.spec.storageClassName 指定使用哪个storageClass。

在这里插入图片描述
当创建pvc 的时候,系统会通知storageClass,storageClass 会从它所关联的分配器来获取后端存储类型,然后动态的创建一个pv 出来和此pvc 进行关联。

  • 所以,我们创建流程呢就是
  • 1、配置SC
  • 2、配置分配器【自带的可以不用配置】
  • 3、创建pvc

创建动态卷供应【以nfs为例】

我前面已经用nfs 配置过共享文件夹了,因为配置起来相对简单,所以这里继续以nfs 作为后端存储来配置动态卷供应。

主机信息

  • 下面4台主机呢,其中3台是一个集群,一台已经安装好nfs的服务
    如果没有下面环境的,先搭建这么一套出来【k8s集群搭建和nfs服务端配置我博客中都有,如果不会的可以去翻翻博客先学习一下】
服务器名称(hostname)系统版本IP部署模块
masterCentOS Linux release 7.6.1810 (Core)192.168.59.142k8s集群-master节点
node1CentOS Linux release 7.6.1810 (Core)192.168.59.143k8s集群-node节点
node2CentOS Linux release 7.6.1810 (Core)192.168.59.144k8s集群-node节点
etcd1CentOS Linux release 7.4.1708 (Core)192.168.59.156仅部署nfs【未加入集群】

nfs文件共享配置

  • 【nfs这个,建议先去我k8s分类中,找到volume卷的网络卷配置里面有详细说明nfs主机服务搭建和node节点服务安装】

文件创建并共享【nfs节点操作】

  • 任意创建一个目录,并共享这个目录。
    我使用/vdisk
[root@etcd1 ~]# mkdir /vdisk
[root@etcd1 ~]# vim /etc/exports                            
[root@etcd1 ~]# cat /etc/exports | tail -n 1
/vdisk *(rw,sync,no_root_squash)
[root@etcd1 ~]#  
[root@etcd1 ~]# exportfs -arv
# 下面很多共享是做之前存储测试的,没有删除而已,无需在意
exporting *:/vdisk
exporting *:/nfs1
exporting *:/nfs
exporting *:/data/nfs5
exporting *:/data/nfs4
exporting *:/data/nfs3
exporting *:/data/nfs2
exporting *:/data/nfs1
[root@etcd1 ~]# 

nfs外部分配器配置

因为kubernetes 里,nfs 没有内置分配器,所以需要下载相关插件来创建nfs 外部分配器。

安装git服务

[root@master volume]# yum install git -y
[root@master volume]# yum -y install unzip

分配器包准备

[root@master volume]# ls | grep zip
external-storage-master.zip
[root@master volume]# ls | grep tar
nfs-client-provisioner.tar
[root@master volume]# 
  • 然后将nfs这个包拷贝到全部node节点
[root@master volume]# ls | grep tar
nfs-client-provisioner.tar
[root@master volume]# scp nfs-client-provisioner.tar node1:~
root@node1's password: 
nfs-client-provisioner.tar                    100%   44MB  28.7MB/s   00:01    
[root@master volume]# scp nfs-client-provisioner.tar node2:~
root@node2's password: 
nfs-client-provisioner.tar                    100%   44MB  32.5MB/s   00:01    
[root@master volume]# 
  • 然后在所有节点上解压这个nfs镜像
[root@master volume]# docker load -i nfs-client-provisioner.tar 
8dfad2055603: Loading layer  4.284MB/4.284MB
a17ae64bae4f: Loading layer  2.066MB/2.066MB
bd01fa00617b: Loading layer  39.72MB/39.72MB
Loaded image: quay.io/external_storage/nfs-client-provisioner:latest
[root@master volume]# 

[root@node1 ~]# docker load -i nfs-client-provisioner.tar 
8dfad2055603: Loading layer  4.284MB/4.284MB
a17ae64bae4f: Loading layer  2.066MB/2.066MB
bd01fa00617b: Loading layer  39.72MB/39.72MB
Loaded image: quay.io/external_storage/nfs-client-provisioner:latest
[root@node1 ~]# 

[root@node2 ~]# docker load -i nfs-client-provisioner.tar 
8dfad2055603: Loading layer  4.284MB/4.284MB
a17ae64bae4f: Loading layer  2.066MB/2.066MB
bd01fa00617b: Loading layer  39.72MB/39.72MB
Loaded image: quay.io/external_storage/nfs-client-provisioner:latest
[root@node2 ~]# 

在master上安装nfs分配器

解压项目并进入到目录

[root@master volume]# unzip external-storage-master.zip 
....
# 很多输出内容
[root@master volume]
[root@master volume]# cd external-storage-master/
[root@master external-storage-master]# cd nfs-client/
[root@master nfs-client]# cd deploy/
[root@master deploy]# ls | grep rb
rbac.yaml
[root@master deploy]# 
  • 部署rbac 权限。
    关于权限的设置后面章节会讲解,因为我们是在命名空间volume 里的,所以需要把rbac.yaml 里指定的命名空间更换为volume,然后部署rbac:
[root@master volume]# kubectl config get-contexts 
CURRENT   NAME           CLUSTER   AUTHINFO   NAMESPACE
*         context        master    ccx        volume
          context1-new   master1   ccx1       default
[root@master volume]#
[root@master deploy]# pwd
/root/volume/external-storage-master/nfs-client/deploy
[root@master deploy]# 
[root@master deploy]# sed -i 's/namespace: default/namespace: volume/g' rbac.yaml
[root@master deploy]# 
[root@master deploy]# kubectl apply -f rbac.yaml
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner created
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
[root@master deploy]# 
  • 配置文件编辑
    需要修改3处参数,已经在内容中说明了
[root@master deploy]# cat -n deployment.yaml
     1  apiVersion: apps/v1
     2  kind: Deployment
     3  metadata:
     4    name: nfs-client-provisioner
     5    labels:
     6      app: nfs-client-provisioner
     7    # replace with namespace where provisioner is deployed
	     # 修改当前所属命名空间【上面步骤有查看方式的】
     8    namespace: volume
     9  spec:
    10    replicas: 1
    11    strategy:
    12      type: Recreate
    13    selector:
    14      matchLabels:
    15        app: nfs-client-provisioner
    16    template:
    17      metadata:
    18        labels:
    19          app: nfs-client-provisioner
    20      spec:
    21        serviceAccountName: nfs-client-provisioner
    22        containers:
    23          - name: nfs-client-provisioner
    24            image: quay.io/external_storage/nfs-client-provisioner:latest
    			  # 增加镜像获取规则【上面分配器步骤已经将包导入了】
    25            imagePullPolicy: IfNotPresent
    26            volumeMounts:
    27              - name: nfs-client-root
    28                mountPath: /persistentvolumes
    29            env:
    30              - name: PROVISIONER_NAME
    31                value: fuseim.pri/ifs
    32              - name: NFS_SERVER
    			      # nfs的共享ip
    33                value: 192.168.59.156
    34              - name: NFS_PATH
    				  # nfs的共享目录
    35                value: /vdisk
    36        volumes:
    37          - name: nfs-client-root
    38            nfs:
    				# 下面nfsip和共享目录
    39              server: 192.168.59.156
    40              path: /vdisk
[root@master deploy]# 
  • 创建pod
    创建需要一点时间,可能要多等会才能running
[root@master deploy]# kubectl apply -f deployment.yaml 
deployment.apps/nfs-client-provisioner configured
[root@master deploy]# kubectl get pods -o wide
NAME                                      READY   STATUS        RESTARTS   AGE     IP               NODE    NOMINATED NODE   READINESS GATES
nfs-client-provisioner-8464d69b6b-6gj48   0/1     Terminating   0          6m29s   10.244.166.148   node1   <none>           <none>
[root@master deploy]# kubectl get pods -o wide
NAME                                    READY   STATUS              RESTARTS   AGE   IP       NODE    NOMINATED NODE   READINESS GATES
nfs-client-provisioner-c8f4bcbd-cksn2   0/1     ContainerCreating   0          0s    <none>   node1   <none>           <none>
[root@master deploy]# kubectl get pods -o wide
NAME                                    READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
nfs-client-provisioner-c8f4bcbd-cksn2   1/1     Running   0          3s    10.244.166.149   node1   <none>           <none>
[root@master deploy]#

部署storageClass【master上操作】

  • 创建了nfs 分配器之后,下面开始创建一个使用这个分配器的storageClass。【这是接着上面做的,所以期间没有切换过路径】

  • 创建storageClass。
    在当前目录里有一个名为class.yaml 的文件,用于创建storageClass,其中name可以其定义,其他部要修改即可。
    注:这个class创建后不会有一个单独的pod显示,是正常的,最终kubectl get sc能执行成功就行。

[root@master deploy]# kubectl get sc
No resources found
[root@master deploy]# cat -n class.yaml
     1  apiVersion: storage.k8s.io/v1
     2  kind: StorageClass
     3  metadata:
     	  # 可以自定义name
     4    name: mysc
     5  provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
     6  parameters:
     7    archiveOnDelete: "false"
[root@master deploy]# 
[root@master deploy]# kubectl apply -f class.yaml
storageclass.storage.k8s.io/mysc created
[root@master deploy]# kubectl get pods -o wide
NAME                                    READY   STATUS    RESTARTS   AGE    IP               NODE    NOMINATED NODE   READINESS GATES
nfs-client-provisioner-c8f4bcbd-cksn2   1/1     Running   0          3m2s   10.244.166.149   node1   <none>           <none>
[root@master deploy]# kubectl get sc
NAME   PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
mysc   fuseim.pri/ifs   Delete          Immediate           false                  29s
[root@master deploy]# 

查看sc命令

  • 命令:kubectl get sc
[root@master deploy]# kubectl get sc
NAME   PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
mysc   fuseim.pri/ifs   Delete          Immediate           false                  8m12s
[root@master deploy]# 

配置文件增加一行内容

  • 在1.20及以后的版本需要修改一个参数,查看方式:
[root@master volume]# kubectl version
Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.0", GitCommit:"cb303e613a121a29364f75cc67d3d580833a7479", GitTreeState:"clean", BuildDate:"2021-04-08T16:31:21Z", GoVersion:"go1.16.1", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.0", GitCommit:"cb303e613a121a29364f75cc67d3d580833a7479", GitTreeState:"clean", BuildDate:"2021-04-08T16:25:06Z", GoVersion:"go1.16.1", Compiler:"gc", Platform:"linux/amd64"}
[root@master volume]# 
  • 修改文件:vim /etc/kubernetes/manifests/kube-apiserver.yaml
# 新增下面18行内容,然后重启服务
[root@master volume]# cat -n /etc/kubernetes/manifests/kube-apiserver.yaml | grep -C1 feature-gates=RemoveSelfLink=false 
    17      - --allow-privileged=true
    18      - --feature-gates=RemoveSelfLink=false
    19      - --authorization-mode=Node,RBAC
[root@master volume]# 
[root@master volume]# systemctl restart kubelet.service
[root@master volume]# 

配置动态卷【nfs】

这个就不多说了,动态卷呢,就是没有创建pv的这个流程,我们直接创建一个pvc,系统会自动给我们创建一个pv并且绑定到pvc上面。

配置文件说明

[root@master volume]# cat -n pvauto.yaml
     1  apiVersion: v1
     2  kind: PersistentVolumeClaim
     3  metadata:
     4    name: autopv #自定义的
     5    annotations:
     6      volume.beta.kubernetes.io/storage-class: "mysc" #这是指定sc的,如果只有一个sc,5和6行可不要,kubectl get sc 查看sc名称
     7  spec:
     8    accessModes:
     9      - ReadWriteOnce # 这些都是模式而已,持久性存储中有说明的
    10    volumeMode: Filesystem #文件类型罢了
    11    resources:
    12      requests:
    13        storage: 300Mi #这是定义大小单位有M和G
    14    storageClassName: mysc #指定sc名称,kubectl get sc 可查看
[root@master volume]# 

创建pvc

  • 创建前当前系统是没有pv和pvc的
[root@master volume]# kubectl get pv
No resources found
[root@master volume]# 
[root@master volume]# kubectl get pvc
No resources found in volume namespace.
[root@master volume]# 
  • 编辑配置文件并创建
    下面创建成功一个pvc以后,就可以看到pvc已经自动和一个pv绑定了。
[root@master volume]# cat -n pvauto.yaml 
     1  apiVersion: v1
     2  kind: PersistentVolumeClaim
     3  metadata:
     4    name: autopv
     5    annotations:
     6      volume.beta.kubernetes.io/storage-class: "mysc"
     7  spec:
     8    accessModes:
     9      - ReadWriteOnce
    10    volumeMode: Filesystem
    11    resources: 
    12      requests: 
    13        storage: 300Mi
    14    storageClassName: mysc
[root@master volume]# 
[root@master volume]# kubectl apply -f pvauto.yaml
persistentvolumeclaim/autopv created
[root@master volume]# 
[root@master volume]# kubectl get pvc
NAME     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
autopv   Bound    pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c   300Mi      RWO            mysc           9s
[root@master volume]# 
[root@master volume]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM           STORAGECLASS   REASON   AGE
pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c   300Mi      RWO            Delete           Bound    volume/autopv   mysc                    11s
[root@master volume]# 

查看pv详细信息【自动生成pv说明】

前面说了,创建pvc呢,会自动生产一个pv,查看pv详细信息:kubectl describe pv pv_name

[root@master volume]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM           STORAGECLASS   REASON   AGE
pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c   300Mi      RWO            Delete           Bound    volume/autopv   mysc                    6m8s
[root@master volume]# 
[root@master volume]# kubectl describe pv pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c 
Name:            pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c
Labels:          <none>
Annotations:     pv.kubernetes.io/provisioned-by: fuseim.pri/ifs
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    mysc
Status:          Bound
Claim:           volume/autopv
Reclaim Policy:  Delete
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        300Mi
Node Affinity:   <none>
Message:         
Source:
    Type:      NFS (an NFS mount that lasts the lifetime of a pod)
    Server:    192.168.59.156
    Path:      /vdisk/volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c
    ReadOnly:  false
Events:        <none>
[root@master volume]# 

这个时候就可以看到自动生成的pv路径了,如上,Source下,这些信息就是nfs服务器的信息了

Source:
    Type:      NFS (an NFS mount that lasts the lifetime of a pod)
    Server:    192.168.59.156
    Path:      /vdisk/volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c
    ReadOnly:  false
Events:        <none>

我们去nfs下验证一下这歌目录信息,并且来了,就随便创建2个文件吧,后面验证用。

[root@etcd1 ~]# cd /vdisk/
[root@etcd1 vdisk]# ls
volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c
[root@etcd1 vdisk]# cd volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c/
[root@etcd1 volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c]# ls
[root@etcd1 volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c]# touch nfs{test1,test2}
[root@etcd1 volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c]# ls
nfstest1  nfstest2
[root@etcd1 volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c]#

删除pvc说明

  • 删除pvc会自动删除相应的pv,这个应该能理解吧。
    注:因为pv的模式是Delete,这个pv被删除以后,对应的数据就会被直接删除【这个delete模式定义在上面sc安装的class.yaml文件中定义的,这不多说,感兴趣的自行研究吧,我觉得动态卷的模式为delete挺合适的,就不想折腾】 【是删除pvc才会丢失数据,通过pvc创建的pod,删除pod后数据是不会丢失的】
[root@master volume]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM           STORAGECLASS   REASON   AGE
pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c   300Mi      RWO            Delete           Bound    volume/autopv   mysc                    11m
[root@master volume]#
  • 现在我们删除这个pv,并且去nfs服务器中查看目录文件是否被删除了。
[root@master volume]# kubectl delete pvc autopv 
persistentvolumeclaim "autopv" deleted
[root@master volume]# 
[root@master volume]# kubectl get pv
No resources found
[root@master volume]# 

# 数据确实没了,成功。
[root@etcd1 ~]# cd /vdisk/
[root@etcd1 vdisk]# ls
[root@etcd1 vdisk]#

绑定pv创建pod

代码解释

  • 先创建好pvc
[root@master volume]# kubectl apply -f pvauto.yaml 
persistentvolumeclaim/autopv created
[root@master volume]# kubectl get pvc
NAME     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
autopv   Bound    pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324   300Mi      RWO            mysc           7s
[root@master volume]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM           STORAGECLASS   REASON   AGE
pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324   300Mi      RWO            Delete           Bound    volume/autopv   mysc                    11s
[root@master volume]# 
  • 下面是一些创建pod的基本参数规则,已经在代码后面注明作用了
    这个和创建pod差不太多,只是卷定义稍有不同,pod更多参数可以参考pod创建自定义测试哦。
[root@master volume]# cat pvpod.yaml 
apiVersion: v1 #自定义版本号
kind: Pod
metadata:
  name: pvpod #自定义pod名称
spec:
  containers:
  - name: pv-pod #自定义名称
    image: nginx #镜像名称
    imagePullPolicy: IfNotPresent #定义镜像获取规则,默认pull
    args: # 下面是自定义command的一种方式,只有一个容器不定义也可
    - /bin/sh
    - -c
    - sleep 300000
    volumeMounts:
    - mountPath: /testdata  #定义容器中的目录
      name: volumedata  #保证与卷的名称一致【卷名称在下面】
  volumes:
    - name: volumedata    #定义卷的名称
      persistentVolumeClaim:
        claimName: ccx-pvc  #指定逻辑卷对应的PVC名称【kubectl get pvc查看】

编辑文件并创建pod

创建这个pod呢,其实和前面持久性存储方式是一样的,仅仅需要修改pvc名称内容即可。而且动态卷和持久性本来就是一样的,就是创建流程不一样罢了。

[root@master volume]# cat -n pvpod.yaml
     1  apiVersion: v1
     2  kind: Pod
     3  metadata:
     4    name: pvpod
     5  spec:
     6    containers:
     7    - name: pv-pod
     8      image: nginx
     9      imagePullPolicy: IfNotPresent
    10      args:
    11      - /bin/sh
    12      - -c
    13      - sleep 300000
    14      volumeMounts:
    15      - mountPath: /testdata
    16        name: volumedata
    17    volumes:
    18      - name: volumedata
    19        persistentVolumeClaim:
    20          claimName: autopv
[root@master volume]# 
[root@master volume]# kubectl apply -f pvpod.yaml
pod/pvpod created
[root@master volume]# kubectl get pod -o wide | grep pod
pvpod                                   1/1     Running   0          14s    10.244.166.151   node1   <none>           <none>
[root@master volume]# 

pod数据测试

额, 我就不多说明了,直接丢测试结果,过程可以去持久性存储里面的pod数据测试看,里面很详细。

#nfs
[root@etcd1 ~]# cd /vdisk/
[root@etcd1 vdisk]# ls
volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324
[root@etcd1 vdisk]# cd volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324/
[root@etcd1 volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324]# touch nfs{test1,test2,test3}
[root@etcd1 volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324]# ls
nfstest1  nfstest2  nfstest3
[root@etcd1 volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324]#

#master
[root@master volume]# kubectl exec -it pvpod -- bash
root@pvpod:/# cd /testdata/
root@pvpod:/testdata# ls
nfstest1  nfstest2  nfstest3
root@pvpod:/testdata# 
root@pvpod:/testdata# touch pvpod{hero1,hero2,hero3}
root@pvpod:/testdata# ls
nfstest1  nfstest2  nfstest3  pvpodhero1  pvpodhero2  pvpodhero3
root@pvpod:/testdata# 

#nfs
[root@etcd1 volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324]# ls
nfstest1  nfstest2  nfstest3  pvpodhero1  pvpodhero2  pvpodhero3
[root@etcd1 volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324]#
  • 上面数据测试没问题
    注:我们删除pod以后数据其实还在,只是删除pvc,数据才会丢失
    现在测试一下吧
#master
[root@master volume]# kubectl delete pod pvpod 
pod "pvpod" deleted
[root@master volume]#

#nfs
[root@etcd1 ~]# cd /vdisk/
[root@etcd1 vdisk]# ls
volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324
[root@etcd1 vdisk]# cd volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324/
[root@etcd1 volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324]# ls
nfstest1  nfstest2  nfstest3  pvpodhero1  pvpodhero2  pvpodhero3
[root@etcd1 volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324]# 

创建动态动态卷供应【官网】

上面的共享卷是nfs的方式,本地卷呢,很明显,就是存储卷在mater上。

配置动态卷供应

  • 注:下面资料来源于官网,我只是照着做了测试而已【有补充】。
    动态卷供应
  • 要启用动态供应功能,集群管理员需要为用户预先创建一个或多个 StorageClass 对象。 StorageClass 对象定义当动态供应被调用时,哪一个驱动将被使用和哪些参数将被传递给驱动。 以下清单创建了一个 StorageClass 存储类 “slow”,它提供类似标准磁盘的永久磁盘。
[root@master volume]# cat bdpv.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard
[root@master volume]#
  • 以下清单创建了一个 “fast” 存储类,它提供类似 SSD 的永久磁盘。
[root@master volume]# cat bdpv2.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard
[root@master volume]# 
  • 创建这2个sc
[root@master volume]# kubectl apply -f bdpv.yaml 
storageclass.storage.k8s.io/slow created
[root@master volume]# kubectl apply -f bdpv2.yaml 
storageclass.storage.k8s.io/fast created
[root@master volume]#
[root@master volume]# kubectl get sc
NAME   PROVISIONER            RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
mysc   fuseim.pri/ifs         Delete          Immediate           false                  6h12m
slow   kubernetes.io/gce-pd   Delete          Immediate           false                  6s
[root@master volume]# 

使用动态卷供应

  • 用户通过在 PersistentVolumeClaim 中包含存储类来请求动态供应的存储。 在 Kubernetes v1.9 之前,这通过 volume.beta.kubernetes.io/storage-class 注解实现。然而,这个注解自 v1.6 起就不被推荐使用了。 用户现在能够而且应该使用 PersistentVolumeClaim 对象的 storageClassName 字段。 这个字段的值必须能够匹配到集群管理员配置的 StorageClass 名称(见下面)。

  • 例如,要选择 “fast” 存储类,用户将创建如下的 PersistentVolumeClaim:

[root@master volume]# cat bdpvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: claim1
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast
  resources:
    requests:
      storage: 30Gi
[root@master volume]#

该声明会自动供应一块类似 SSD 的永久磁盘。 在删除该声明后,这个卷也会被销毁。

  • 创建该pvc,我创建的claim1状态为pending【有一个正常的,可以对比一下】
[root@master volume]# kubectl apply -f bdpvc.yaml
persistentvolumeclaim/claim1 created
[root@master volume]# kubectl get pvc
NAME     STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
autopv   Bound     pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324   300Mi      RWO            mysc           28m
claim1   Pending                                                                        one            2m45s
[root@master volume]#
[root@master volume]# kubectl describe pvc claim1 
Name:          claim1
Namespace:     volume
StorageClass:  fast
Status:        Pending
Volume:        
Labels:        <none>
Annotations:   volume.beta.kubernetes.io/storage-provisioner: kubernetes.io/gce-pd
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      
Access Modes:  
VolumeMode:    Filesystem
Used By:       <none>
Events:        <none>
[root@master volume]# 
[root@master volume]# kubectl describe pvc claim1 
Name:          claim1
Namespace:     volume
StorageClass:  fast
Status:        Pending
Volume:        
Labels:        <none>
Annotations:   volume.beta.kubernetes.io/storage-provisioner: kubernetes.io/gce-pd
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      
Access Modes:  
VolumeMode:    Filesystem
Used By:       <none>
Events:        <none>
[root@master volume]# 
  • 原因是因为我的集群在内网环境,没有我忘,配置卷:无法获取AWS云提供程序,所以状态就是pending,如果集群有外网,上面状态就会为Running了

说明

本来想找找上面的,有没有办法离线弄的,但网上找了很多文章,tm这些人全是复制粘贴的官网内容,没有一点帮助。
不过我在官网中看了较多资料,provisioner: kubernetes.io/gce-pd好像是定义好的,我们直接用就行,我一直失败的原因,我怀疑是因为我的环境是没有外网的,所以本地卷就此打住吧。不折腾这个了。

设置默认值的行为

  • 可以在群集上启用动态卷供应,以便在未指定存储类的情况下动态设置所有声明。 集群管理员可以通过以下方式启用此行为:

    • 标记一个 StorageClass 为 默认;
    • 确保 DefaultStorageClass 准入控制器在 API 服务端被启用。
  • 管理员可以通过向其添加 storageclass.kubernetes.io/is-default-class 注解来将特定的 StorageClass 标记为默认。 当集群中存在默认的 StorageClass 并且用户创建了一个未指定 storageClassName 的 PersistentVolumeClaim 时, DefaultStorageClass 准入控制器会自动向其中添加指向默认存储类的 storageClassName 字段。

  • 请注意,群集上最多只能有一个 默认 存储类,否则无法创建没有明确指定 storageClassName 的 PersistentVolumeClaim。

拓扑感知

在多区域集群中,Pod 可以被分散到多个区域。 单区域存储后端应该被供应到 Pod 被调度到的区域。 这可以通过设置卷绑定模式来实现。

使用aws 的ebs 作为pv 的后端存储

因为这个是系统自带的,所以我们不需要做分配器了,直接定义sc即可。

创建sc

[root@master volume]# cat ebs.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs
provisioner: kubernetes.io/aws-ebs
parameters:
  type: io1
  iopsPerGB: "10"
  fsType: ext4
[root@master volume]# kubectl apply -f ebs.yaml
storageclass.storage.k8s.io/ebs created
[root@master volume]# 
[root@master volume]# kubectl get sc
NAME   PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
ebs    kubernetes.io/aws-ebs   Delete          Immediate           false                  7s
fast   kubernetes.io/gce-pd    Delete          Immediate           false                  19m
mysc   fuseim.pri/ifs          Delete          Immediate           false                  6h36m
slow   kubernetes.io/gce-pd    Delete          Immediate           false                  24m
[root@master volume]# 

创建pvc

[root@master volume]# cat pvauto2.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: autopv2
  #annotations:
    #volume.beta.kubernetes.io/storage-class: "ebs"
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources: 
    requests: 
      storage: 300Mi
  storageClassName: ebs
[root@master volume]# 
[root@master volume]# kubectl apply -f pvauto2.yaml
persistentvolumeclaim/autopv2 created
[root@master volume]# 
[root@master volume]# kubectl get pvc
NAME      STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
autopv2   Pending                                      ebs            3s
claim1    Pending                                      fast           21m
[root@master volume]# 

pending报错原因查看

[root@master volume]# kubectl describe pvc autopv2 
Name:          autopv2
Namespace:     volume
StorageClass:  ebs
Status:        Pending
Volume:        
Labels:        <none>
Annotations:   volume.beta.kubernetes.io/storage-provisioner: kubernetes.io/aws-ebs
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      
Access Modes:  
VolumeMode:    Filesystem
Used By:       <none>
Events:
  Type     Reason              Age               From                         Message
  ----     ------              ----              ----                         -------
  Warning  ProvisioningFailed  6s (x5 over 58s)  persistentvolume-controller  Failed to provision volume with StorageClass "ebs": Failed to get AWS Cloud Provider. GetCloudProvider returned <nil> instead
[root@master volume]# 

上面报错翻译过来就是:persistentvolume controller无法使用StorageClass“ebs”配置卷:无法获取AWS云提供程序。GetCloudProvider返回了

说明

  • 总结,还是因为没有外网,另外,还有一个问题,就是,使用这种自带的分配器,需要考虑账户问题,不知道这个是不是一定条件【或许上面官网的方法也缺这一步账号呢?,但官网没提到过账号这个问题啊,也不知道是不是只要通外网就行了】

  • 使用aws的话,得要有自己的账户
    可以把aws的账户密码存放在一个secret里,在创建sc的时候,里面指定这个secret。这样才能连接到你的aws账户里去

  • 上面的内容是请教的大佬,我没实验过,你可以自己尝试一下哦。【因为我没有通外网的集群,就不折腾了】

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐