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

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

2. CephFS配置Quotas

CephFS的mount方式分为内核态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  /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=
dd: error writing ‘test1.bin’: Disk quota exceeded
+ records in
+ records out
bytes ( MB) copied, 0.428233 s, MB/s # df -h
Filesystem Size Used Avail Use% Mounted on
ceph-fuse 92M -64Y -36M % /mnt/cephfs

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

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

# dd if=/dev/zero of=test2.bin bs=1M count=
dd: error writing ‘test2.bin’: Disk quota exceeded
+ records in
+ records out
bytes ( 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中创建访问Ceph的Secret的步骤见《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.
volumeMounts:
- name: cephfs
mountPath: "/data/"
volumes:
- name: cephfs
cephfs:
monitors:
- 10.32.3.70:
- 10.32.3.71:
- 10.32.3.72:
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:,10.32.3.71:,10.32.3.72::/k8s_test
.2T .1G .2T % /data

5. Kubernetes Persistent Volume使用CephFS

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

# echo 'apiVersion: v1
kind: PersistentVolume
metadata:
name: nginx-test-cephfs-pv-
namespace: test
spec:
capacity:
storage: 100Mi
accessModes:
- ReadWriteMany
cephfs:
monitors:
- 10.32.3.70:
- 10.32.3.71:
- 10.32.3.72:
path: /k8s_test
user: k8s
secretRef:
name: ceph-k8s-secret
readOnly: false
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nginx-test-cephfs-pvc-
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 50Mi
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-test-cephfs-
spec:
containers:
- name: nginx-test-cephfs
image: registry.exmaple.com/base/nginx:v1.
volumeMounts:
- name: cephfs-vol1
mountPath: "/data/"
volumes:
- name: cephfs-vol1
persistentVolumeClaim:
claimName: nginx-test-cephfs-pvc-' | 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:,10.32.3.71:,10.32.3.72::/k8s_test
.2T .1G .2T % /data

6. Kubernetes StorageClass使用CephFS

Kubernetes StorageClass原生不支持CephFS,但是在社区的孵化项目External Storage中添加了CephFS类型的StorageClass。External 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:,10.32.3.71:,10.32.3.72:
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-
annotations:
volume.beta.kubernetes.io/storage-class: "cephfs"
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 100Mi’ | kubectl create -f -

6) 创建使用PVC的Pod

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

7) 查看容器状态

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

7. 为CephFS StorageClass添加Quotas支持

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

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

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

1) 修改CephFS external provisioner

CephFS external provisioner的结构比较简单,主要就是cephfs-provisioner.go和cephfs_provisioner.py两个文件。cephfs-provisioner.go是主程序,创建CephFS Provisioner。cephfs_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.go的execFuseMount()函数,原来的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- -it -- /bin/bash
root@nginx-test-cephfs-:/# df -h
Filesystem Size Used Avail Use% Mounted on
ceph-fuse 100M 100M % /data

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

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

Quota确实生效了。

参考资料

CephFS Admin Tips – Create a new user and share

kubernetes笔记: Cephfs

Kubernetes添加带Quota限额的CephFS StorageClass的更多相关文章

  1. 百度地图API 批量添加 带检索功能的信息窗口

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. 烂泥:puppet添加带密码的用户

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 前一篇文章,我们介绍了有关puppet3.7的安装与配置,这篇文章我们再来介绍下如何利用puppet添加带密码的用户. 要通过puppet添加带密码的用 ...

  3. [转帖]vagrant 添加带版本号的 box

    vagrant 添加带版本号的 box https://www.jianshu.com/p/12cf1ecb224b 第三种好用 lnmpcomposerphp  阅读约 8 分钟 前言 众所周知,v ...

  4. 在word2010中添加带滚动条的文本框

    由于文件内容过长,为了加强文章的可读性,可以添加一个带滚动条的文本框,既能使文章看起来干净整洁,同时也极大的提高了文章的可读性. 我这里对在word2010中文本框带滚动条作个介绍: 1. 打开wor ...

  5. 百度API的经历,怎样为多个点添加带检索功能的信息窗口

    不管我们要做什么样的效果,APIKey(密钥)都是不可缺少的要件,所以我们需要先去百度申请我们的APIKey!!! 伸手党,请直接到页面底部获取完整代码! 最近做一个门店查询的内容展示,考虑到用户直观 ...

  6. 右键菜单添加带图标的Notepad++

    给Notepad++ 加带图标右键菜单 方式一: 拷贝以下代码建立一个reg文件,替换相关路径,保存,双击运行加入注册表 Windows Registry Editor Version 5.00 [H ...

  7. 【kubernetes 自带监控】 container级别cadvisor+kubelet,集群级别apiserver

    apiserver https://feisky.gitbooks.io/kubernetes/components/apiserver.html kube-apiserver 支持同时提供 http ...

  8. kubernetes(14):k8s基于NFS部署storageclass实现pv自动供给

    k8s基于NFS部署storageclass实现pv自动供给 https://www.cnblogs.com/Smbands/p/11059843.html https://www.jianshu.c ...

  9. vagrant 添加带版本号的 box

    众所周知,vagrant添加box的时候要从外网下载,那速度...(说多了都是泪),所以只好用下载工具下载到本地之后再添加. 如何搭建 homestead:https://laravelacademy ...

随机推荐

  1. java实现定时任务(Quartz)

    java中实现定时任务执行某一业务.具体操作如下: 1.定义初始化任务 2.任务业务操作 3.定义初始化方法 4.在web.xml中注册启动 5.定义具体执行时间 6.quartz定时任务时间设置 q ...

  2. android中AudioRecord使用

    一 什么是音频的采样率和采样大小 自然界中的声音非常复杂,波形极其复杂,通常我们采用的是脉冲代码调制编码.即PCM编码.PCM通过抽样.量化.编码三个步骤将连续变化的模拟信号转换为数字编码. 抽样:在 ...

  3. jQuery知识重构

    jQuery知识重构 目录: 一.入口函数 1          $(document).ready(function(){}); 2          $(function(){}); jQuery ...

  4. 页面中引入百度地图,实例化后影响html5的表单元素date的上下箭头

    复现步骤: 使用百度地图的JavaScript的API,引入文件地址"http://api.map.baidu.com/api?key=&v=1.1&services=tru ...

  5. 云中(云厂商)抗DDoS究竟哪家强?

    随着云计算的兴起,大量资源触手可得,这让DDoS攻击的成本断崖般下降,而人们对于互联网服务的可靠性要求又在不断加强,这就使得DDoS攻击所造成的破坏力与日俱增.面对日趋严重的网络安全形势,企业传统的见 ...

  6. SqlServer Alwayson 搭建排错记录(二)

    下面记录下建立好alwayson可用性组后,向可用性组内添加数据库出现过的问题及解决方法 一.数据库未处于恢复状态 将数据库联接到可用性组的时候报错: 数据库“XXXX”未处于恢复状态,而此状态是镜像 ...

  7. 05、Win7上openSSH的安装与配置

    05.Win7上openSSH的安装与配置 1.概述 linux上的ssh命令在网络通信场景下非常方便.现在windows也支持ssh方式和远程主机进行访问.如果只是使用ssh简单的访问功能,就需要很 ...

  8. [转贴] ASP.NET -- Web Service (.asmx) & JSON

    [转贴] ASP.NET -- Web Service (.asmx) & JSON 以前没做过,但临时被要求 ASP.NET Web Service 要传回 JSON格式 找到网络上两篇好文 ...

  9. pta 编程题6 树的同构

    其它pta数据结构编程题请参见:pta 题目请参见:树的同构 因题目中左右子树是按照下标给出,因此用数组存放树是更好的方法. 判断两棵树是否同构:用递归的方法.如果当前两个结点都为空,则返回TRUE: ...

  10. POJ 3046 Ant Counting(递推,和号优化)

    计数类的问题,要求不重复,把每种物品单独考虑. 将和号递推可以把转移优化O(1). f[i = 第i种物品][j = 总数量为j] = 方案数 f[i][j] = sigma{f[i-1][j-k], ...