• 第32讲:K8S集群与Cephfs文件系统集成


    1.在K8S环境下RBD与Cephfs的使用对比

    在K8S环境中,大多数情况下都是多个Pod资源同时挂载一个存储端,共享存储中的数据,在这个普遍应用场景下,Ceph集群的RBD块存储和Cephfs文件系统有着非常明显的区别。

    • RBD存储
      • 仅支持同一个Node节点中的多个Pod共享存储中的数据,不支持跨Node节点的Pod挂载同一个RBD存储。
      • Ceph RBD块存储的读写延迟低,性能强。
      • QKubernetes集群对RBD块存储有专门的驱动程序。
    • Cephfs文件系统
      • 支持多个Node节点中多个Pod同时挂载,实现共享存储。
      • 读写延迟性能略逊于RBD块存储。
      • 需要安装第三方的驱动程序。

    无论是RBD还是Cephfs与K8S集群集成都没有想象中那么好,RBD不支持跨Node节点的Pod一起使用,而Cephfs则不支持指定使用某个Cephfs文件系统,但是在我不懈努力之下,终于研究出了指定某个Cephfs文件系统的方法。

    Cephfs更加友好,起码支持跨节点的Pod都可以同时使用,并且可以指定使用哪一个Cephfs文件系统,我们可以为K8S集群单独创建一个Cephfs文件系统。

    Cephfs文件系统常用的几种方式:

    • 为不同的客户端创建不同Cephfs文件系统,挂载时指定使用不同的Cephfs。

    • 集群中只创建一个Cephfs,为不同的客户端在Cephfs文件系统中创建不同的子目录,挂载时指定不同的子目录路径。

    在实际生产者中第二种方式最为常见,但是如果一个Ceph集群中要为不同类型的客户端提供存储服务,那么建议创建出多个Cephfs文件系统,客户端通过参数分别指定使用哪一个Cephfs。

    2.Cephfs环境介绍

    K8S集群连接Cephfs文件系统时,默认情况下是连接的Ceph集群中默认的Cephfs文件系统,也就是数据资源池为cephfs_data和元数据资源池cephfs_metadata的Cephfs文件系统,并且K8S官方的对接Cephfs的文档中,如果Ceph集群中有多个Cephfs文件系统时,中并没有说明使用什么参数可以指定使用某一个的Cephfs文件文件系统。

    好在功夫不负有心人,再查阅了大量的资料后,终于找到了可以让K8S各种存储卷指定使用某一个Cephfs文件系统的方法。

    我们K8S对接Ceph集群的Cephfs文件系统的环境如下:

    当前集群中存在多个Cephfs文件系统,我们会为K8S集群创建单独的Cephfs文件系统,K8S集群Volume、PV、StorageClass访问Cephfs时,会通过具体的参数指定要使用Ceph集群的哪一个Cephfs文件系统,来实现数据的存储。

    3.在Ceph集群中为K8S创建单独Cephfs文件系统和认证用户

    3.1.创建一个K8S使用的Cephfs文件系统

    1)首先创建Cephfs依赖的数据池和元数据池

    [root@ceph-node-1 ~]# ceph osd pool create kubernetes_cephfs_data 16 16
    pool 'kubernetes_cephfs_data' created
    [root@ceph-node-1 ~]# ceph osd pool create kubernetes_cephfs_metadata 16 16
    pool 'kubernetes_cephfs_metadata' created
    

    2)创建一个Cephfs文件系统

    [root@ceph-node-1 ~]# ceph fs new kubernetes_cephfs kubernetes_cephfs_metadata kubernetes_cephfs_data
    new fs with metadata pool 14 and data pool 13
    

    3)查看集群中所有的Cephfs文件系统

    发型当前集群有两个Cephfs文件系统,后面会通过具体的参数,指定存储卷使用某一个Cephfs文件系统。

    [root@ceph-node-1 ~]# ceph fs ls
    name: kubernetes_cephfs, metadata pool: kubernetes_cephfs_metadata, data pools: [kubernetes_cephfs_data ]
    name: cephfs-storage, metadata pool: cephfs2_data, data pools: [cephfs2_metadata ]
    

    4)查看Cephfs文件系统的状态

    [root@ceph-node-1 ~]# ceph fs status kubernetes_cephfs
    kubernetes_cephfs - 0 clients
    =================
    +------+--------+-------------+---------------+-------+-------+
    | Rank | State  |     MDS     |    Activity   |  dns  |  inos |
    +------+--------+-------------+---------------+-------+-------+
    |  0   | active | ceph-node-2 | Reqs:    0 /s |    0  |    0  |
    +------+--------+-------------+---------------+-------+-------+
    +----------------------------+----------+-------+-------+
    |            Pool            |   type   |  used | avail |
    +----------------------------+----------+-------+-------+
    | kubernetes_cephfs_metadata | metadata | 1728k | 17.9G |
    |   kubernetes_cephfs_data   |   data   |    0  | 17.9G |
    +----------------------------+----------+-------+-------+
    +-------------+
    | Standby MDS |
    +-------------+
    | ceph-node-1 |
    +-------------+
    +-----------------------------------------------------------------------------------+-------------+
    |                                      version                                      |   daemons   |
    +-----------------------------------------------------------------------------------+-------------+
    |                                        None                                       | ceph-node-2 |
    | ceph version 14.2.22 (ca74598065096e6fcbd8433c8779a2be0c889351) nautilus (stable) | ceph-node-1 |
    +-----------------------------------------------------------------------------------+-------------+
    

    3.2.将创建的Cephfs文件系统挂载到本地路径

    挂载到本地路径的原因是为了给K8S集群不同类型的存储卷,提供一个子目录,不同的存储卷挂载不同的子目录来存储持久化文件。

    使用mount命令中的mds_namespace参数指定要将哪个Cephfs文件系统挂载到本地路径。

    [root@ceph-node-1 ~]# mount -t ceph  192.168.20.20:6789,192.168.20.21:6789,192.168.20.22:6789:/nginx_conf /nginx_conf/ -o name=admin,mds_namespace=kubernetes_cephfs
    
    [root@ceph-node-1 kubernetes_cephfs]# df -hT /kubernetes_cephfs/
    文件系统                                                   类型  容量  已用  可用 已用% 挂载点
    192.168.20.20:6789,192.168.20.21:6789,192.168.20.22:6789:/ ceph   18G     0   18G    0% /kubernetes_cephfs
    

    3.3.创建K8S连接Ceph集群使用的认证用户

    [root@ceph-node-1 ~]# ceph auth get-or-create client.kubernetes_cephfs mon "allow r" mds "allow rw" osd "allow rw pool=kubernetes_cephfs_data, allow rw pool=kubernetes_cephfs_metadata"
    [client.kubernetes_cephfs]
    	key = AQAVMFpi1gm6GBAARrJdTXsxYQwGiA1D7h2jHw==
    

    4.K8S PV存储卷使用Cephfs文件系统

    4.1.在Cephfs文件系统中为PV挂载创建子目录

    在Cephfs文件系统中为PV类型的存储卷创建独立的子目录,来持久化容器的数据。

    现在属于实验环境,如果是线上环境时,还要在子子目录下为不同应用程序挂载分别创建三级目录。

    [root@ceph-node-1 ~]# mkdir /kubernetes_cephfs/pv_storage
    

    4.2.将K8S连接Cephfs的认证用户信息存储在Secret中

    我们在前面创建了一个专门用于K8S访问Cephfs文件系统的认证用户,将该用户的Key通过Base64进行加密,然后保存在Secret资源中,最后在创建存储卷的资源编排文件中,引用这个Secret资源。

    1)将认证用户的Key进行Base64加密

    [root@ceph-node-1 ~]# ceph auth get-key client.kubernetes_cephfs | base64
    QVFBVk1GcGkxZ202R0JBQVJySmRUWHN4WVF3R2lBMUQ3aDJqSHc9PQ==
    

    2)将加密后的用户认证Key存储在Secret资源中

    [root@k8s-master volumes]# vim cephfs-volumes-secret.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: cephfs-secret
    data:
      key: QVFBVk1GcGkxZ202R0JBQVJySmRUWHN4WVF3R2lBMUQ3aDJqSHc9PQo=
    

    3)创建Secret并查看资源的状态

    [root@k8s-master volumes]# kubectl apply -f cephfs-volumes-secret.yaml
    secret/cephfs-secret created
    
    [root@k8s-master volumes]# kubectl get secret
    NAME                  TYPE                                  DATA   AGE
    cephfs-secret         Opaque                                1      3m30s
    

    4.3.创建PV存储卷对接Cephfs文件系统

    创建一个PV资源采用Cephfs文件系统作为底层存储端。

    1)编写资源编排文件

    PV指定使用某个Cephfs文件系统主要是通过mountOptions参数来实现的,这个参数是为挂载存储卷时设置一些挂载参数,在宿主机使用mount挂载Cephfs时有参数可以指定挂载哪一个Cephfs,同理在PV中也提供了这种参数,通过这个参数,我们就可以指定使用哪一个Cephfs文件系统了。

    [root@k8s-master pv]# cat cephfs-pv.yaml
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: cephfs-pv
    spec:
      capacity:
        storage: 10Gi
      accessModes:
      - ReadWriteMany
      mountOptions: 								#指定使用哪一个Cephfs文件系统
      - mds_namespace=kubernetes_cephfs					#Cephfs文件系统的名称
      cephfs:										#存储源使用Cephfs类型
        monitors:									#Monitor组件的地址
        - 192.168.20.20:6789
        - 192.168.20.21:6789
        - 192.168.20.22:6789
        path: /pv_storage								#挂载Cephfs文件系统中的哪一个子目录
        user: kubernetes_cephfs							#使用Cephfs文件系统的认证用户
        readOnly: false
        secretRef:									   #认证用户的Secret
          name: cephfs-secret
      persistentVolumeReclaimPolicy: Recycle
    

    2)创建PV资源并查看资源的状态

    [root@k8s-master pv]# kubectl apply -f cephfs-pv.yaml 
    persistentvolume/cephfs-pv created
    
    [root@k8s-master pv]# kubectl get pv
    NAME            CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                    STORAGECLASS   REASON   AGE
    cephfs-pv       10Gi       RWX            Recycle          Available                                                    5m12s
    

    4.4.创建PVC资源从PV中获取存储空间

    PV已经创建完成了,下面来创建PVC资源,关联PV,从PV中分配存储空间给Pod资源使用。

    1)编写资源编排文件

    [root@k8s-master pv]# cat cephfs-pvc.yaml 
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: cephfs-pvc
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 10Gi
    

    2)创建PVC并查看资源的状态

    [root@k8s-master pv]# kubectl apply -f cephfs-pvc.yaml
    persistentvolumeclaim/cephfs-pvc created
    
    [root@k8s-master pv]# kubectl get pvc
    NAME             STATUS   VOLUME          CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    cephfs-pvc       Bound    cephfs-pv       10Gi       RWX                           3s
    

    PVC已经与PV资源进行了绑定,下面就可以给Pod资源使用了。

    4.5.创建Pod资源将数据持久化到Cephfs中

    使用Cephfs文件系统作为存储源的PV和PVC资源都已经准备就绪了,下面来创建一个Pod资源,挂载PVC,将数据持久化到Cephfs文件系统中。

    1)编写资源编排文件

    [root@k8s-master pv]# cat cephfs-pv-pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: cephfs-pod
    spec:
      containers:
        - image: nginx:1.15
          name: cephfs-pod
          ports:
          - name: web
            containerPort: 80
            protocol: TCP
          volumeMounts:
          - name: data
            mountPath: /data						#将PVC挂载到/data目录
      volumes:	
        - name: data
          persistentVolumeClaim:
            claimName: cephfs-pvc					#关联PVC的名称
    

    2)创建Pod并查看资源的状态

    [root@k8s-master pv]# kubectl apply -f cephfs-pv-pod.yaml
    pod/cephfs-pod created
    
    [root@k8s-master pv]# kubectl get pod
    NAME         READY   STATUS    RESTARTS   AGE
    cephfs-pod   1/1     Running   0          11s
    

    4.6.验证Pod资源持久化数据导Cephfs

    Pod资源已经创建完成,下面进入到Pod中创建一些文件,看看是否能持久化到Cephfs文件系统中。

    1)在Pod资源中写入数据文件

    [root@k8s-master pv]# kubectl exec -it cephfs-pod bash 
    root@cephfs-pod:/# cd /data/
    root@cephfs-pod:/data# touch file{1..10}.txt
    

    2)查看Cephfs文件系统中是否有Pod持久化的数据文件

    到查看这一步,就要尽显当初将Cephfs文件系统的根目录挂载到本地路径的好处了,我们可以直接进入到挂载的目录中,查看来自客户端写入的数据。

    [root@ceph-node-1 ~]# cd /kubernetes_cephfs/
    [root@ceph-node-1 kubernetes_cephfs]# tree pv_storage/
    pv_storage/
    ├── aa
    ├── file10.txt
    ├── file1.txt
    ├── file2.txt
    ├── file3.txt
    ├── file4.txt
    ├── file5.txt
    ├── file6.txt
    ├── file7.txt
    ├── file8.txt
    └── file9.txt
    
    0 directories, 11 files
    

    Pod数据持久化成功。

    5.K8S StorageClass存储类使用Cephfs文件系统

    5.1.Cephfs-Provisioner客户端简介

    StoragecClass存储类动态分配PV,需要依赖第三方的客户端插件,通过客户端插件连接到Cephfs文件系统,从而自动分配PV资源。

    由于K8S没有内置Cephfs的Provisioner,故需要安装第三方的Provisioner客户端

    Cephfs-Provisioner主要组件:

    • cephfs-provisioner.go:是cephfs-provisioner(cephfs的storageclass)的核心,主要是watch kubernetes中PVC资源的CURD事件,然后以命令行方式调用cephfs_provisor.py脚本创建PV。
    • cephfs_provisioner.py:python 脚本实现的与cephfs交互的命令行工具。cephfs-provisioner对cephfs端volume的创建都是通过该脚本实现。里面封装了volume的增删改查等功能。

    5.2.在K8S集群中部署Cephfs-Provisioner客户端

    Cephfs-Provisioner客户端在GitHub的地址:https://github.com/kubernetes-retired/external-storage/tree/master/ceph/cephfs/deploy/rbac

    完整的Cephfs-Provisioner客户端资源编排文件内容:

    [root@k8s-master cephfs-provisioner]# cat cephfs-provisioner.yaml 
    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: cephfs-provisioner
      namespace: kube-system
    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: ["create", "update", "patch"]
      - apiGroups: [""]
        resources: ["services"]
        resourceNames: ["kube-dns","coredns"]
        verbs: ["list", "get"]
    
    ---
    
    kind: ClusterRoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: cephfs-provisioner
    subjects:
      - kind: ServiceAccount
        name: cephfs-provisioner
        namespace: kube-system
    roleRef:
      kind: ClusterRole
      name: cephfs-provisioner
      apiGroup: rbac.authorization.k8s.io
    
    
    ---
    
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: cephfs-provisioner
      namespace: kube-system
    rules:
      - apiGroups: [""]
        resources: ["secrets"]
        verbs: ["create", "get", "delete"]
      - apiGroups: [""]
        resources: ["endpoints"]
        verbs: ["get", "list", "watch", "create", "update", "patch"]
    
    ---
    
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: cephfs-provisioner
      namespace: kube-system
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: cephfs-provisioner
    subjects:
    - kind: ServiceAccount
      name: cephfs-provisioner
    
    ---
    
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: cephfs-provisioner
      namespace: kube-system
    
    ---
    
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: cephfs-provisioner
      namespace: kube-system
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: cephfs-provisioner
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            app: cephfs-provisioner
        spec:
          containers:
          - name: cephfs-provisioner
            image: "quay.io/external_storage/cephfs-provisioner:latest"
            env:
            - name: PROVISIONER_NAME
              value: ceph.com/cephfs
            - name: PROVISIONER_SECRET_NAMESPACE
              value: cephfs
            command:
            - "/usr/local/bin/cephfs-provisioner"
            args:
            - "-id=cephfs-provisioner-1"
          serviceAccount: cephfs-provisioner
    

    在集群中部署Cephfs-Provisioner客户端。

    [root@k8s-master cephfs-provisioner]# kubectl apply -f cephfs-provisioner.yaml
    clusterrole.rbac.authorization.k8s.io/cephfs-provisioner created
    clusterrolebinding.rbac.authorization.k8s.io/cephfs-provisioner created
    role.rbac.authorization.k8s.io/cephfs-provisioner created
    rolebinding.rbac.authorization.k8s.io/cephfs-provisioner created
    serviceaccount/cephfs-provisioner created
    deployment.apps/cephfs-provisioner created
    

    当看到Cephfs-Provisioner客户端的Pod资源处于Running状态就表示部署成功了。

    [root@k8s-master cephfs-provisioner]# kubectl get pod -n kube-system | grep cephfs
    cephfs-provisioner-67dd56fb57-l7xxm         1/1     Running   0          21m
    

    5.3.失败了。。。。。。。

    6.K8S Volumes存储卷使用Cephfs文件系统

    Volumes类型的存储卷无法像PV、PVC等通过mountOptions参数指定要使用的Cephfs文件系统,因此Volumes存储卷只能使用默认的Cephfs文件系统,基于这种场景,我们可以在默认的Cephfs文件系统中创建出多个子目录供不同的客户端去使用,这也是Cephfs文件系统最常用的方法。

    6.1.在默认的Cephfs文件系统中为Volumes创建子目录

    所谓默认的Cephfs文件系统指的是数据资源池为cephfs_data、元数据资源池为cephfs_metadata的Cephfs文件系统。

    在Cephfs文件系统中为Volumes类型的存储卷创建独立的子目录,来持久化容器的数据。

    1)默认的Cephfs文件系统的创建方法

    1.创建元数据资源池
    [root@ceph-node-1 ~]# ceph osd pool create cephfs_metadata 16 16
    pool 'cephfs_metadata' created
    
    2.创建数据资源池
    [root@ceph-node-1 ~]# ceph osd pool create cephfs_data 16 16
    pool 'cephfs_data' created
    
    3.创建Cephfs文件系统
    [root@ceph-node-1 ~]# ceph fs new cephfs-storage cephfs_metadata cephfs_data
    new fs with metadata pool 8 and data pool 9
    

    2)挂载Cephfs文件系统

    [root@ceph-node-1 ceph-deploy]# mount -t ceph  192.168.20.20:6789,192.168.20.21:6789,192.168.20.22:6789:/ /kubernetes_cephfs/ -o name=admin
    

    3)为Volumes存储创建子目录

    [root@ceph-node-1 ~]# mkdir /kubernetes_cephfs/volumes_storage
    

    6.2.将K8S连接Cephfs的认证用户信息存储在Secret中

    可以直接使用admin用户连接Ceph集群,也可以专门创建一个。

    1)将认证用户的Key进行Base64加密

    [root@ceph-node-1 ~]# ceph auth get-key client.admin | base64
    QVFCSVdVaGlFbWFGT0JBQTZKcjZpdFVlSGlMVlZPZVlGVnBSb2c9PQ==
    

    2)将加密后的用户认证Key存储在Secret资源中

    [root@k8s-master volumes]# vim cephfs-volumes-secret.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: cephfs-volumes-secret
    data:
      key: QVFCSVdVaGlFbWFGT0JBQTZKcjZpdFVlSGlMVlZPZVlGVnBSb2c9PQ==
    

    3)创建Secret并查看资源的状态

    [root@k8s-master volumes]# kubectl apply -f cephfs-volumes-secret.yaml
    secret/cephfs-secret created
    
    [root@k8s-master volumes]# kubectl get secret
    NAME                  TYPE                                  DATA   AGE
    cephfs-secret         Opaque                                1      3m30s
    

    6.3.Volumes存储卷对接Cephfs文件系统

    创建一个Pod资源使用Volumes存储卷,将Pod资源的数据持久化到Cephfs文件系统中的子目录里。

    1)编写Pod资源的资源编排文件

    [root@k8s-master volumes]# vim cephfs-volumes-pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: cephfs-pod-volumes
    spec:
      containers:
      - name: cephfs-pod-volumes
        image: nginx:1.15
        volumeMounts:
        - mountPath: "/data"
          name: cephfs-volume
      volumes:
      - name: cephfs-volume
        cephfs:									#使用cephfs类型
          monitors:								 #monitor集群的地址
          - 192.168.20.21:6789
          - 192.168.20.22:6789
          - 192.168.20.23:6789
          path: /volumes_storage					#挂载文件系统中的哪一个子目录
          user: admin								#连接Ceph集群的用户
          secretRef: 								#用户的Secret资源名称
            name: cephfs-volumes-secret
    

    2)创建Pod资源并查看资源的状态

    [root@k8s-master volumes]# kubectl apply -f cephfs-volumes-pod.yaml
    pod/cephfs-pod-volumes created
    
    [root@k8s-master volumes]# kubectl get pod
    NAME                 READY   STATUS    RESTARTS   AGE
    cephfs-pod-volumes   1/1     Running   0          4m18s
    

    6.4.进入Pod中产生数据验证数据持久化效果

    1)产生数据

    [root@k8s-master volumes]# kubectl exec -it cephfs-pod-volumes bash
    root@cephfs-pod-volumes:/# cd /data/
    root@cephfs-pod-volumes:/data# touch web{1..5}.index
    root@cephfs-pod-volumes:/data# ls
    web1.index  web2.index	web3.index  web4.index	web5.index
    

    2)查看Cephfs文件系统中的数据持久化结构

    之前已经将文件系统挂载到本地路径了,可以直接看到一级一级目录的数据内容。

    [root@ceph-node-1 ~]# tree /kubernetes_cephfs/
    /kubernetes_cephfs/
    └── volumes_storage
        ├── web1.index
        ├── web2.index
        ├── web3.index
        ├── web4.index
        └── web5.index
    
    1 directory, 5 files
    
  • 相关阅读:
    干货 | 数字经济创新创业——如何造就成功的职业生涯
    初创公司即融资上亿,这个“人造超级大脑”赛道为什么不是噱头?
    计算机网络——三种交换方式(电路交换、分组交换、报文交换以及优缺点)
    猿创征文 | 2022初学者10个必备程序 “工具箱“
    深度解析JavaScript事件对象属性
    【设计模式】Java设计模式 - 单例模式
    C语言|初始C语言常见问题集(2)
    imx6ull烧写系统固件
    Java — 关于异常
    java获取中文拼音
  • 原文地址:https://blog.csdn.net/weixin_44953658/article/details/140091886