导语
本文将全面详细介绍如何搭建如图1所示的集群。
图1
环境
3台装有CentOS 7的主机,每台主机有5个磁盘(虚拟机磁盘要大于30G),具体虚拟机搭建可以查看虚拟机搭建 , 目前已经有了3个2T的盘,再在每个节点添加一个240G的盘,假装是一个用作journal的SSD,和一个800G的盘,假装是一个用作OSD的SSD。另外再添加1台装有CentOS 7的主机,用作ntp server和ceph本地源,详细信息如下:
集群配置如下:
主机 | IP | 功能 |
---|---|---|
ceph-1 | 192.168.56.100 | deploy、mon1、osd3 |
ceph-2 | 192.168.56.101 | mon1、 osd3 |
ceph-3 | 192.168.56.102 | mon1 、osd3 |
ceph-admin | 192.168.56.200 | ntp server、 ceph本地源 |
环境清理
如果之前部署失败了,不必删除ceph客户端,或者重新搭建虚拟机,只需要在每个节点上执行如下指令即可将环境清理至刚安装完ceph客户端时的状态!强烈建议在旧集群上搭建之前清理干净环境,否则会发生各种异常情况。
Ceph本地源的搭建
这一节有以下3个目的:
- 对于不能访问外网的集群,必须在内网搭建好ceph源。
- 对于使用非最新(0.94.9)小版本(0.94.7)的ceph,搭好本地源方便后续增加节点。
- 做实验的话,有了本地源,搭环境速度会快很多。
写本文时,ceph的最新版本为10.2.3,现在在ceph-admin节点搭建一个10.2.2的本地源。
在ceph-admin节点安装httpd和createrepo: yum install httpd createrepo -y
创建ceph源目录,并下载所有文件,方法其实很简单,选择并下载你需要安装的ceph版本,这里选择的是/rpm-jewel/el7/x86_64/,然后把所有的包含10.2.2的rpm包都下下来,除了那个ceph-debuginfo,1G多太大了,可以不下。最后再加上ceph-deploy的rpm链接,这里你只需要复制粘贴就好了:
代码语言:javascript复制mkdir-p /var/www/html/ceph/10.2.2
cd /var/www/html/ceph/10.2.2
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/ceph-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/ceph-base-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/ceph-common-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/ceph-devel-compat-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/ceph-fuse-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/ceph-libs-compat-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/ceph-mds-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/ceph-mon-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/ceph-osd-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/ceph-radosgw-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/ceph-selinux-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/ceph-test-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/cephfs-java-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/libcephfs1-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/libcephfs1-devel-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/libcephfs_jni1-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/libcephfs_jni1-devel-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/librados2-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/librados2-devel-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/libradosstriper1-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/libradosstriper1-devel-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/librbd1-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/librbd1-devel-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/librgw2-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/librgw2-devel-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/python-ceph-compat-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/python-cephfs-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/python-rados-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/python-rbd-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/rbd-fuse-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/rbd-mirror-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/rbd-nbd-10.2.2-0.el7.x86_64.rpm
wget http://mirrors.aliyun.com/ceph/rpm-hammer/el7/noarch/ceph-deploy-1.5.36-0.noarch.rpm
创建源并添加ceph.repo:
记得开启httpd服务:systemctl start httpd
这样就在ceph-admin节点上搭建好了10.2.2源,其他的ceph-1/2/3节点只需要把ceph.repo拷贝过去就可以安装了ceph了。暂时没找到别的简单的方法,我制作本地源的最初目的就是为了虚拟机里面安装能快一点。
yum源及ceph的安装
需要在每个节点(ceph-1/2/3)上执行以下指令
增加ceph的源
代码语言:javascript复制scp ceph-admin:/etc/yum.repos.d/ceph.repo /etc/yum.repos.d/
安装ceph客户端和ntp:
代码语言:javascript复制yum makecache
yum install ceph ceph-radosgw ntp -y
关闭selinux&firewalld
代码语言:javascript复制sed-i 's/SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
setenforce 0
systemctl stop firewalld
systemctl disable firewalld
配置NTP
这里我把NTPserver放在了ceph-admin节点上,其余三个ceph-1/2/3节点都是NTP client,目的就是从根本上解决时间同步问题。(暂时没有server的)
在ceph-admin节点上: 修改/etc/ntp.conf,注释掉默认的四个server,添加三行配置如下:
修改/etc/ntp/step-tickers文件如下:
代码语言:javascript复制#List of NTP servers used by the ntpdate service.
# 0.centos.pool.ntp.org
127.127.1.0
重启ntp服务,并查看server端是否运行正常,正常的标准就是ntpq -p指令的最下面一行是*:
代码语言:javascript复制[root@ceph-admin~]# systemctl enable ntpd
Created symlink from /etc/systemd/system/multi-user.target.wants/ntpd.serviceto /usr/lib/systemd/system/ntpd.service.
[root@ceph-admin ~]# systemctl restart ntpd
[root@ceph-admin ~]# ntpq -p
remote refid st t when poll reach delay offset jitter
==============================================================================
*LOCAL(0) .LOCL. 0l - 16 1 0.000 0.000 0.000
至此,NTP server端已经配置完毕,下面开始配置client端。
在ceph-1/ceph-2/ceph-3三个节点上: 修改/etc/ntp.conf,注释掉四行server,添加一行server指向ceph-admin:
重启ntp服务并观察client是否正确连接到server端,同样正确连接的标准是ntpq -p的最下面一行以*号开头:
代码语言:javascript复制[root@ceph-1~]# systemctl enable ntpd
Created symlink from /etc/systemd/system/multi-user.target.wants/ntpd.serviceto /usr/lib/systemd/system/ntpd.service.
[root@ceph-1 ~]# systemctl restart ntpd
[root@ceph-1 ~]# ntpq -p
remote refid st t when poll reach delay offset jitter
==============================================================================
*ceph-admin .LOCL. 1u 1 64 1 0.329 0.023 0.000
这个过程不会持续太久,实际生产最久5min内也会达到*状态,下图给了一个未能正确连接的输出:
可以观察到ceph-admin前面是没有*的,一定要确定所有server和client端的NTP都正确连接才能继续搭建ceph ! ! !
OS参数配置方法
之所以写这一节,是因为网上查到的一些形如echo 4194303 > /proc/sys/kernel/pid_max的方法重启之后是不会生效的,所以这里提供了一种重启之后仍然生效的方法,注意只是方法,并不代表实际生产值要配置成这里的值。当然在VM里面搭建ceph不需要配置这些。
- 所有/proc/sys/*参数的配置方法,比如上面的pid_max,这一类的参数配置方法都类似,就是把值写入到/etc/sysctl.conf文件中即可:# /proc/sys/kernel/pid_max 参数配置方法如下: echo 'kernel.pid_max = 4194303' >> /etc/sysctl.conf # /proc/sys/fs/file-max 参数配置方法如下: echo 'fs.file-max = 26234859' >> /etc/sysctl.conf
- ulimit -n即 open files 文件句柄最大数,默认是1024,这里我们需要把这个值放大到65536:echo'* soft nofile 65536' >> /etc/security/limits.conf echo '* hard nofile 65536' >> /etc/security/limits.conf
- 修改磁盘的I/O Scheduler,这里我添加了一个/etc/udev/rules.d/99-disk.rules,内容如下:SUBSYSTEM=="block",ATTR{device/model}=="VBOX HARDDISK", ACTION=="add|change",KERNEL=="sd[a-h]",ATTR{queue/scheduler}="noop",ATTR{queue/read_ahead_kb}="8192"
解释下这里各个参数的意义,VBOX HARDDISK这个值可以从cat/sys/block/sda/device/model指令获取,一般SSD和SATA的model都是不一样的,上述指令对从sda-sdh的model是VBOX HARDDISK的磁盘设置了shcheduler为noop,以及read_ahead_kb为8192。对于不同的磁盘,可以在99-disk.rules内添加多条规则。
终于,终于,终于,把环境准备好了,这时候,我比较建议重启下主机。然后,简要介绍下这次搭建的ceph的架构:
- 240G SSD: 用作3个2T SATA的journal,以及800G SSD的journal。
- 800G SSD: 用作OSD,三台机器共3个构成ssd-pool
- 2T SATA: 用作OSD,三台机器共9个构成sata-pool
磁盘分区
我们将240G的盘分出4个20G的分区用作journal:
更新分区表,并查看分区是否正确:
将三台主机的240G盘都分好区,就可以开始部署ceph了。 如果报下面的错误,可以尝试重启主机,保证partprobe指令没有输出:
代码语言:javascript复制[root@ceph-1~]# partprobe
Error: Error informing the kernel about modifications to partition /dev/sde1 --设备或资源忙. This means Linux won'tknow about any changes you made to /dev/sde1 until you reboot -- so youshouldn't mount it or use it in any way before rebooting.
Error: Failed to add partition 1 (设备或资源忙)
部署Ceph
在部署节点(ceph-1)安装ceph-deploy,下文的部署节点统一指ceph-1:
在部署节点创建部署目录并开始部署:
从部署节点ssh-copy-id到各个其他节点。
如果之前没有ssh-copy-id到各个节点,则需要输入一下密码,过程log如下:
此时,目录内容如下:
在ceph.conf文件中,添加几个配置项(未添加cluster_network):
开始部署monitor:
查看集群状态:
开始部署OSD, journal盘对应关系如下:
OSD盘 | journal盘 | 备注 |
---|---|---|
/dev/sdb | /dev/sde1 | 2T SATA |
/dev/sdc/ | dev/sde2 | 2T SATA |
/dev/sdd | /dev/sde32T | SATA |
/dev/sdf/ | dev/sde4800G | SSD |
我的一个小习惯,先部署SATA,再部署SSD,这样序号就会连续了。。。
osd prepare 后面的参数格式为:HOSTNAME:data-disk:journal-disk。
代码语言:javascript复制ceph-deploy--overwrite-conf osd prepare ceph-1:/dev/sdb:/dev/sde1ceph-1:/dev/sdc:/dev/sde2 ceph-1:/dev/sdd:/dev/sde3 ceph-2:/dev/sdb:/dev/sde1ceph-2:/dev/sdc:/dev/sde2 ceph-2:/dev/sdd:/dev/sde3 ceph-3:/dev/sdb:/dev/sde1ceph-3:/dev/sdc:/dev/sde2 ceph-3:/dev/sdd:/dev/sde3
osd activate后面的参数格式为:HOSTNAME:data-disk1,需要注意的是,刚刚的/dev/sdb这里需要写成/dev/sdb1,因为分了区。
现在,激活创建的OSD:
这里会遇到一个ERR,因为jewel版本的ceph要求journal需要是ceph:ceph权限,报错如下:
代码语言:javascript复制[ceph-1][WARNIN] 2016-10-1004:56:59.268469 7f47dd1d8800 -1 OSD::mkfs: ObjectStore::mkfs failed with error-13[ceph-1][WARNIN] 2016-10-10 04:56:59.2685297f47dd1d8800 -1 ** ERROR: error creating empty object store in/var/lib/ceph/tmp/mnt.YmTO7V: (13) Permission denied
执行如下指令即可解决这个错误,当然这个步骤最好是放在磁盘分区一节:
代码语言:javascript复制chown ceph:ceph/dev/sde[1-4]
不要忘了所有的journal盘都需要修改权限。
代码语言:javascript复制ceph-deploy--overwrite-conf osd activate ceph-1:/dev/sdb1 ceph-1:/dev/sdc1ceph-1:/dev/sdd1 ceph-2:/dev/sdb1 ceph-2:/dev/sdc1 ceph-2:/dev/sdd1ceph-3:/dev/sdb1 ceph-3:/dev/sdc1 ceph-3:/dev/sdd1
我在部署的时候出了个小问题,有一个OSD没成功(待所有OSD部署完毕后,再重新部署问题OSD即可解决),如果不出意外的话,集群状态应该如下:
不用等了,这里的64 creating会一直卡着的,查看ceph osd tree就会理解osd_crush_update_on_start = false的作用了。不像快速部署文章中会达到active clean状态了,会在后续的章节中继续完善CRUSH来解决这个问题。
同样的方法部署三个SSD,指令如下:
执行完后,查看ceph -s,应该可以看到12个OSD是up的。
自定义CRUSH
最后的工作就是把刚刚建的12个OSD组成下图所示的架构,这里的root-sata,ceph-1-sata等都是我们虚构出来的,和主机名没有任何关系,但是OSD必须和刚刚部署的顺序一一对应!
首先创建对应的Bucket,指令规范为:
所以对应指令为:
再将对应的host移到root下,然后把OSD移到对应的host下面,注意添加OSD时的weight是该OSD的实际大小(2T为2 ,800G为0.8),切勿随意填写!!!指令如下:
一不小心加错了怎么办?
查看当前的ceph osd tree,是不是觉得棒棒哒!
最后有个孤零零的root default,丢那别管咯,留个纪念。
最后,修改CRUSHMAP即可:我习惯导出crushmap进行操作,十分方便不需要记什么指令。导出crushmap,并增加一条rule:
代码语言:javascript复制cephosd getcrushmap -o /tmp/crush
crushtool -d /tmp/crush -o /tmp/crush.txt
# -d 的意思是decompile,导出的crush是二进制格式的。
vim /tmp/crush.txt
翻到最下面,有个#rule:
复制粘贴再加个rule,并修改成下面的样子:
保存退出,编译刚刚的crush.txt,并注入集群中:
查看ceph -s:
代码语言:javascript复制[root@ceph-1cluster]# ceph -s
cluster db18ec7d-9070-4a23-9fbc-36b3137d7587
health HEALTH_WARN
too few PGsper OSD (16 < min 30)
monmap e1: 3 mons at{ceph-1=192.168.56.101:6789/0,ceph-2=192.168.56.102:6789/0,ceph-3=192.168.56.103:6789/0}
electionepoch 4, quorum 0,1,2 ceph-1,ceph-2,ceph-3
osdmap e59: 12 osds: 12 up, 12 in
flagssortbitwise
pgmap v321: 64 pgs, 1 pools, 0 bytes data, 0objects
405 MB used,20820 GB / 20820 GB avail
64 active clean
去除WARN,增大rbd的pg数即可:
代码语言:javascript复制cephosd pool set rbd pg_num 256
ceph osd pool set rbd pgp_num 256
这时候,稍等一下就会看到Health_OK的状态了,但是还没有体现出这种架构的优点,先查看下rbd池的情况:
代码语言:javascript复制[root@ceph-1cluster]# ceph osd pool ls detail
pool 0 'rbd' replicated size 3 min_size 2 crush_ruleset 0 object_hash rjenkinspg_num 256 pgp_num 256 last_change 62 flags hashpspool stripe_width 0
这里主要关注crush_ruleset 0 ,rbd池使用的是刚刚建的rule-sata,所以rbd池的所有数据都是保存在osd.0--osd.8上的:
代码语言:javascript复制[root@ceph-1cluster]# ceph pg map 0.0
osdmap e66 pg 0.0 (0.0) -> up [6,1,5] acting [6,1,5]
关于PG的一些概念,可以参照大话ceph--PG那点事儿这篇文章。 此时,将rbd池是ruleset设置为1,即由osd.9-osd.11组成的结构,rbd池的所有数据将会保存在这三个SSD上:
代码语言:javascript复制[root@ceph-1cluster]# ceph osd pool set rbd crush_ruleset 1
set pool 0 crush_ruleset to 1
[root@ceph-1 cluster]# ceph pg map 0.0
osdmap e68 pg 0.0 (0.0) -> up [9,10,11] acting [9,10,11]
实际用法比如:
代码语言:javascript复制[root@ceph-1cluster]# ceph osd pool create sata-pool 256 rule-sata
pool 'sata-pool' created
[root@ceph-1 cluster]# ceph osd pool create ssd-pool 256 rule-ssd
pool 'ssd-pool' created
[root@ceph-1 cluster]# ceph df
GLOBAL:
SIZE AVAIL RAW USED %RAW USED
20820G 20820G 452M 0
POOLS:
NAME ID USED %USED MAX AVAIL OBJECTS
rbd 0 0 0 799G 0
sata-pool 1 0 0 6140G 0
ssd-pool 2 0 0 799G 0
[root@ceph-1 cluster]# ceph osd pool ls detail
pool 0 'rbd' replicated size 3 min_size 2 crush_ruleset 1 object_hash rjenkinspg_num 256 pgp_num 256 last_change 67 flags hashpspool stripe_width 0
pool 1 'sata-pool' replicated size 3 min_size 2 crush_ruleset 0 object_hashrjenkins pg_num 256 pgp_num 256 last_change 69 flags hashpspool stripe_width 0
pool 2 'ssd-pool' replicated size 3 min_size 2 crush_ruleset 1 object_hashrjenkins pg_num 256 pgp_num 256 last_change 79 flags hashpspool stripe_width 0
这一节的作用就是将同一台主机上的SATA和SSD分开使用,在一批次同样结构的主机上,构建出两种不同速度的pool,实际上,CRUSH的自定义性,给ceph提供了极大的可塑性。
总结的话
这篇文章除了没有涉及到具体的ceph.conf参数以及OS优化的参数外,基本上可以搭建一个适用于生产环境的集群,也算了了一桩心事,因为快速部署那篇还是写的很毛糙的,这篇花了不少心思把整个流程整理了下。 Enjoy it !