持久化存储 StorageClass

上面文章我们创建的pv和pvc都是静态的,简单的来说静态的pv和pvc需要我们手动的创建,这种情况很大程度上并不能满足我们的需求,比如我们有一个应用需要对存储的并发度要求比较高,而另外一个应用对读写速度又要求比较高,特别是对于StatefulSet类型的应用。使用静态PV就很不合时了,这里就需要使用StorageClass

Kubernetes从v1.4版本开始引入了一个新的资源对象StorageClass,用于标记存储资源的特性和性能。到v1.6版本时,StorageClass和动态资源供应的机制得到了完善,实现了存储卷的按需创建,在共享存储的自动化管理进程中能够实现了重要的一步。
通过StorageClass的定义,管理员可以将存储资源定义为某种类别(Class),正如存储设备对于自身的配置描述(Profile),例如 "快速存储" "慢速存储" "有数据冗余" "无数据冗余"等。用户根据StorageClass的描述就能够直观得知各种存储资源的特性,就可以根据应用对存储资源的需求去申请存储资源了。
StorageClass作为对存储资源的抽象定义,对用户设置的PVC申请屏蔽后端的细节,一方面减轻用户对于存储资源细节的关注,另一方面也减轻了管理员手工管理PV的工作,由系统自动完成PV的创建和绑定,实现了动态的资源供应。使用基于StorageClass的动态资源供应模式将逐步成为云平台的标准存储配置模式
StorageClass的定义主要包括名称、后端存储的提供者(Provisioner)和后端存储的相关参数配置。StorageClass一旦被创建出来,将无法修改。如需修改,则只能删除原StorageClass的定义重建。
上面文章我们创建的pv和pvc都是静态的,简单的来说静态的pv和pvc需要我们手动的创建,这种情况很大程度上并不能满足我们的需求,比如我们有一个应用需要对存储的并发度要求比较高,而另外一个应用对读写速度又要求比较高,特别是对于StatefulSet类型的应用。使用静态PV就很不合时了,这里就需要使用StorageClass

创建Provisioner

如果需要使用StorageClass,我们就需要安装对应的自动配置程序,比如我们这里后端采用的是nfs,那么我们就需要使用到一个nfs-client的自动配置程序,我们也叫它Provisioner,这个程序使用我们已经配置好的nfs服务器,来自动创建持久卷,也就是自动帮我们创建PV
自动创建的PV以{namespace}-${pvcname}-${pvname}进行命名到服务器上
当pv被回收后会以archieved-${namespace}-${pvcname}-${pvname}格式存在服务器上
关于安装nfs这里不在介绍,需要的请点击下面的文章进行查看

Kubernetes PV与PVC

新闻联播老司机

  • 20年1月31日
  • 喜欢:0
  • 浏览:4.9k
  • 首先,我们需要配置nfs-client的Deployment文件

    #环境说明
    本次nfs服务器地址192.168.0.14
    数据存储目录 /data1/k8s-volume
    
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: nfs-client-provisioner
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nfs-client-provisioner
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            app: nfs-client-provisioner
        spec:
          serviceAccountName: nfs-client-provisioner
          containers:
            - name: nfs-client-provisioner
              image: quay.io/external_storage/nfs-client-provisioner:latest
              volumeMounts:
                - name: nfs-client-root
                  mountPath: /persistentvolumes
              env:
                - name: PROVISIONER_NAME
                  value: fuseim.pri/ifs
                - name: NFS_SERVER
                  value: 192.168.0.14           #nfs server 地址
                - name: NFS_PATH
                  value: /data1/k8s-volume     #nfs共享目录
          volumes:
            - name: nfs-client-root
              nfs:
                server: 192.168.0.14
                path: /data1/k8s-volume
    

    接下来我们还需要创建一个serveraccount,用于将nfs-client-provisioner中的ServiceAccount绑定到一个nfs-client-provisioner-runner的ClusterRole。而该ClusterRole声明了一些权限,其中就包括了对persistentvolumes的增删改查,所以我们就可以利用ServiceAccount来自动创建PV

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: nfs-client-provisioner
    
    ---
    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: nfs-client-provisioner-runner
    rules:
      - 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: ["list", "watch", "create", "update", "patch"]
      - apiGroups: [""]
        resources: ["endpoints"]
        verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
    
    ---
    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
    

    创建storageclass
    fuseim.pri/ifs 需要和deployment保持一直
    这里我们声明了一个名为managed-nfs-storage的Storageclass对象

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: managed-nfs-storage
    provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
    

    创建

    [root@k8s-01 nfs-client]# kubectl create -f .
    deployment.apps/nfs-client-provisioner created
    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
    storageclass.storage.k8s.io/managed-nfs-storage created
    

    这里也可以直接参考nfs-client的官方文档 (里面有不同存储后端的文件)
    https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client/deploy
    接下来我们可以查看一下

    #Pod状态Running
    [root@k8s-01 nfs-client]# kubectl get pod
    NAME                                      READY   STATUS    RESTARTS   AGE
    nfs-client-provisioner-57cb5b4cfd-lhqpw   1/1     Running   0          61m
    
    #serveraccount也已经创建完成。
    [root@k8s-01 nfs-client]# kubectl get sc
    NAME                  PROVISIONER      AGE
    managed-nfs-storage   fuseim.pri/ifs   62m
    

    持久化存储 StorageClass-每日运维
    接下来我们需要创建一个pvc,来引用刚刚创建的storageclass

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: test-claim
      annotations:
        volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"    #storageclass 名称
    spec:
      accessModes:              #访问模式
        - ReadWriteMany
      resources:
        requests:
          storage: 1024Mi              #请求数据大小
    
    
    #查看sc的名称可以使用kubectl get sc
    

    创建完成后我们可以查看一下pvc

    [root@k8s-01 nfs-client]# kubectl apply -f  nfs-pvc.yaml
    persistentvolumeclaim/test-claim created
    
    
    
    #这里可以看到一个名称为test-claim的pvc,自动帮我们创建了一个pv并绑定到当前的pvc上
    [root@k8s-01 nfs-client]# kubectl get pvc
    NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
    pvc-nfs      Bound    pv1                                        10Gi       RWO                                  3h4m
    test-claim   Bound    pvc-72ecd497-44e0-11ea-b5f6-000c29eeccce   1Gi        RWX            managed-nfs-storage   37s
    
    #这里可以看到自动创建了一个pv
    [root@k8s-01 nfs-client]# kubectl get pv
    NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                STORAGECLASS          REASON   AGE
    pvc-72ecd497-44e0-11ea-b5f6-000c29eeccce   1Gi        RWX            Delete           Bound    default/test-claim   managed-nfs-storage            16m
    

    在默认情况下,我们创建一个pvc需要有一个状态为空闲的pv,然后才会绑定到pvc上。使用storageclass之后,我们不需要的手动创建pv,只需要创建一个pvc,storageclass会自动将pv给创建并且关联
    除了上面使用annotations参数指定storageclass的方式以外,还可以通过修改yaml或者或者通过patch的方式将storageclass设置为默认的存储。(如找不到指定的storageclass则会使用默认sc进行创建pv)

    ##1.通过命令的方式进行修改
    kubectl patch storageclass course-nfs-storage -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
    
    #2.通过修改storageclass方式
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: managed-nfs-storage
      annotations:
        storageclass.kubernetes.io/is-default-class": "true"
    provisioner: fuseim.pri/ifs
    
    
    #提示: 如果我们有一个默认的sc,则不需要在pvc中声明sc的名称
    

    测试

    上面我们创建了nfs-client以及storageclass和pvc,现在我们后端存储已经做好了,接下来我们需要创建一个应用进行演示

    使用Deployment 引用PVC

    这里的Pod类型和Deployment使用方式是一样的,官方默认使用的是Pod这里就不变,修改为Deployment也是一样的格式

    kind: Pod
    apiVersion: v1
    metadata:
      name: test-pod                        #pod的名称
    spec:
      containers:
      - name: test-pod                      #容器的名称
        image: busybox
        imagePullPolicy: IfNotPresent
        command:                            #容器执行的命令
          - "/bin/sh"
        args:
          - "-c"
          - "touch /mnt/SUCCESS && exit 0 || exit 1"
        volumeMounts:
          - name: nfs-pvc                   #容器挂载点名称
            mountPath: "/mnt"               #容器挂载目录
      restartPolicy: "Never"
      volumes:
        - name: nfs-pvc                    #这里的名称要和上面容器挂载点的名称匹配
          persistentVolumeClaim:            #挂载使用pvc
            claimName: test-claim                   #pvc的名称
    

    我们在busybox创建一个SUCCESS的文件,同时将/mnt目录挂载到pvc中

    [root@k8s-01 nfs-client]# kubectl apply -f test.yaml
    pod/test-pod created
    
    [root@k8s-01 nfs-client]# kubectl get pod|grep test-pod
    test-pod                                  0/1     Completed   0          4m30s
    
    #在nfs存储目录就可以看到这个目录
    [root@k8s-01 nfs-client]# ls /data1/k8s/default-test-claim-pvc-72ecd497-44e0-11ea-b5f6-000c29eeccce/
    SUCCESS
    #前面说过,在storageclass中创建的存储,会以${namespace}-${pvc name}-${pv name}
    

    使用StatefulSet 引用Storageclass

    如果我们使用手动指定pvc的方式,当我们pod为多实例的时候,多个pod使用的是一个pvc。但是我们使用statefulset时,storageclass会为我们每一个Pod创建一个pv和pvc

    apiVersion: apps/v1beta1
    kind: StatefulSet
    metadata:
      name: storageclass-test
    spec:
      replicas: 3
      serviceName: "nginx"                      #使用statefulSet需要在配置文件中设置一个service的名称
      template:
        metadata:
          labels:
            app: sc-web
        spec:
          containers:
          - name: nginx
            images: nginx
            ports:
              - containerPort: 80
            volumeMounts:
            - name: nginx-test-pvc                   #挂载点名称 要和下面的关联
              mountPath: /usr/share/nginx/html      #容器挂载目录    
      volumeClaimTemplates:  #使用pvc的情况下就直接在下面创建一个volumes就可以,但是这里不使用pvc
        - metadata:       #这里的格式和我们创建pvc的格式是相同的
            name: nginx-test-pvc                    #pvc名称 要和上面的关联
            annotations:
              volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"   #sc的名称
          spec:
              accessModes:                      #访问模式
                - ReadWriteMany
              resources:
                requests:
                  storage: 10Gi               #存储空间
    

    接下来我们创建查看pv和pvc并且查看一下nfs挂载目录的文件

    [root@k8s-01 nfs-client]# kubectl get pod
    NAME                                      READY   STATUS    RESTARTS   AGE
    nfs-client-provisioner-57cb5b4cfd-lhqpw   1/1     Running   0          169m
    
    storageclass-test-0                       1/1     Running   0          2m38s
    storageclass-test-1                       1/1     Running   0          2m16s
    storageclass-test-2                       1/1     Running   0          2m9s
    
    
    #当Pod状态为Running时,已经帮我们创建好pv和pvc并且相互绑定
    [root@k8s-01 nfs-client]# kubectl get pv
    NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                        STORAGECLASS          REASON   AGE
    pv1                                        10Gi       RWO            Recycle          Bound    default/pvc-nfs                                                             4h33m
    pvc-72ecd497-44e0-11ea-b5f6-000c29eeccce   1Gi        RWX            Delete           Bound    default/test-claim                           managed-nfs-storage            89m
    pvc-81272745-44ec-11ea-b5f6-000c29eeccce   10Gi       RWX            Delete           Bound    default/nginx-test-pvc-storageclass-test-0   managed-nfs-storage            2m51s
    pvc-8dfe513e-44ec-11ea-b5f6-000c29eeccce   10Gi       RWX            Delete           Bound    default/nginx-test-pvc-storageclass-test-1   managed-nfs-storage            2m42s
    pvc-91f8193c-44ec-11ea-b5f6-000c29eeccce   10Gi       RWX            Delete           Bound    default/nginx-test-pvc-storageclass-test-2   managed-nfs-storage            2m21s
    
    
    [root@k8s-01 nfs-client]# kubectl get pvc
    NAME                                 STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
    nginx-test-pvc-storageclass-test-0   Bound    pvc-81272745-44ec-11ea-b5f6-000c29eeccce   10Gi       RWX            managed-nfs-storage   3m16s
    nginx-test-pvc-storageclass-test-1   Bound    pvc-8dfe513e-44ec-11ea-b5f6-000c29eeccce   10Gi       RWX            managed-nfs-storage   2m54s
    nginx-test-pvc-storageclass-test-2   Bound    pvc-91f8193c-44ec-11ea-b5f6-000c29eeccce   10Gi       RWX            managed-nfs-storage   2m47s
    
    
    #同时按照storageclass的生成目录规则帮我们在nfs共享存储中创建好目录
    [root@k8s-01 nfs-client]# ll /data1/k8s/
    总用量 0
    drwxrwxrwx 2 root root  6 2月   1 20:15 default-nginx-test-pvc-storageclass-test-0-pvc-81272745-44ec-11ea-b5f6-000c29eeccce
    drwxrwxrwx 2 root root  6 2月   1 20:15 default-nginx-test-pvc-storageclass-test-1-pvc-8dfe513e-44ec-11ea-b5f6-000c29eeccce
    drwxrwxrwx 2 root root  6 2月   1 20:15 default-nginx-test-pvc-storageclass-test-2-pvc-91f8193c-44ec-11ea-b5f6-000c29eeccce
    

    扩展资料
    在Deployment中,与之对应的服务是service,而在StatefulSet中与之对应的headless service,headless service,即无头服务,与service的区别就是它没有Cluster IP,解析它的名称时将返回该Headless Service对应的全部Pod的Endpoint列表。
    除此之外,StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod副本创建了一个DNS域名,这个域名的格式为:

    $(podname).(headless server name)   
    FQDN: $(podname).(headless server name).namespace.svc.cluster.local
    
    #Headless Service,名为nginx,用来定义Pod网络标识(DNS domain)
    扩展资料http://www.mamicode.com/info-detail-2368542.html
    

    如果不是使用NFS,使用其他如ceph等,依旧可以参考nfs-client的官方文档
    https://github.com/kubernetes-incubator/external-storage

    相关文章:

    1. Kubernetes 1.14 二进制集群安装
    2. Prometheus Operator 持久化存储
    3. CentOS 7 ETCD集群配置大全
    4. Kubernetes PV与PVC