kubernets使用ceph-rbd作为storageclass并创建pvc和应用

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

当然除了上述 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==
  • 1
  • 2

创建名称为 ceph-secret-admin 的 Secret。

$ vim ceph-secret-admin.yaml
apiVersion: v1
kind: Secret
metadata:
  name: ceph-secret-admin
  namespace: kube-system
type: "kubernetes.io/rbd"  
data:
  key: QVFCS3FYSmFRa05wSEJBQWxIRkgrR1NMQ1B3TzNXS2V2YUlMVkE9PQ==
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
$ kubectl create -f ceph-secret-admin.yaml 
secret "ceph-secret-admin" created
  • 1
  • 2

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"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

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

  • 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"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

说明:

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

$ kubectl create -f rbd-storage-class.yaml 
storageclass "rbd" created
$ kubectl get storageclass
NAME      TYPE
rbd       kubernetes.io/rbd
  • 1
  • 2
  • 3
  • 4
  • 5

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

注意: 
这里要使用 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

用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: kube-system
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
      nodeSelector:
        kubernetes.io/hostname: k8smaster01
      tolerations:
      - key: "master"
        operator: "Equal"
        value: "true"
        effect: "NoSchedule"
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-use-rbd
  namespace: kube-system
spec:
  type: NodePort
  ports:
  - name: nginx-use-rbd
    port: 80
    targetPort: 80
    nodePort: 30099
  selector:
    app: nginx
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

创建成功后在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.youkuaiyun.com/aixiaoyang168/article/details/79120095 
2.https://kubernetes.io/docs/concepts/storage/storage-classes/#ceph-rbd

<think>好的,用户现在问的是关于Ceph创建StorageClass是否支持多个应用独立动态申请PVC的问题。之前我已经解释了云盘(比如阿里云云盘)的情况,说明它们不支持多个应用同时挂载,但用户提到了Ceph,这需要进一步分析。 首先,我需要确认Ceph的存储类型。Ceph通常提供块存储(RBD)、文件存储(CephFS)对象存储(RGW)。其中,RBD对应块存储,而CephFS是文件存储。块存储文件存储在Kubernetes中的行为不同。 用户提到的是通过Ceph创建StorageClass支持多个应用动态申请PVC。这时候要区分使用的是RBD还是CephFS。如果是RBD,默认情况下,RBD的访问模式是ReadWriteOnce,即每个PVC只能被一个Pod挂载,这之前提到的云盘类似。但Ceph可能有一些机制允许共享,比如通过多挂载选项,但这通常需要特定的配置,可能不是默认行为。 不过,用户提到的是“独立动态申请PVC”,这可能意味着每个应用都有自己的PVC,但可能希望这些PVC共享同一个存储后端。这里需要明确动态Provisioning的工作机制:每个PVC会动态创建一个PV,对应Ceph中的一个块设备(如果是RBD)。因此,每个PVC对应独立的存储空间,而不是共享同一块设备。这种情况下,应用之间数据是隔离的,但都能独立申请存储资源。 如果用户的需求是多个应用共享同一块存储,那么可能需要使用CephFS,因为它支持ReadWriteMany(RWX)模式,允许多个Pod同时挂载同一个文件系统。此时,StorageClass配置为CephFS的provisioner,PVC申请时会动态创建存储卷,且多个PVC可以指向同一个存储后端,或者每个PVC对应不同的子目录,实现共享或独立使用。 另外,需要检查用户是否混淆了“多个PVC“共享存储”。动态申请PVC通常意味着每个PVC都是独立的存储资源,而共享存储需要特定的配置,如使用同一个PVCStorageClass支持RWX。 可能的误解点:用户可能认为动态申请PVC就能自动共享存储,但实际上这取决于存储类型访问模式。CephRBD默认不支持RWX,而CephFS支持。因此,需要明确用户使用Ceph存储类型。 总结回答步骤: 1. 确认Ceph的存储类型(RBDCephFS)。 2. 解释不同存储类型在Kubernetes中的行为。 3. 说明动态Provisioning时,每个PVC是否独立或共享。 4. 提供配置示例适用场景。 5. 澄清用户可能的误解,确保正确理解PVC存储类型的关系。</think>--- ### **一、核心结论** **Ceph创建StorageClass可以支持多个应用独立动态申请PVC,但具体行为取决于Ceph存储类型(RBDCephFS)访问模式配置**: 1. **若使用Ceph RBD(块存储)**: - 默认支持`ReadWriteOnce`(单Pod读写),但通过特殊配置可实现**静态绑定共享同一RBD镜像**(需手动操作,非动态特性)。 - 动态申请的PVC会为每个应用创建独立的RBD镜像(独立存储空间),**数据隔离,无共享**。 2. **若使用CephFS(文件存储)**: - 天然支持`ReadWriteMany`(多Pod读写),动态申请的PVC可共享同一文件系统(不同子目录或相同路径),**数据可共享或隔离**。 --- ### **二、详细分析** #### **场景1:Ceph RBD(块存储)** | 配置方式 | 共享能力 | 动态PVC行为 | 适用场景 | |-------------------|----------|-------------|------------------------| | **默认动态申请** | ❌ 隔离 | 每个PVC创建独立RBD镜像 | 单Pod读写场景(如数据库) | | **手动静态共享** | ⚠️ 有限共享 | 需提前创建RBD镜像绑定为PV,允许多PVC以`ReadOnly`挂载 | 多Pod只读同一数据(如配置文件) | **关键限制**: - RBD动态PVC默认无法实现多Pod共享写入(需额外工具如`rbd-nbd`或内核支持发挂载,但Kubernetes原生不支持)。 - 若强行配置多Pod挂载同一RBD镜像,可能导致数据损坏(块存储无发控制)。 #### **场景2:CephFS(文件存储)** | 配置方式 | 共享能力 | 动态PVC行为 | 适用场景 | |-------------------|----------|-----------------------------------------|------------------------| | **动态申请PVC** | ✅ 共享 | 所有PVC共享同一文件系统,通过子目录隔离 | 多应用共享存储(如日志、媒体文件) | | **独立子目录** | ✅ 隔离 | 每个PVC分配独立子目录,存储空间按需分配 | 多租户环境 | **优势**: - 支持`ReadWriteMany`,多Pod可发读写。 - 存储配额可通过CephFS子目录配额功能实现。 --- ### **三、配置示例** #### **1. Ceph RBD动态PVC(独立存储)** ```yaml # StorageClass定义(RBD块存储) apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: ceph-rbd provisioner: rbd.csi.ceph.com parameters: clusterID: <ceph-cluster-id> pool: rbd imageFeatures: layering csi.storage.k8s.io/provisioner-secret-name: ceph-secret csi.storage.k8s.io/node-stage-secret-name: ceph-secret reclaimPolicy: Delete allowVolumeExpansion: true mountOptions: - discard ``` **行为**: - 每个PVC动态创建一个RBD镜像(如`pvc-xxxxx`),挂载到单个Pod。 #### **2. CephFS动态PVC(共享存储)** ```yaml # StorageClass定义(CephFS文件存储) apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: cephfs provisioner: cephfs.csi.ceph.com parameters: clusterID: <ceph-cluster-id> fsName: my-cephfs pool: my-cephfs-metadata subvolumeGroup: my-group reclaimPolicy: Delete allowVolumeExpansion: true ``` **行为**: - 每个PVC动态创建CephFS子卷(位于同一文件系统),多Pod可挂载同一PVC实现共享。 --- ### **四、特殊场景:RBD镜像共享(非动态特性)** 若需多Pod共享同一RBD镜像(非Kubernetes原生支持),需手动操作: 1. **创建RBD镜像**: ```bash rbd create my-shared-image --size 1024 --pool rbd ``` 2. **定义静态PV**: ```yaml apiVersion: v1 kind: PersistentVolume metadata: name: shared-rbd-pv spec: capacity: storage: 1Gi accessModes: - ReadWriteMany # 实际需Ceph内核支持! csi: driver: rbd.csi.ceph.com volumeHandle: my-shared-image nodeStageSecretRef: name: ceph-secret persistentVolumeReclaimPolicy: Retain ``` 3. **风险**: - 需内核支持发挂载RBD镜像(`exclusive-lock``journaling`功能)。 - 数据一致性需应用层保障,可能引发冲突。 --- ### **五、关键总结** | 存储类型 | 共享能力 | 动态PVC支持 | 适用场景 | |----------------|---------------|-------------|------------------------------| | **Ceph RBD** | ❌ 单Pod读写 | ✅ 独立存储 | 数据库、单节点应用 | | **CephFS** | ✅ 多Pod读写 | ✅ 共享/隔离 | 日志收集、多应用共享存储 | --- ### **六、运维建议** 1. **明确需求选择存储类型**: - 需共享存储时优先使用CephFS,避免强用RBD。 2. **监控存储配额**: - CephFS动态PVC需配置子目录配额,防止单一应用耗尽存储。 3. **数据一致性保障**: - 共享存储场景中,应用需处理文件锁或冲突(如使用NFSv4协议特性)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值