您的位置:首页 > 其它

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

2018-02-01 16:08 1096 查看

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。

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


$ kubectl create -f ceph-secret-admin.yaml
secret "ceph-secret-admin" created


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"


说明:

我的ceph和rbd版本是10.2.10,不支持
--image-feature
,所以必须将imageFormat设为1,并且不设置imageFeatures参数。相关issue见:

https://github.com/kubernetes/kubernetes/issues/50522

https://github.com/kubernetes-incubator/kubespray/issues/1959

然后我们创建一下名称为 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 map
mkfs
mount


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


创建成功后在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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ceph kubernetes 存储