• Kubernetes添加带Quota限额的CephFS StorageClass


    1. Ceph上为Kubernetes创建一个文件系统

    # ceph osd pool create cephfs_data 128
    # ceph osd pool create cephfs_metadata 128
    # ceph fs new cephfs cephfs_metadata cephfs_data

    2. CephFS配置Quotas

    CephFSmount方式分为内核态mount和用户态mount,内核态使用mount命令挂载,用户态使用ceph-fuse。内核态只有在kernel 4.17 + Ceph mimic以上的版本才支持Quotas,用户态则没有限制。

    内核态mount

    # mount -t ceph 10.32.3.70:/k8s_test /mnt/cephfs/ -o name=admin,secret=AQCs2Q9bqAjCHRAAlQUF+hAiXhbErk4NdtvORQ==

    用户态mount

    # ceph-fuse -r /k8s_test /mnt/cephfs/ --name client.admin

    配置quota

    1) 首先在CephFS创建一个要限额的目录

    # mkdir /mnt/cephfs
    # ceph-fuse /mnt/cephfs
    # mkdir /mnt/cephfs/k8s_test

    2) 然后在目录上使用setfattr设置限额属性

    # setfattr -n ceph.quota.max_bytes -v 100000000 /mnt/cephfs/k8s_test

    比如上面这条命令限制/k8s_test目录只能使用100MB大小的空间。

    3) 挂载限额目录并测试

    # mkdir /mnt/k8s_test
    # ceph-fuse -r /k8s_test /mnt/k8s_test/ --name client.admin --client-quota

    由于使用的内核和Ceph版本比较低,只能在用户态测试。在Jewel及之前版本的ceph-fuse,挂载时要指定--client-quota参数,限额才会生效。而在Luminous之后的版本,则不支持这个参数了,会自动识别quota。由于我这里使用的是Jewel版本,所以指定了--client-quota参数。然后写入200MB数据测试一下:

    # cd /mnt/k8s_test
    # dd if=/dev/zero of=test1.bin bs=1M count=200
    dd: error writing ‘test1.bin’: Disk quota exceeded
    129+0 records in
    128+0 records out
    134348800 bytes (134 MB) copied, 0.428233 s, 314 MB/s
    
    # df -h
    Filesystem      Size  Used Avail Use% Mounted on
    ceph-fuse        92M  -64Y  -36M 100% /mnt/cephfs

    可以看到中途提示超出配额,但是写入了134MB数据,超过了指定的配额100MB。这是因为CephFSQuotas不是严格的,按官方说法判断检测周期是10s

    再次写入数据,可以发现完全写不进去了:

    # dd if=/dev/zero of=test2.bin bs=1M count=200
    dd: error writing ‘test2.bin’: Disk quota exceeded
    1+0 records in
    0+0 records out
    0 bytes (0 B) copied, 0.00162182 s, 0.0 kB/s

    3. 更新k8s用户权限

    # ceph auth caps client.k8s mon 'allow rwx' osd 'allow rwx pool=k8s, allow rw pool=cephfs_data' mds 'allow rwp'

    如果还没有创建k8s用户,则使用下面的命令创建:

    # ceph auth get-or-create client.k8s mon 'allow rwx' osd 'allow rwx pool=k8s, allow rw pool=cephfs_data' mds 'allow rwp' -o ceph.client.k8s.keyring

    Kubernets中创建访问CephSecret的步骤见Kubernetes配置Ceph RBD StorageClasses作为Persistent Volumes Claims后端》3~5步。

    4. Kubernetes Volume使用CephFS

    Kubernetes Volume原生支持CephFS类型,使用方法:

    # echo ‘apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-test-cephfs
    spec:
      containers:
      - name: nginx-test-cephfs
        image: registry.exmaple.com/base/nginx:v1.0
        volumeMounts:
        - name: cephfs
          mountPath: "/data/"
      volumes:
      - name: cephfs
        cephfs:
          monitors:
          - 10.32.3.70:6789
          - 10.32.3.71:6789
          - 10.32.3.72:6789
          path: /k8s_test
          user: k8s
          secretRef:
            name: ceph-k8s-secret
          readOnly: false’ | kubectl create -f -

    进入容器查看:

    # kubectl exec nginx-test-cephfs -it -- /bin/bash                                                                                                        
    [root@nginx-test-cephfs ~]# df -h
    Filesystem            Size  Used Avail Use% Mounted on
    10.32.3.70:6789,10.32.3.71:6789,10.32.3.72:6789:/k8s_test
                          5.2T  1.1G  5.2T   1% /data

    5. Kubernetes Persistent Volume使用CephFS

    Kubernetes Persistent Volume原生支持CephFS类型,使用方法:

    # echo 'apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: nginx-test-cephfs-pv-01
      namespace: test
    spec:
      capacity:
        storage: 100Mi
      accessModes:
        - ReadWriteMany
      cephfs:
        monitors:
        - 10.32.3.70:6789
        - 10.32.3.71:6789
        - 10.32.3.72:6789
        path: /k8s_test
        user: k8s
        secretRef:
          name: ceph-k8s-secret
        readOnly: false
    ---
    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: nginx-test-cephfs-pvc-01
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 50Mi
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-test-cephfs-01
    spec:
      containers:
      - name: nginx-test-cephfs
        image: registry.exmaple.com/base/nginx:v1.0
        volumeMounts:
        - name: cephfs-vol1
          mountPath: "/data/"
      volumes:
      - name: cephfs-vol1
        persistentVolumeClaim:
          claimName: nginx-test-cephfs-pvc-01' | kubectl create -f -

    进入容器查看:

    # kubectl exec nginx-test-cephfs -it -- /bin/bash                                                                                                        
    [root@nginx-test-cephfs ~]# df -h
    Filesystem            Size  Used Avail Use% Mounted on
    10.32.3.70:6789,10.32.3.71:6789,10.32.3.72:6789:/k8s_test
                          5.2T  1.1G  5.2T   1% /data

    6. Kubernetes StorageClass使用CephFS

    Kubernetes StorageClass原生不支持CephFS,但是在社区的孵化项目External Storage中添加了CephFS类型的StorageClassExternal Storage是对核心的Kubernetes controller manager的扩展,其中包含的每个external provisioner可以独立部署以支持扩展的StorageClass类型。

    部署CephFS external provisioner

    1) 下载External Storage代码

    # go get github.com/kubernetes-incubator/external-storage

    同时要保证CephFS external provisioner依赖的package源码存在于$GOPATH/src目录下,如果有缺失,后面编译会报错,按照报错使用go get下载就行。

    2) 编译、打包镜像、上传镜像

    进入CephFS external provisioner的源码目录:

    # cd $GOPATH/src/github.com/kubernetes-incubator/external-storage/ceph/cephfs

    修改Makefile,将REGISTRY变量改成自己的镜像仓库地址,注意结尾要带/

    # vim Makefile
    ifeq ($(REGISTRY),)
        REGISTRY = registry.example.com/
    endif

    修改Dockerfile,指定CEPH_VERSION与自己Ceph Cluster的版本一致:

    # vim Dockerfile
    ENV CEPH_VERSION "mimic"

    编译,生成cephfs-provisioner二进制文件:

    # make

    打包docker镜像,并上传到镜像仓库:

    # make push

    3) 部署CephFS external provisioner

    进入部署目录:

    # cd $GOPATH/src/github.com/kubernetes-incubator/external-storage/ceph/cephfs/deploy

    修改镜像地址:

    # vim rbac/deployment.yaml
    image: "registry.example.com/cephfs-provisioner:latest"

    修改希望部署到的namespace

    # NAMESPACE=kube-system
    # sed -r -i "s/namespace: [^ ]+/namespace: $NAMESPACE/g" ./rbac/*.yaml

    部署:

    # kubectl -n $NAMESPACE apply -f ./rbac

    4) 创建cephfs StorageClass

    # echo ‘apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
       name: cephfs
    provisioner: ceph.com/cephfs
    parameters:
      monitors: 10.32.3.70:6789,10.32.3.71:6789,10.32.3.72:6789
      adminId: k8s
      adminSecretName: ceph-k8s-secret
      adminSecretNamespace: kube-system‘ | kubectl create -f -

    5) 创建一个PersistentVolumeClaim

    # echo ‘apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: nginx-test-cephfs-pvc-03
      annotations:
        volume.beta.kubernetes.io/storage-class: "cephfs"
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 100Mi’ | kubectl create -f -

    6) 创建使用PVCPod

    # echo ‘apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-test-cephfs-03
    spec:
      containers:
      - name: nginx-test-cephfs-03
        image: registry.example.com/base/nginx:v1.0
        volumeMounts:
          - name: pvc
            mountPath: "/data/"
      volumes:
        - name: pvc
          persistentVolumeClaim:
            claimName: nginx-test-cephfs-pvc-03’ | kubectl create -f -

    7) 查看容器状态

    # kubectl exec nginx-test-cephfs-03 -it -- /bin/bash
    # df -h
    Filesystem            Size  Used Avail Use% Mounted on
    10.32.3.70:6789,10.32.3.71:6789,10.32.3.72:6789:/volumes/kubernetes/kubernetes-dynamic-pvc-6bfb0ff3-6980-11e8-aa58-5a90b87a7c36
                          5.2T  1.1G  5.2T   1% /data

    7. CephFS StorageClass添加Quotas支持

    注意容器中CephFS的挂载方式,使用的是内核态mount,挂载目录的容量并不是PVC声明的100MiB,而是整个CephFS的可用大小。

    查看源码发现在Kubernetes 1.10之后的版本才会尝试用户态mount。而且目前使用的Kubernetes 1.10.4版本存在bugceph-fuse挂载时指定了-k参数,却没有指定-i或者-n参数,导致尝试使用ceph-fuse挂载会报错,最终后还是回退到内核态挂载。

    另外目前CephFS external provisioner中创建目录时,并没有指定ceph.quota.max_bytes属性,为了添加配额限制,需要修改代码。

    1) 修改CephFS external provisioner

    CephFS external provisioner的结构比较简单,主要就是cephfs-provisioner.gocephfs_provisioner.py两个文件。cephfs-provisioner.go是主程序,创建CephFS Provisionercephfs_provisioner.py 是对ceph_volume_client.CephFSVolumeClient的封装,方便调用。

    修改思路就是在CephFS中创建目录时指定size参数,底层的CephFSVolumeClient.create_volume()判断size存在时会调用setattr设置ceph.quota.max_bytes属性。

    具体修改内容可以参考这个PR。修改完后,重新执行第6步中的打包部署操作使之生效。

    2) 修改Kubelet

    由于1.10.4版本的kubelet存在bug,使用ceph-fuse挂载目录时指定了-k参数却没有指定-i或者-n参数,导致挂载报错。需要修改代码,加上-i参数。具体位置是kubernetes/pkg/volume/cephfs/cephfs.goexecFuseMount()函数,原来的mount参数:

    func (cephfsMounter *cephfsMounter) checkFuseMount() bool {
        …
        mountArgs := []string{}
        mountArgs = append(mountArgs, "-k")
        mountArgs = append(mountArgs, keyring_file)
        mountArgs = append(mountArgs, "-m")
        mountArgs = append(mountArgs, src)
        mountArgs = append(mountArgs, mountpoint)
        mountArgs = append(mountArgs, "-r")
    mountArgs = append(mountArgs, cephfsVolume.path)
    …
    }

    追加两行:

        mountArgs = append(mountArgs, "--id")
        mountArgs = append(mountArgs, cephfsVolume.id)

    如果使用的ceph-fuse版本低于Luminous,还要加上--client-quota参数:

        mountArgs = append(mountArgs, "--client-quota")

    然后重新编译kubelet,替换安装文件,重启服务生效。编译方法参考《编译Kubelet二进制文件》

    3) 验证Quota

    重新使用第6步的配置创建一个Pod,进入容器查看:

    # kubectl exec nginx-test-cephfs-03 -it -- /bin/bash
    root@nginx-test-cephfs-03:/# df -h
    Filesystem    Size    Used    Avail     Use%     Mounted on
    ceph-fuse    100M        0    100M        0%     /data

    看到挂载方式是ceph-fuse,目录可用大小也是quota配置的100M。写入数据测试一下:

    # dd if=/dev/zero of=/data/test.bin bs=1M count=200
    dd: error writing '/data/test.bin': Disk quota exceeded
    123+0 records in
    122+0 records out
    128421888 bytes (128 MB, 122 MiB) copied, 4.32033 s, 29.7 MB/s
    # df -h
    Filesystem    Size    Used    Avail   Use%    Mounted on
    ceph-fuse     100M    100M        0   100%    /data

    Quota确实生效了。

    参考资料

    CephFS Admin Tips – Create a new user and share

    kubernetes笔记: Cephfs

  • 相关阅读:
    饿了么 PostgreSQL 优化之旅
    kubernetes 滚动更新发布及回滚
    kubernetes yaml
    mongodb安装
    node.js安装
    linux输出换行
    把token放入请求头
    $.ajaxSetup
    js前端读取文件内容
    v-echarts安装
  • 原文地址:https://www.cnblogs.com/ltxdzh/p/9173706.html
Copyright © 2020-2023  润新知