CRUSH的全称是Controlled Replication Under Scalable Hashing,是ceph数据存储的分布式选择算法,也是ceph存储引擎的核心。在之前的博客里介绍过,ceph的客户端在往集群里读写数据时,动态计算数据的存储位置。这样ceph就无需维护一个叫metadata的东西,从而提高性能。
ceph分布式存储有关键的3R: Replication(数据复制)、Recovery(数据恢复)、Rebalancing(数据均衡)。在组件故障时,ceph默认等待300秒,然后将OSD标记为down和out,并且初始化recovery操作。这个等待时间可以在集群配置文件的mon_osd_down_out_interval参数里设置。在recovery过程中,ceph会重新产生受故障影响的数据。
因为CRUSH会复制数据到不同的磁盘,这些数据副本在recovery时就变得有用。在恢复过程中,CRUSH会尽量移动最小数量的数据,并且产生一个新的集群布局,从而使集群从故障中恢复。
当新的主机或磁盘加入到集群时,CRUSH开始rebalancing操作,它将数据从存在的主机、磁盘迁移到新的主机、磁盘。rebalancing时会尽量利用所有磁盘,以提高集群性能。例如,某个ceph集群包含2000个OSD,现在新加入20个OSD,这样仅1%的数据将被迁移。在迁移中所有存在的磁盘会并行工作,使得迁移工作尽快完成。当然,如果ceph集群在重度使用中,推荐做法是新加入的磁盘设置权重0,并且逐步提高权重,使得数据迁移缓慢发生,以免影响性能。所有的分布式存储在扩容时都建议这样操作,比如我之前写的swift容量管理文章。
在实际中可能经常需要调整集群的布局。默认的CRUSH布局很简单,执行ceph osd tree命令,会看到仅有host和OSD这两种bucket类型在root下面。默认的布局对分区容错很不利,没有rack、row、room这些概念。下面我们增加一种bucket类型:rack(机架)。所有的host(主机)都应位于rack下面。
注:如下文字及图片,都来自《learning ceph》这本书。建议读者有时间详读原著。
(1)执行ceph osd tree得到当前的集群布局:
(2)增加rack:
$ ceph osd crush add-bucket rack01 rack $ ceph osd crush add-bucket rack02 rack $ ceph osd crush add-bucket rack02 rack
(3)将host移动到rack下面:
$ ceph osd crush move ceph-node1 rack=rack01 $ ceph osd crush move ceph-node2 rack=rack02 $ ceph osd crush move ceph-node3 rack=rack03
(4)将rack移动到默认的root下面:
$ ceph osd crush move rack03 root=default $ ceph osd crush move rack02 root=default $ ceph osd crush move rack01 root=default
(5)再次运行ceph osd tree命令,会看到新的布局已产生,所有host都位于特定rack下面。按此操作,就完成了对CRUSH布局的调整。