深入理解ceph-disk运行机制

谷忠言

一,背景

目前项目所用的ceph集群内部的一个节点, 一般需要管理大约十块硬盘左右的数据存储空间,外加一到两块ssd组成的journal空间。Ceph要求每个osd对应的数据盘挂载到特定的目录,对应的ssd的journal分区也不能加载错,否则osd 无法启动。

目前对于数据盘的挂载采用的是基于/etc/fstab的方式。

上图是某个节点的/etc/fstab的实例。/dev/slot* 是一个由diskctl_init.sh 脚本产生的从/dev/slot* 到/dev/sdx的映射。如下图所示。

 

Diskctl_init.sh的原理是生成的slot 与主板物理槽位磁盘接口形成固定映射,这样当盘符漂移的时候,/dev/slot* 始终对应物理槽位的磁盘。只要磁盘不插拔更换物理槽位,osd 就能加载正确的数据盘。

而对于ssd journal分区,则是直接采用的journalà盘符的裸映射。

 

存在的问题:

1.      Ssd journal分区的盘符裸映射, 有时候会导致机器重启,ceph服务起不来。测试发现,正是由于盘符漂移,裸映射成为死链。

2.      Diskctl_init.sh 生成的slot 映射, 据同事反映,也可能有潜在的问题。具体细节不详。

 

二,调研ceph-disk

Ceph-disk 是官方发布的一个用于部署osd 数据及journal分区或目录的工具。基于python.安装ceph rpm包将默认安装此工具,安装目录是/usr/sbin/ceph-disk。由于此工具涉及数据盘及journal盘的分区。需要root权限。

 

ceph-disk 是如何工作的?

通过ceph-disk 部署osd, 数据分区和journal 分区将自动挂载到正确的目录,机器重启也能保证工作。通过ceph-disk部署osd, 将大大提高ceph部署运维的自动化程度,并降低操作出错几率。

以新创建OSD为例,描述ceph-disk的工作机制。

分为两大步骤:prepare disk 和activate disk

假设/dev/sdg是OSD要使用的数据盘, /dev/sdk 是SSD, OSD要使用的journal分区在这里创建。则创建OSD 并上线的命令如下:

Ceph-disk prepare /dev/sdg /dev/sdk

Ceph-disk activate /dev/sdg1

下面详细深入其过程。

1.      准备journal分区。

Prepare_journal_dev()调用分区工具sgdisk从/dev/sdk上划分一块journal分区。

有以下注意要点:

a.      在调用sgdisk之前,prepare_journal_dev()会获取ceph.conf文件中指定的osd_journal_size大小,我们的ceph.conf指定大小如下:

 

b.      实际部署环境中,由于作为journal的ssd分区并不需要很大空间,所以一个ssd很可能被多个osd共享来划分各自的journal分区,我们的环境是,一个300G的ssd 划分成5个(甚至更多的)20G的分区,挂载成5个osd的journal.

c.      Ceph-disk 在部署journal分区的时候,能自动侦测SSD盘已有分区数,不破坏已有分区,分配不冲突的新分区号来创建分区。

d.      如果不指定创建分区的uuid,ceph-disk会自动为journal分区生成一个,称之为journal_uuid.

e.      在调用sgdisk的时候,还有一个重要的参数,--typecode. Ceph-disk 使用一个特殊的UUID 作为创建journal的typecode:

至于为何用此特殊UUID做typecode, 基本上此UUID可作为辨识分区为ceph journal的凭证,稍后深入解释。

至此,prepare_journal_dev()已经准备好了sgdisk所需的各个参数,下面给出一个实际发生的参数例子:

/usr/sbin/sgdisk --new=6:0:+20480M--change-name="6:ceph journal" --partition-guid=6:c6422c03-d320-4633-b35d-4f43c6cdd9fa--typecode=6:45b0969e-9b03-4f30-b4c6-b4b80ceff106 --mbrtogpt -- /dev/sdk

2.      在目录/dev/disk/by-partuuid/下为此journal分区创建link:

 

简单介绍一下这个link如何产生的。

在调用sgdisk 创建完journal分区后,ceph-disk 调用partx更新分区表,会触发一个块设备/分区udev event并通知到内核。Ceph编写了udev规则文件如下:

 

Udev daemon在收到由partx产生的udev event后,根据以上的ceph规则文件,将调用/usr/sbin/ceph-disk-udev脚本。正是在这个脚本里,在目录/dev/disk/by-partuuid/下为此journal分区创建了link。此脚本还有另外一个扫描OSD专属分区的功能,后文会提及。暂时不表。

 

这个link有什么用?

由于这个link是根据partition uuid生成的,可以把它看成是到特定journal分区的固定映射。后文会指出osd的journal将映射到此link:

 

由此图看出,位于osd 数据分区里的journal是一个link,指向一个固定的位置:/dev/disk/by-partuuid/c6422c03-d320-4633-b35d-4f43c6cdd9fa, 再由这个link指向真正的journal分区,由此解决的盘符漂移带来的问题。下文介绍的osd 数据分区的link也是基于此原理。

 

3.      准备OSD数据分区。

这个过程跟准备journal分区大体一样。区别在于:

a.      调用sgdisk 使用—largest-new来使用磁盘最大可能空间。所以/dev/sdg会有一个分区sdg1,它使用所有的空间。

b.      格式化/dev/sdg1。这里对ceph-disk做了小的定制,默认使用了ext4分区格式。

c.      将此分区mount到一个临时的目录,然后再其中创建一个名为journal的link,指向/dev/disk/by-partuuid/c6422c03-d320-4633-b35d-4f43c6cdd9fa。至此,OSD的journal分区映射完成。最后umount。

d.      再次调用sgdisk,写入一个重要的参数,--typecode. Ceph-disk 使用一个特殊的UUID 作为创建OSD的typecode:

同JOURNAL_UUID, 为何用此特殊UUID做typecode, 是因为此UUID可作为辨识分区为ceph OSD数据分区的凭证,稍后深入解释。

 

4.      在目录/dev/disk/by-partuuid/下为此OSD 数据分区创建link。

过程同journal的link创建过程。

 

5.      Activate过程。

Activate的命令是 ceph-disk activate /dev/sdg1。

但其实并不需要显式的调用这个命令。原因是,准备好OSD 数据分区后,udev event 触发了ceph-disk-udev。而ceph-disk-udev会自动调用ceph-disk activate /dev/sdg1。

下面介绍这个过程是如何自动化的。详情参见ceph-disk-udev脚本。

新的OSD 数据分区的生成,触发udev event, 通过ceph udev rule,最终调用ceph-disk-udev,分析该分区的typecode,发现是OSD_UUID,即表明是ceph OSD的数据分区,于是触发ceph-disk activate /dev/sdg1:

 

Typecode 为JOURNAL_UUID的情况也一样,只不过是通过ceph-disk activate-journal 来启动OSD.

在介绍ceph-disk activate /dev/sdg1的具体流程。

a.      将/dev/sdg1 挂载至临时目录,一般为var/lib/ceph/tmp/mnt.xxx

b.      分配OSD id,及调用ceph osd create 产生 osd id

c.      初始化OSD, 如ceph-osd –mkfs –osd-data –osd-journal

d.      根据osd id 重新挂载到最终目录: var/lib/{cluster}/osd/ceph-{osd.id}

e.      Service ceph start osd

对于osd id 已经存在,重启osd的case,也会用到ceph-disk activate,这种情况稍有不同,不需要产生新的osd id,只需要将/dev/sdg1挂载至临时目录,获取osd id后,重新挂载到最终目录。

 

Ceph-disk 支持的其他命令如下:

    prepare             Prepare a directory or disk for aCeph OSD

    activate            Activate a Ceph OSD

    activate-journal    Activate an OSD via its journal device

    activate-all        Activate all tagged OSD partitions

    list                List disks, partitions, and CephOSDs

    suppress-activate   Suppress activate on a device (prefix)

    unsuppress-activate

                        Stop suppressingactivate on a device (prefix)

    zap                 Zap/erase/destroy a device'spartition table (and

                        contents)

特别强调几点:

a.      Suppress的字面意思就是抑制,用在这里的意图主要是,如果只想prepare各个分区,暂时不想activate OSD(创建osd 上线),可以使用此命令,等到所有的分区都prepare好了,unsuppress 一把,再activate-all.

b.      Activate-journal 是通过制定journal 分区来启动osd, 如:ceph-diskactivate-journal /dev/sdk6. Ceph-disk 执行的流程为:

通过 ceph-osd -i 0 --get-journal-uuid --osd-journal /dev/sdk6 返回osd_uuid. 有了osd_uuid,就能找到osd 数据分区了,即定位/dev/disk/by-partuuid/$osd_uuid,这样就回到了使用osd 数据分区来activate的命令逻辑,即ceph-disk activate /dev/sdg1。

这里要解释 为什么是ceph-osd-i 0?在此条命令中, -i 后面可以跟任何一个整数,在get-journal-uuid中会被忽略。但问题是,不加-i, ceph-osd格式检查就会报错。

还有就是—get-journal-uuid,字面意思好像是获取journal分区的uuid,但实际上返回的一个叫journal.header 结构体里的fsid. 此fsid的值就是 osd 数据分区的uuid. 所以命令ceph-osd -i 0 --get-journal-uuid --osd-journal /dev/sdk6 返回值是osd_uuid。不得不抱怨一把,这个命令太容易让人产生混乱。理清逻辑是从源码中分析得来的。从这个小问题可以看出开源软件比起商业软件,细处略显粗糙,还需精细打磨。

 

c.      如果prepare不显式指定 journal, 如 ceph-disk prepare /dev/sdg, 则处理逻辑为:

在sdg上划出两个分区,sdg2 为20G的journal分区,sdg1为剩下空间大小的osd 数据分区。

 

 

 

注意事项

Ceph-disk的定制:

1.      default fstype ext4

2.      keyring的问题,由于目前的ceph部署没有enablekeyring,所以屏蔽了相关代码。

ceph-disk –v将打印更详细的log, 如果想深入理解ceph-disk命令的运行过程,此参数非常有效。

权限问题:

chmod -R 777/home/ceph/software/ceph/var/lib/ceph/osd/ceph-*

删除OSD产生的死链问题。

posted @ 2017-10-26 16:19  多看多学多记多实践  阅读(5097)  评论(0编辑  收藏  举报