osd对象存储设备:
ceph中数据存储过程首先数据会被分割成多个object,(每个object一个object id,大小可设置,默认是4MB),object是Ceph存储的最小存储单元。由于object的数量很多,为了有效减少了Object到OSD的索引表、降低元数据的复杂度,使得写入和读取更加灵活,引入了pg(Placement Group ):PG用来管理object,每个object通过Hash,映射到某个pg中,一个pg可以包含多个object。 Pg再通过CRUSH计算,映射到osd中。如果是三副本的,则每个pg都会映射到三个osd,保证了数据的冗余。写入数据的过程如下图所示:
完成存储用户数据的工作绝大多数都是由osd daemon进程来实现的。集群中一般有多个osd,client将直接与osd进行I/O操作的交互,而不再需要ceph monitor干预。在ceph集群中每个osd高度自治,数据复制,数据恢复,数据迁移等都由osd自主进行而无需中心控制器干预;osd之间相互监督,确保故障能够被及时捕获和上报至monitor;通过osd与客户端、以及osd之间相互学习和点对点传播osdmap,ceph能够快速进行故障切换和恢复,并最大程度保证对外提供不中断的存储服务。
网络通讯
在设计上,ceph将整个RADOS集群网络分为两个独立的平面,即公共网络平面和集群网络平面。公共网络平面,用于客户端与集群进行通信。由于客户端必须通过Monitor才能获得OSDMap,所以Monitor也必须暴露在公共网络之中,集群网络则用于OSD之间进行通信,原理上OSD之间也可以复用公共网络进行通信,那为什么在设计上要将这两个网络平面分开呢?
首先,两者传输的流量并不对等。以3副本为例,OSD每处理一次客户端的写操作,都要复制两份相同的数据到其他两个不同副本的OSD,所以此时从客户端到这个OSD流量比是1,那么从这个OSD到其他两个副本的流量比是2,由于集群内部在一些情况下还会有数据恢复,数据重均衡等任务,因此理论上集群网的负载要远高于公共网络。其次两者承载的业务性质不同,如果强行将两者合二为一,后台任务很可能会占用大量的带宽,导致优先级更高的客户端业务所需的带宽得不到保障,如果从物理上将两者进行隔离,那么可以单纯从网络方面避免它们承载的业务之间产生干扰。
osd故障恢复过程:
一个新的OSD上线后,首先根据配置信息与monitor通信。Monitor将其加入cluster map,并设置为up且out状态,再将最新版本的cluster map发给这个新OSD。收到monitor发来的cluster map之后,这个新OSD计算出自己所承载的PG及和自己承载同一个PG的其他OSD。然后,新OSD将与这些OSD取得联系。如果这个PG目前处于降级状态(即承载该PG的OSD个数少于正常值,如正常应该是3个,此时只有2个或1个。这种情况通常是OSD故障所致),如果现在有新的osd加入进来则其他OSD将把这个PG内的所有对象和元数据复制给新OSD。数据复制完成后,新OSD被置为up且in状态。
osd重平衡:
如果该PG前一切正常,则这个新OSD将替换掉现有OSD中的一个(PG内将重新选出Primary OSD),并承担其数据。在数据复制完成后,新OSD被置为up且in状态,而被替换的OSD将退出该PG(但状态通常仍然为up且in,因为还要承载其他PG)。而cluster map内容也将据此更新。
故障检查:
如果一个OSD发现和自己共同承载一个PG的另一个OSD无法联通,则会将这一情况上报monitor。此外,如果一个OSD deamon发现自身工作状态异常,也将把异常情况主动上报给monitor。在上述情况下,monitor将把出现问题的OSD的状态设为down且in。如果超过某一预订时间期限,该OSD仍然无法恢复正常,则其状态将被设置为down且out。反之,如果该OSD能够恢复正常,则其状态会恢复为up且in。在上述这些状态变化发生之后,monitor都将更新cluster map并进行扩散。
1、 OSD之间的心跳:
OSD 之间每 osd_heartbeat_interval(默认 2 秒)会有一个来回心跳包的检测,该心跳包会分别从public和cluster网分别发出,(心跳包是单播)当一个 OSD 在 osd_heartbeat_grace(默认 7 秒)时间内没有收到其他 OSD 心跳的时候,那么这个 OSD 会向 MON 汇报说另一个 OSD 心跳已经超时。当MON 收到来自俩个不同故障域的 OSD 都汇报了同一个 OSD 的心跳问题,就会将这个 OSD mark DOWN。 【mon_osd_min_down_reporters(默认为2)(同一故障域只会记1票)】
2、 OSD向mon报告自己的状态:
OSD每最小osd_beacon_report_interval(默认100秒),如果一 OSD 在 mon_osd_report_timeout(默认300秒) 时间内没向mon报告过自己的状态,mon就认为它 down 了。
Osd的数据存放在/var/lib/ceph/osd/
日志文件在/var/log/ceph/ceph-osd.*
Osd的水位信息就是"mon_osd_nearfull_ratio": "0.850000",接近85%就会告警
"mon_osd_full_ratio": "0.950000", 超过95就会报错。
OSD 离线问题分析
如果是环境因素的问题导致 OSD 离线的话,这时候通常表现为心跳超时,异常类型主要分为网络异常、磁盘异常、磁盘压力太大 OSD 自杀。主要从监控角色节点上的 ceph.log 可以看到部分的信息,其次可以从离线 OSD 日志里面也可以得到部分信息。
grep -rnE "FAILED assert|suicide|Seg|link|dummy io|osd_max_markdown_count|returned: -5" ceph-osd.$id.log 如果有相关关键字,说明进程crash了
a)FAILED assert 关键字:一般是由于某些assert条件不满足,触发了逻辑bug
b)suicide 关键字: 一般是内部线程超时超过设置阈值(默认150s),导致OSD进程主动退出
可以通过grep "water level" ceph-osd.$id.log 来查看水位
c)Seg 关键字:程序访问了非法内存导致crash
d)link 关键字:网卡down导致,通过grep "NIC Link is Down" /var/log/messages 来确认
e)dummy io 关键字:说明store层很忙或者慢,60s内未完成一个4k的写操作,
此时要查看页面上该 osd 故障时间段 数据盘利用率
f)osd_max_markdown_count 关键字:osd 在一段时间内被 markdown 多次,导致osd进程退出,此时一般是网络问题导致osd被频繁mark down
g)returned: -5 关键字:一般是磁盘硬件问题此时可以通过 grep "critical medium error" /var/log/messages来确认
网络问题
当存在网卡下线造成的网络异常时,整个服务器上所有 OSD 都会检测到该现象并离线,因此在 3.2 以上的版本在 ceph.log 会显示 osd.x "mark down" 或者被其他的 OSD 报收到了 "refuse" 消息,这时候 mon 会直接将 OSD 设置为离线。
grep -rnE "stuck, cost|send msg delay|recv stuck" ceph-osd.$id.log
如果有相关关键字,大概率说明网络有问题
a) stuck, cost 关键字:说明ping消息包在网络上消耗太多时间(默认大于1s会打印)
b) send msg delay 关键字:网络发送 ping消息包延迟,一般认为是网络发送慢导致
c) recv stuck 关键字:网络收包慢导致
出现上述现象,说明osd之间网络问题,可以使用 ping -f $ip 查看丢包率
查看 /var/log/messages 里面有没有相应的网卡 Down 事件
OSD 如果有检测到网卡 Down,那么会有相关的错误,其中 hb_front_server_messager 表示 public 网络,hb_back_server_messager 表示 cluster 网络,link 1 表示正常,link 0 表示出问题。