Ceph蹚坑笔记 - (1)
来源:互联网 发布:高仿转转网站源码 编辑:程序博客网 时间:2024/06/05 03:39
Ceph蹚坑笔记 - (1)
- Ceph蹚坑笔记 - 1
- 现象
- 分析
- 结论
现象
由于设备调度的原因,运维的哥们需要把一台服务器上的OSD移除。他做了以下操作:
1. pkill ceph-osd
关闭服务器上的所有OSD
2. 在集群把这些OSD标记成down后,用ceph osd rm <osd-id>
删除对应的OSD ID
3. 期待与这些OSD有关的PG转移到其它OSD上,并由degraded状态转到active+clean状态
4. 等了很久,发现集群完全没有修复这些degraded PG的意思
5. 实在没办法,再执行ceph osd crush remove osd.<osd-id>
,degraded PG终于逐渐转到active+clean状态
分析
OSD的状态发生变化触发OSD Map更新,所有活着的OSD都会基于新的OSD Map和根据CRUSH算法重新计算其所承载的PG的新归宿。如果发现PG的新归宿不是当前承载它的OSD集合,集群就会触发Peering动作(自己主导Peering或通知其他OSD发动Peering),进而进行必要的Recovery或Backfill。
OSD变为down后,相应的PG转入degraded状态是符合预期的。按常理说,在ceph osd rm <osd-id>
之后集群应该注意到OSD的状态又发生了一些变化,并为degraded PG寻找新的归宿。
既然ceph osd rm <osd-id>
没有触发Peering,很有可能是因为OSD不认为PG的归宿发生了变化。按照这个思路,查看了代码。OSDMap::_raw_to_up_osds()
的如下代码确认了这个推测(环境中用的是ReplicatedPG)。这里!exists
与is_down
被认为是等价的,在OSD变为down后,集群的决策是:幸存下来的OSD继续承载degraded PG。ceph osd rm <osd-id>
之后,OSDMap::_raw_to_up_osds()
的结果和OSD变为down时结果是一样的,所以不认为degraded PG需要新的OSD来承载,也就没有触发Peering和相应的Recovery或Backfill。
up->clear(); for (unsigned i=0; i<raw.size(); i++) { if (!exists(raw[i]) || is_down(raw[i])) continue; up->push_back(raw[i]); }
后来,尝试了以下操作序列,就没有问题了
1. pkill ceph-osd
关闭服务器上的所有OSD
2. 在集群把这些OSD标记成down后,用ceph osd out <osd-id>
把对应OSD标记为out(也可以清除noout标志位,等待足够长的时间,让集群自动把OSD标记为out)
3. 用ceph osd rm <osd-id>
删除对应的OSD ID
4. 相应的PG逐渐从degraded状态转到active+clean状态
本来以为ceph osd rm <osd-id>
会隐含ceph osd out <osd-id>
。从这次的观察看,这样的想当然是错误的。查看了一下OSDMonitor::prepare_command_impl()
中的如下代码发现,原来out操作修改的是OSD ID的权值(OSDMap::osd_weight[id]
在OSDMap::_pg_to_osds()
被使用),而rm是修改OSD ID的状态信息(OSDMap::osd_state[id]
在OSDMap::_raw_to_up_osds()
中被间接使用)。
} if (prefix == "osd out") { if (osdmap.is_out(osd)) { ss << "osd." << osd << " is already out. "; } else { pending_inc.new_weight[osd] = CEPH_OSD_OUT; ss << "marked out osd." << osd << ". "; any = true; } } // ... } else if (prefix == "osd rm") { if (osdmap.is_up(osd)) { if (any) ss << ", "; ss << "osd." << osd << " is still up; must be down before removal. "; err = -EBUSY; } else { pending_inc.new_state[osd] = osdmap.get_state(osd); pending_inc.new_uuid[osd] = uuid_d(); pending_metadata_rm.insert(osd); if (any) { ss << ", osd." << osd; } else { ss << "removed osd." << osd; } any = true; } }
OSDMap::_pg_to_osds()
被先调用,然后OSDMap::_raw_to_up_osds()
基于OSDMap::_pg_to_osds()
的结果做运算。out的OSD在OSDMap::_pg_to_osds()
先被清理出局,down的或被rm的OSD在OSDMap::_raw_to_up_osds()
才被清理出局。
假设两副本的PG X最先是由osd.1和osd.11承载的。然后,osd.1进入down状态而不是out。这时,OSDMap::_pg_to_osds()
还是选出了osd.1和osd.11,然后OSDMap::_raw_to_up_osds()
从中选出了osd.11。接着osd.1被执行ceph osd rm
,由于is_down
和!exists
是等价的,OSDMap::_raw_to_up_osds()
还是为PG X选择了osd.11。
假设两副本的PG X最先由osd.1,osd.11承载。但osd.1从down状态进入out状态之后才被执行ceph osd rm
,OSDMap::_pg_to_osds()
会把osd.1淘汰并为PG X选择osd.11和另一个存活的OSD(假设是osd.21),而OSDMap::_raw_to_up_osds()
也在此基础上选出了存活的osd.11和osd.21。这样集群就知道PG X应该重新分布到osd.11和osd.21上了。
ceph osd crush remove
之所以也能能够触发PG的重分布,也是因为它修改CRUSH Map(OSDMap.crush)而促使OSDMap::_pg_to_osds()
为PG X选择osd.11和osd.21而不是osd.1和osd.11。
结论
- 这里的
ceph osd rm <osd-id>
不是很有必要,除非永远都不想再使用这些OSD ID了 ceph osd rm <osd-id>
与ceph osd out <osd-id>
不同,ceph osd rm <osd-id>
也不隐含ceph osd out <osd-id>
- 在
ceph osd rm <osd-id>
之前最好等待对应的OSD变成out
- Ceph蹚坑笔记 - (1)
- Ceph蹚坑笔记 - (2)
- Ceph蹚坑笔记 - (3)
- Ceph蹚坑笔记 - (4)
- Ceph 笔记
- ceph笔记
- 实验环境Ceph 9.2.1部署笔记
- Ceph-Openstack学习笔记
- ceph使用笔记
- ceph学习笔记
- ceph学习笔记
- ceph 学习笔记
- 《ceph源码分析》 学习笔记
- ceph架构学习1
- ceph 随笔1
- ceph技巧1
- 1 ceph 概念
- ceph
- Uva11374
- Android自定义开关按钮
- 微信调用jssdk在网页端实现调用扫一扫,java+jsp
- Node.js操作SQLite3
- 关于图片代替文字的语义化
- Ceph蹚坑笔记 - (1)
- Swing之JTree
- Mechanical ARX 无法打开图纸
- Android APP终极瘦身指南
- 有网址解析网络数据
- PHP原生--文件上传
- iOS开发之UIWebView(一)
- 一个好用的jquery树形插件zTree
- java 全角引起的报错1