由于业务需要,目前ceph已经上线并进行了业务的承载,运行还算稳定,趁机整改了一下集群自动化相关的东西
写在前面
松鼠哥的ceph专业课程上线啦!
面向新手同学,从0实战,全面入门ceph安装部署与运维,有需要的同学赶紧联系松鼠哥订购吧:
生产环境与测试环境集群搭建有所不同,生产环境更讲究高效、后续运维易管理维护等。
需求提出
目前我们使用的是磁盘柜+服务器的方式使用ceph集群,具体配置为:
- 联想D3284磁盘柜,每个柜子84个磁盘槽位,插满10TB硬盘,共840TB,单集群两个磁盘柜
- 联想服务器,24盘位,插满intel ssd磁盘
- 服务器之间使用IB卡,40Gb的网络能力,集群私网接入同一个交换机,开启巨帧模式
硬件配置上看,集群安排还算可以,集群一共176个osd,8个ssd osd加168个hdd osd,建集群的时候发现,每个hdd osd建立时间很长,我们使用的是ceph-deploy起的osd,每个osd大概需要1分24秒才建立完成,集群168个hdd osd的情况下,建一次集群(上线前进行过几次测试,所以会有重装过程,后续上线其他集群或者集群更迭都会有重装场景)差不多要4个小时,加上集群建立后的配置,比如crushmap的定制、pg的均衡调整等,一趟下来要5-6个小时,不能忍!
踩坑前行-试验
使用ceph-deploy起osd的好处是,很多操作不需要我们一个个去手工实现,并且在指定各个分区之后也不用担心大小问题,但是,我们集群建立慢主要的原因是创建osd数量太多,导致创建时间长,那么,能不能每个osd节点同时创建osd呢?为了避免osd-id顺序不一致或者其他问题,我们通过指定osd-id的方式来创建osd,不就能实现同时创建了?
带着这样的想法,查阅了不少资料,都没有太多有用的信息,官方那边提供的可以指定osd id 的方法简直不能太挫,ceph osd create {id}
这种方式根本就不是我们需要的创建方式,ceph-deploy并不支持使用指定osd id的方式进行创建,几经搜索,发现ceph-volume可以使用–osd-id的方式指定osd id
关于–osd-id的参数说明,在命令行的说明是这样的
1 | [cephfsd@ceph-201 ceph-deploy]$ ceph-volume lvm create -h |
Reuse一个已经存在的osd id,我的天!这是什么操作?重新使用一个已经存在的osd id?愚钝的我人为,这个osd id应该是曾经被用过但是现在这个osd已经被清除掉了,所以才会说是重新使用
使用ceph-volume命令多次进行测试–osd-id参数,没有什么作用啊,该参数在指定osd的情况下表现为:
- 此osd已经存在,例如已经有osd.0 ,指定–osd-id 0 ,显然创建失败
- 此osd已经存在但是处于destroyed状态,创建也会失败
- 此osd不存在,指定–osd-id也会失败,此时会使用集群分配的最小osd id值
- 此osd曾经存在但是被清除了,创建同样失败,指定的osd id不能生效
***,不管osd id 在什么情况下都不能成功指定osd-id进行创建,那这个参数有什么意义?难道要就此罢手?不行!
踩坑前行-看源码
测试了两天没有什么进展,看看ceph-deploy的源码,发现了一线生机。
首先解决了一个坑,在使用如下脚本进行集群初始化后,直接使用ceph-volume创建osd会失败,原因是/var/lib/ceph/bootstrap-osd/ceph.keyring
不存在,在使用ceph-deploy创建osd的时候,如果发现此文件不存在,会自动创建
1 |
|
ceph-deploy的输出显示该文件不存在就会创建
1 | [2018-07-04 18:21:36,663][ceph-201][WARNING] osd keyring does not exist yet, creating one |
这里通过查看ceph-deploy发现它就是对/var/lib/ceph/bootstrap-osd/ceph.keyring
写入key,所以这里在初始化集群的时候顺便把key写入该文件就可以了,之所以要这么搞清楚它的过程,是因为手工使用ceph-volume创建osd的时候,不知道它除了拷贝key文件之外,还会不会有其他的配置操作
根据ceph-deploy的输出,定位到ceph-volume的源码位置,调查了一下关于–osd-id的相关过程,它的github位置为prepare.py,定位到50行,它在创建osd前创建一个osd id
1 | def create_id(fsid, json_secrets, osd_id=None): |
注意到第18行,它使用了check_id()方法检查指定的osd id 能不能用,如果可以用,就将该id放入到cmd中,后续执行的时候,就会使用该id进行osd的创建,我们再来看看这个check_id()方法
1 | def check_id(osd_id): |
可以看到,它使用ceph osd tree的方式获取当前集群已经存在的osd id,然后通过比对,看看指定的id是否已经被使用,注意到最后的any()方法,这个方法专门查了一下,只要参数中有一个为True,就返回True,而除了是 0、空、FALSE 外都算True,也就是说,any()中的列表推倒是有问题的
,假如当前集群存在osd.0,指定–osd-id为0,这里就会返回True,那么0就会被加入到创建参数中,当然,后续创建工作会识别出0已经被使用而导致创建失败,但是这里的逻辑就有问题了,假如指定的–osd-id是不存在集群中的,这里的列表推倒就会返回False,check_id()返回将不会使用指定的osd-id,这也不是正常的逻辑,因此,check_id()方法是有逻辑问题的
,使用any()看起来并不合理,给社区提个bug?
问题的解决
综上,使用ceph-volume指定–osd-id参数创建osd失败其实是ceph-deploy的bug导致,由于我们的环境中,每个节点创建的osd数是提前知道的,所以这边的处理方案是对check_id()方法进行修改,使得其总是返回True,即总是认为指定的osd-id是可用的(内部使用,不适用一般场景)
1 | 修改本地的prepare文件: |
经过测试,指定的osd可以正常创建并使用,如果使用手工创建osd,可能还要手动将其加入crushmap中,当前的创建脚本参考:
1 |
|
可以配置从哪个id开始创建osd,一共创建几个osd
- 本文作者: 奋斗的松鼠
- 本文链接: http://www.strugglesquirrel.com/2018/07/15/多节点同时创建osd踩坑纪要/
- 版权声明: 本博客所有文章除特别声明外,创作版权均为作者个人所有,未经允许禁止转载!