替换OSD操作的优化与分析
http://www.zphj1987.com/2016/09/19/%E6%9B%BF%E6%8D%A2OSD%E6%93%8D%E4%BD%9C%E7%9A%84%E4%BC%98%E5%8C%96%E4%B8%8E%E5%88%86%E6%9E%90/
前言
之前有写过一篇删除OSD的正确方式,里面只是简单的讲了下删除的方式怎样能减少迁移量,本篇属于一个扩展,讲述了 Ceph 运维当中经常出现的坏盘提换盘的步骤的优化
基础环境两台主机每台主机8个 OSD,一共 16 个 OSD,副本设置为2,PG 数设置为800,计算下来平均每个 OSD 上的 P G数目为100个,本篇将通过数据来分析不同的处理方法的差别
开始测试前先把环境设置为 noout
,然后通过停止 OSD 来模拟 OSD 出现了异常,之后进行不同处理方法
测试三种方法
首先 out 一个 OSD,然后剔除 OSD,然后增加 OSD
- 停止指定 OSD 进程
- out 指定 OSD
- crush remove 指定 OSD
- 增加一个新的 OSD
一般生产环境会设置为 noout
,当然不设置也可以,那就交给程序去控制节点的 out,默认是在进程停止后的五分钟,总之这个地方如果有 out 触发,不管是人为触发,还是自动触发数据流是一定的,我们这里为了便于测试,使用的是人为触发,上面提到的预制环境就是设置的 noout
开始测试前获取最原始的分布
[root@lab8106 ~]# ceph pg dump pgs|awk '{print $1,$15}'|grep -v pg > pg1.txt
|
获取当前的 PG 分布,保存到文件pg1.txt,这个 PG 分布记录是 PG 所在的 OSD,记录下来,方便后面进行比较,从而得出需要迁移的数据
停止指定的 OSD 进程
[root@lab8106 ~]# systemctl stop ceph-osd@15
|
停止进程并不会触发迁移,只会引起 PG 状态的变化,比如原来主 PG 在停止的 OSD 上,那么停止掉 OSD 以后,原来的副本的那个 PG 就会角色升级为主 PG 了
out 掉一个 OSD
[root@lab8106 ~]# ceph osd out 15
|
在触发 out 以前,当前的 PG 状态应该有 active+undersized+degraded
,触发 out 以后,所有的 PG 的状态应该会慢慢变成 active+clean
,等待集群正常后,再次查询当前的 PG 分布状态
[root@lab8106 ~]# ceph pg dump pgs|awk '{print $1,$15}'|grep -v pg > pg2.txt
|
保存当前的 PG 分布为pg2.txt
比较 out 前后的 PG 的变化情况,下面是比较具体的变化情况,只列出变化的部分
[root@lab8106 ~]# diff -y -W 100 pg1.txt pg2.txt --suppress-common-lines
|
这里我们关心的是变动的数目,只统计变动的 PG 的数目
[root@lab8106 ~]# diff -y -W 100 pg1.txt pg2.txt --suppress-common-lines|wc -l
|
第一次 out 以后有102个 PG 的变动,这个数字记住,后面的统计会用到
从 crush 里面删除 OSD
[root@lab8106 ~]# ceph osd crush remove osd.15
|
crush 删除以后同样会触发迁移,等待 PG 的均衡,也就是全部变成 active+clean
状态
[root@lab8106 ~]# ceph pg dump pgs|awk '{print $1,$15}'|grep -v pg > pg3.txt
|
获取当前的 PG 分布的状态
现在来比较 crush remove 前后的 PG 变动
[root@lab8106 ~]# diff -y -W 100 pg2.txt pg3.txt --suppress-common-lines|wc -l
|
我们重新加上新的 OSD
[root@lab8106 ~]# ceph-deploy osd prepare lab8107:/dev/sdi
|
加完以后统计当前的新的 PG 状态
[root@lab8106 ~]# ceph pg dump pgs|awk '{print $1,$15}'|grep -v pg > pg4.txt
|
比较前后的变化
[root@lab8106 ~]# diff -y -W 100 pg3.txt pg4.txt --suppress-common-lines|wc -l
|
整个替换流程完毕,统计上面的 PG 总的变动
102 +137 +167 = 406
也就是按这个方法的变动为406个 PG,因为是只有双主机,里面可能存在某些放大问题,这里不做深入的讨论,因为我的三组测试环境都是一样的情况,只做横向比较,原理相通,这里是用数据来分析出差别
先crush reweight 0 ,然后out,然后再增加osd
首先恢复环境为测试前的环境
[root@lab8106 ~]# ceph pg dump pgs|awk '{print $1,$15}'|grep -v pg > 2pg1.txt
|
记录最原始的 PG 分布情况
crush reweight 指定OSD
[root@lab8106 ~]# ceph osd crush reweight osd.16 0
|
等待平衡了以后记录当前的 PG 分布状态
[root@lab8106 ~]# ceph pg dump pgs|awk '{print $1,$15}'|grep -v pg > 2pg2.txt
|
比较前后的变动
[root@lab8106 ~]# diff -y -W 100 2pg1.txt 2pg2.txt --suppress-common-lines|wc -l
|
crush remove 指定 OSD
[root@lab8106 ~]# ceph osd crush remove osd.16
|
这个地方因为上面 crush 已经是0了所以删除也不会引起 PG 变动
然后直接 ceph osd rm osd.16
同样没有 PG 变动
增加新的 OSD
[root@lab8106 ~]#ceph-deploy osd prepare lab8107:/dev/sdi
|
等待平衡以后获取当前的 PG 分布
[root@lab8106 ceph]# ceph pg dump pgs|awk '{print $1,$15}'|grep -v pg > 2pg3.txt
|
来比较前后的变化
[root@lab8106 ~]# diff -y -W 100 2pg2.txt 2pg3.txt --suppress-common-lines|wc -l
|
总的 PG 变动为
166+159=325
开始做norebalance,然后做crush remove,然后做add
恢复环境为初始环境,然后获取当前的 PG 分布
[root@lab8106 ~]# ceph pg dump pgs|awk '{print $1,$15}'|grep -v pg > 3pg1.txt
|
给集群做多种标记,防止迁移
设置为 norebalance,nobackfill,norecover,后面是有地方会解除这些设置的
[root@lab8106 ~]# ceph osd set norebalance
|
crush reweight 指定 OSD
[root@lab8106 ~]# ceph osd crush reweight osd.15 0
|
这个地方因为已经做了上面的标记,所以只会出现状态变化,而没有真正的迁移,我们也先统计一下
[root@lab8106 ~]# ceph pg dump pgs|awk '{print $1,$15}'|grep -v pg > 3pg2.txt
|
注意这里只是计算了,并没有真正的数据变动,可以通过监控两台的主机的网络流量来判断,所以这里的变动并不用计算到需要迁移的 PG 数目当中
crush remove 指定 OSD
[root@lab8106 ~]#ceph osd crush remove osd.15
|
删除指定的 OSD
删除以后同样是没有 PG 的变动的
ceph osd rm osd.15
|
这个地方有个小地方需要注意一下,不做 ceph auth del osd.15 把15的编号留着,这样好判断前后的 PG 的变化,不然相同的编号,就无法判断是不是做了迁移了
增加新的 OSD
[root@lab8106 ~]#ceph-deploy osd prepare lab8107:/dev/sdi
|
我的环境下,新增的 OSD 的编号为16了
解除各种标记
我们放开上面的设置,看下数据的变动情况
[root@lab8106 ceph]# ceph osd unset norebalance
|
设置完了后数据才真正开始变动了,可以通过观察网卡流量看到,来看下最终pg变化
[root@lab8106 ceph]# ceph pg dump pgs|awk '{print $1,$15}'|grep -v pg > 3pg3.txt
|
这里我们只需要跟最开始的 PG 分布状况进行比较就可以了,因为中间的状态实际上都没有做数据的迁移,所以不需要统计进去,可以看到这个地方动了195个 PG
总共的 PG 迁移量为
195
数据汇总
现在通过表格来对比下三种方法的迁移量的比较(括号内为迁移 PG 数目)
方法一 | 方法二 | 方法三 | |
---|---|---|---|
所做操作 | stop osd (0) out osd(102) crush remove osd (137) add osd(167) |
crush reweight osd(166) out osd(0) crush remove osd (0) add osd(159) |
set 标记(0) crush reweight osd(0) crush remove osd (0) add osd(195) |
PG迁移数量 | 406 | 325 | 195 |
可以很清楚的看到三种不同的方法,最终的触发的迁移量是不同的,处理的好的话,能节约差不多一半的迁移的数据量,这个对于生产环境来说还是很好的,关于这个建议先在测试环境上进行测试,然后再操作,上面的操作只要不对磁盘进行格式化,操作都是可逆的,也就是可以比较放心的做,记住所做的操作,每一步都做完都去检查 PG 的状态是否是正常的
总结
从我自己的操作经验来看,最开始是用的第一种方法,后面就用第二种方法减少了一部分迁移量,最近看到资料写做剔除OSD的时候可以关闭迁移防止无效的过多的迁移,然后就测试了一下,确实能够减少不少的迁移量,这个减少在某些场景下还是很好的,当然如果不太熟悉,用哪一种都可以,最终能达到的目的是一样的
附加
有人问到一个问题,为什么按照这个流程操作的时候,会出现slow request?在进行了一次验证后,发现在迁移过程中的请求路径还是很长的,所以出现slow request还是很容易的
假如我们有三个osd,分别为0,1,2,里面有各种的分布,我们在踢掉一个osd.2后,可能出现的一个情况是
某个PG(0.3b)的[2,0]分布变成了[1,0]
而此时后台的osd.1的PG(0.3b)这个目录里面的内容实际是空的,如果这个时候,前端的请求一个对象正好是分布在0.3b这个PG上的时候,后台需要先将osd.0上面的这个0.3b的对象写入到osd.1的0.3b的pg里面去,然后再去响应客户端的请求,自然路径就长了,如果这样的请求一多,响应前台的性能就有问题了,增加节点的时候同理
请求到这种空PG的对象,PG的状态会这样变化:
从active+degraded 变成active+recovery_wait+degraded
迁移的数据量是一定的,这个看是请求的时候实时迁移然后响应还是提前迁移,然后响应,所以这个中间操作过程尽量的快的完成,然后好迁移完响应前端的请求