替换OSD操作的优化与分析


replaceosd

前言

之前有写过一篇删除OSD的正确方式,里面只是简单的讲了下删除的方式怎样能减少迁移量,本篇属于一个扩展,讲述了 Ceph 运维当中经常出现的坏盘提换盘的步骤的优化

基础环境两台主机每台主机8个 OSD,一共 16 个 OSD,副本设置为2,PG 数设置为800,计算下来平均每个 OSD 上的 P G数目为100个,本篇将通过数据来分析不同的处理方法的差别

开始测试前先把环境设置为 noout,然后通过停止 OSD 来模拟 OSD 出现了异常,之后进行不同处理方法

测试三种方法

首先 out 一个 OSD,然后剔除 OSD,然后增加 OSD

  1. 停止指定 OSD 进程
  2. out 指定 OSD
  3. crush remove 指定 OSD
  4. 增加一个新的 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
102

第一次 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
137

我们重新加上新的 OSD

[root@lab8106 ~]# ceph-deploy osd prepare lab8107:/dev/sdi
[root@lab8106 ~]# ceph-deploy osd activate lab8107:/dev/sdi1

加完以后统计当前的新的 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
167

整个替换流程完毕,统计上面的 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
reweighted item id 16 name 'osd.16' to 0 in crush map

等待平衡了以后记录当前的 PG 分布状态

[root@lab8106 ~]# ceph pg dump pgs|awk '{print $1,$15}'|grep -v pg   > 2pg2.txt
dumped pgs in format plain

比较前后的变动

[root@lab8106 ~]# diff -y -W 100 2pg1.txt 2pg2.txt  --suppress-common-lines|wc -l
166

crush remove 指定 OSD

[root@lab8106 ~]# ceph osd crush remove osd.16
removed item id 16 name 'osd.16' from crush map

这个地方因为上面 crush 已经是0了所以删除也不会引起 PG 变动
然后直接 ceph osd rm osd.16 同样没有 PG 变动

增加新的 OSD

[root@lab8106 ~]#ceph-deploy osd prepare lab8107:/dev/sdi
[root@lab8106 ~]#ceph-deploy osd activate lab8107:/dev/sdi1

等待平衡以后获取当前的 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
159

总的 PG 变动为

166+159=325

开始做norebalance,然后做crush remove,然后做add

恢复环境为初始环境,然后获取当前的 PG 分布

[root@lab8106 ~]# ceph pg dump pgs|awk '{print $1,$15}'|grep -v pg   > 3pg1.txt
dumped pgs in format plain

给集群做多种标记,防止迁移

设置为 norebalance,nobackfill,norecover,后面是有地方会解除这些设置的

[root@lab8106 ~]# ceph osd set norebalance
set norebalance
[root@lab8106 ~]# ceph osd set nobackfill
set nobackfill
[root@lab8106 ~]# ceph osd set norecover
set norecover

crush reweight 指定 OSD

[root@lab8106 ~]# ceph osd crush reweight osd.15 0
reweighted item id 15 name 'osd.15' to 0 in crush map

这个地方因为已经做了上面的标记,所以只会出现状态变化,而没有真正的迁移,我们也先统计一下

[root@lab8106 ~]# ceph pg dump pgs|awk '{print $1,$15}'|grep -v pg   > 3pg2.txt
[root@lab8106 ~]# diff -y -W 100 3pg1.txt 3pg2.txt --suppress-common-lines|wc -l
158

注意这里只是计算了,并没有真正的数据变动,可以通过监控两台的主机的网络流量来判断,所以这里的变动并不用计算到需要迁移的 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
[root@lab8106 ~]#ceph-deploy osd activate lab8107:/dev/sdi1

我的环境下,新增的 OSD 的编号为16了

解除各种标记

我们放开上面的设置,看下数据的变动情况

[root@lab8106 ceph]# ceph osd unset norebalance
unset norebalance
[root@lab8106 ceph]# ceph osd unset nobackfill
unset nobackfill
[root@lab8106 ceph]# ceph osd unset norecover
unset norecover

设置完了后数据才真正开始变动了,可以通过观察网卡流量看到,来看下最终pg变化

[root@lab8106 ceph]# ceph pg dump pgs|awk '{print $1,$15}'|grep -v pg   > 3pg3.txt
dumped pgs in format plain
[root@lab8106 ~]# diff -y -W 100 3pg1.txt 3pg3.txt --suppress-common-lines|wc -l
195

这里我们只需要跟最开始的 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

迁移的数据量是一定的,这个看是请求的时候实时迁移然后响应还是提前迁移,然后响应,所以这个中间操作过程尽量的快的完成,然后好迁移完响应前端的请求

变更记录

Why Who When
创建 武汉-运维-磨渣 2016-09-19
修改排版,去掉打赏 武汉-运维-磨渣 2017-02-04
增加附录段落 武汉-运维-磨渣 2017-02-04