kubernets使用ceph-rbd作为storageclass并创建pvc和应用
阅读原文时间:2021年04月26日阅读:1

1.Kubernetes StorageClass 介绍

Kubernetes 集群存储 PV 支持 Static 静态配置以及 Dynamic 动态配置,动态卷配置 (Dynamic provisioning) 可以根据需要动态的创建存储卷。静态配置方式,集群管理员必须手动调用云/存储服务提供商的接口来配置新的固定大小的 Image 存储卷,然后创建 PV 对象以在 Kubernetes 中请求分配使用它们。通过动态卷配置,能自动化完成以上两步骤,它无须集群管理员预先配置存储资源,而是使用 StorageClass 对象指定的供应商来动态配置存储资源。

2.创建StorageClass

StorageClass 对象支持多种类型的存储卷插件来提供 PV,从 Storage Classes 官方文档 provisioner 部分可以看到,它目前支持很多种存储卷类型,其中就有我们熟悉的 Ceph RBD 类型。

AWSElasticBlockStore
AzureFile
AzureDisk
Cinder
Flocker
GCEPersistentDisk
Glusterfs
PhotonPersistentDisk
Quobyte
RBD
VsphereVolume
PortworxVolume
ScaleIO
StorageOS

当然除了上述 k8s 内部支持类别,如果我们需要使用其他类型卷插件,例如 NFS、CephFS 等第三方熟知的类型,可以去 kubernetes-incubator/external-storage 这个 GitHub 仓库,这里有更多扩展存储卷插件支持,下边我们在使用 RBD 作为 StorageClass 的时候也会演示到。

正式开始之前要提一下,通过前边两篇文章 初试 Kubernetes 集群使用 Ceph RBD 块存储 和 初试 Kubernetes 集群使用 CephFS 文件存储 的介绍,我们知道,k8s 不支持跨节点挂载同一 Ceph RBD,支持跨节点挂载 CephFS,让所有的任务都调度到指定node上执行,来保证针对 RBD 的操作在同一节点上。同时既然是动态配置存储资源,意思就是我们不需要提前创建好指定大小的 Image 了,而是动态创建它,所以这里只需要参照 初试 Centos7 上 Ceph 存储集群搭建搭建好 Ceph 存储集群即可,不需要进行 RBD 操作。

2.1 创建 ceph-secret-admin

我们知道 Ceph 存储集群默认是开启了 cephx 认证的,所以我们可以创建一个名称为 ceph-secret-admin 的 secret 对象,用于 k8s volume 插件通过 cephx 认证访问 ceph 存储集群。首先获取并 base64 生成一下 k8s secret 认证 key,然后创建 ceph-secret-admin.yaml 文件,key 值替换一下。

获取并 base64 生成 k8s secret 认证 key

$ ceph auth get-key client.admin | base64
QVFCS3FYSmFRa05wSEJBQWxIRkgrR1NMQ1B3TzNXS2V2YUlMVkE9PQ==

创建名称为 ceph-secret-admin 的 Secret
ceph-secret-admin.yaml文件如下:

apiVersion: v1
kind: Secret
metadata:
  name: ceph-secret-admin
  namespace: kube-system
type: "kubernetes.io/rbd"  
data:
  key: QVFCS3FYSmFRa05wSEJBQWxIRkgrR1NMQ1B3TzNXS2V2YUlMVkE9PQ==

2.2 创建 rbd-storage-class

通过 StorageClass RBD Config Example 官方示例代码,我们可以看到如下信息。

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: fast
provisioner: kubernetes.io/rbd
parameters:
  monitors: 10.16.153.105:6789
  adminId: admin
  adminSecretName: ceph-secret
  adminSecretNamespace: kube-system
  pool: kube
  userId: kube
  userSecretName: ceph-secret-user
  fsType: ext4
  imageFormat: "2"
  imageFeatures: "layering"

这里每个字段我就不一一解释了,其中有几个字段要说明一下:

  • provisioner: 该字段指定使用存储卷类型为 kubernetes.io/rbd,注意 kubernetes.io/ 开头为 k8s 内部支持的存储提供者,不同的存储卷提供者类型这里要修改成对应的值。
  • adminId | userId: 这里需要指定两种 Ceph 角色 admin 和其他 user,admin 角色默认已经有了,其他 user 可以去 Ceph 集群创建一个并赋对应权限值,如果不创建,也可以都指定为 admin。
  • adminSecretName: 为上边创建的 Ceph 管理员 admin 使用的 ceph-secret-admin。secret中必须要有“kubernetes.io/rbd”这个type。
  • adminSecretNamespace 管理员 secret 使用的命名空间,默认 default。
  • imageFormat: Ceph RBD image format, “1” or “2”. Default is “1”.
    • 经过查看ceph文档rbd 块镜像有支持两种格式: --image-format format-id,format-id取值为1或2,默认为 2。
      – format 1 - 新建 rbd 映像时使用最初的格式。此格式兼容所有版本的 librbd 和内核模块,但是不支持较新的功能,像克隆。
      – format 2 - 使用第二版 rbd 格式, librbd 和 3.11 版以上内核模块才支持(除非是分拆的模块)。此格式增加了克隆支持,使得扩展更容易,还允许以后增加新功能。
  • imageFeatures: This parameter is optional and should only be used if you set imageFormat to “2”. Currently supported features are layering only. Default is “”, and no features are turned on.

参照上边示例,我们创建一个 rbd-storage-class.yaml 文件如下。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: rbd
provisioner: kubernetes.io/rbd
parameters:
  monitors: 10.142.21.21:6789,10.142.21.22:6789,10.142.21.23:6789
  adminId: admin
  adminSecretName: ceph-secret-admin
  adminSecretNamespace: kube-system
  pool: rbd
  userId: admin
  userSecretName: ceph-secret-admin
  fsType: ext4
  imageFormat: "1"

说明:

然后我们创建一下名称为 rbd 类型为 rbd 的 storage-class 看下:

$ kubectl create -f rbd-storage-class.yaml 
storageclass "rbd" created
$ kubectl get storageclass
NAME      TYPE
rbd       kubernetes.io/rbd

3. 创建 pvc

现在 storageClass 已经创建好了,这里跟之前的区别就是,不需要创建 PV 和提前创建好指定大小的 Image,只需要创建 PVC 时请求指定存储大小就行,k8s 会根据请求存储大小和类型动态创建并分配,是不是很方便。那么我们就来创建一个 PVC 申请 1G 存储空间,新建 rbd-pvc.yaml 文件如下。

$ vim rbd-pv.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: rbd-pvc1
  namespace: kube-system
spec:
  storageClassName: rbd
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

注意:
这里要使用 storageClassName: rbd 指明我们使用的 storageClass 为前面创建的 rbd。accessModes 指定模型为 ReadWriteOnce rbd 只支持 ReadWriteOnce 和 ReadOnlyMany,因为下边有写入操作,所以这里使用 ReadWriteOnce 即可。

然后创建一个PVC:

$ kubectl create -f rbd-pvc.yaml 
    persistentvolumeclaim "rbd-pvc1" created

$ kubectl get pvc -n kube-system
NAME        STATUS    VOLUME                                     CAPACITY   ACCESSMODES   STORAGECLASS         AGE   
rbd-pvc1    Bound     pvc-b9ecad19-07bc-11e8-a9ca-00505694eb6a   1Gi        RWO           rbd                  2m

还自动创建出pv:
kubectl get pv
NAME                                       CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS    CLAIM                                           STORAGECLASS               REASON    AGE
pvc-b9ecad19-07bc-11e8-a9ca-00505694eb6a   1Gi        RWO           Delete          Bound     kube-system/rbd-pvc1                            rbd                                  5m

用rbd命令查看:

我们会发现,没有提前创建好 1G 大小的 rbd image,而是创建 PVC 时申请了 1G 存储,k8s 就自动创建好了指定大小的 Image。

此时相当于执行了rbd create,还没有把这个image 映射到内核,并格式化为块设备。

4. 创建应用

这一步相当于在pod所在的节点执行了rbd mapmkfsmount

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-use-rbd
  namespace: default
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.11.4-alpine
        imagePullPolicy: IfNotPresent
        name: nginx-use-rbd
        volumeMounts:
        - mountPath: /test
          name: rbd-pvc
      volumes:
      - name: rbd-pvc
        persistentVolumeClaim:
          claimName: rbd-pvc1
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-use-rbd
  namespace: default
spec:
  type: NodePort
  ports:
  - name: nginx-use-rbd
    port: 80
    targetPort: 80
    nodePort: 30099
  selector:
    app: nginx

创建成功后在kubelet日志中看到如下内容:

df -h 可以看到盘挂载上来了:

dmesg | tail可以看到:

并挂载到容器内部,太方便了有木有! 同时,我们看到默认使用的 format 为 1,这里也可以指定格式为 2(需要高版本的ceph和rbd支持),然后可以在 rbd-storage-class.yaml 中指定 imageFormat: “2”,同时还可以指定 imageFeatures: layering 等等。

最后,要提一下的是,如果我们使用动态配置的卷,则默认的回收策略为 “删除”。这意味着,在默认的情况下,当 PVC 被删除时,基础的 PV 和对应的存储也会被删除。如果需要保留存储在卷上的数据,则必须在 PV 被设置之后将回收策略从 delete 更改为 retain。可以通过修改 PV 对象中的 persistentVolumeReclaimPolicy 字段的值来修改 PV 的回收策略。

5. 问题

  • ceph-rbd的ReadWriteOnce问题

    ceph-rbd只支持RWO和RWM,也就是说写数据的话rbd只能挂给一个node,当一个应用只有一个pod实例的时候还好,当有多个pod实例的时候就要求这些实例一定要起在同一个节点上。实验发现,创建多实例应用不做啥约束的话,k8s的调度系统并不会根据这个应用所挂载的pvc类型是RWO而给你去把所有pod实例调度到同一个节点,最终结果甚至会一个pod也创建不出来,这个issue:https://github.com/kubernetes/kubernetes/issues/26567

参考:

1.http://blog.csdn.net/aixiaoyang168/article/details/79120095
2.https://kubernetes.io/docs/concepts/storage/storage-classes/#ceph-rbd

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器