总结:
1、避免一个bucket写入太多的对象,对新建bucket,限制存储对象的最大数量
2、使用比较新的版本0.94以上修复单bucket索引对象过大问题,在Ceph的0.94版本中,已经支持了bucket索引对象的shard功能,一个bucket索引对象可以分成多个shard对象存储,可有效缓解单bucket索引对象过大问题
3、系统上线前需要经过充分的测试,功能,性能,异常,稳定性以及压力测试(大数据量)

Ceph作为一款开源的分布式存储软件,可以利用X86服务器自身的本地存储资源,创建一个或多个存储资源池,并基于资源池对用户提供统一存储服务,包括块存储、对象存储、文件存储,满足企业对存储高可靠性、高性能、高可扩展性方面的需求,并越来越受到企业的青睐。经过大量的生产实践证明,Ceph的设计理念先进,功能全面,使用灵活,富有弹性。不过,Ceph的这些优点对企业来说也是一把双刃剑,驾驭的好可以很好地服务于企业,倘若功力不够,没有摸清Ceph的脾性,有时也会制造不小的麻烦,下面我要给大家分享的正是这样的一个案例。

A公司通过部署Ceph对象存储集群,对外提供云存储服务,提供SDK帮助客户快速实现对图片、视频、apk安装包等非结构化数据的云化管理。在业务正式上线前,曾经对Ceph做过充分的功能测试、异常测试和性能测试。
集群规模不是很大,使用的是社区0.80版本,总共有30台服务器,每台服务器配置32GB内存,10块4T的SATA盘和1块160G的Intel S3700 SSD盘。300块SATA盘组成一个数据资源池(缺省配置情况下就是名称为.rgw.buckets的pool),存放对象数据;30块SSD盘组成一个元数据资源池(缺省配置情况下就是名称为.rgw.buckets.index的pool),存放对象元数据。有过Ceph对象存储运维部署经验的朋友都知道,这样的配置也算是国际惯例,因为Ceph对象存储支持多租户,多个用户在往同一个bucket(用户的一个逻辑空间)中PUT对象的时候,会向bucket索引对象中写入对象的元数据,由于是共享同一个bucket索引对象,访问时需要对这个索引对象加锁,将bucket索引对象存放到高性能盘SSD组成的资源池中,减少每一次索引对象访问的时间,提升IO性能,提高对象存储的整体并发量。
系统上线后,客户数据开始源源不断地存入到Ceph对象存储集群,在前面的三个月中,一切运行正常。期间也出现过SATA磁盘故障,依靠Ceph自身的故障检测、修复机制轻松搞定,运维的兄弟感觉很轻松。进入到5月份,运维兄弟偶尔抱怨说SSD盘对应的OSD有时会变的很慢,导致业务卡顿,遇到这种情况他们简单有效的办法就是重新启动这个OSD,又能恢复正常。大概这种现象零星发生过几次,运维兄弟询问是不是我们在SSD的使用上有什么不对。我们分析后觉得SSD盘的应用没有什么特别的地方,除了将磁盘调度算法修改成deadline,这个已经修改过了,也就没有太在意这个事情。
5月28日晚上21:30,运维兄弟手机上接到系统告警,少部分文件写入失败,马上登陆系统检查,发现是因为一台服务器上的SSD盘对应的OSD读写缓慢引起的。按照之前的经验,此类情况重启OSD进程后就能恢复正常,毫不犹豫地重新启动该OSD进程,等待系统恢复正常。但是这一次,SSD的OSD进程启动过程非常缓慢,并引发同台服务器上的SATA盘OSD进程卡顿,心跳丢失,一段时间后,又发现其它服务器上开始出现SSD盘OSD进程卡顿缓慢。继续重启其它服务器上SSD盘对应的OSD进程,出现了类似情况,这样反复多次重启SSD盘OSD进程后,起不来的SSD盘OSD进程越来越多。运维兄弟立即将此情况反馈给技术研发部门,要求火速前往支援。
到办公室后,根据运维兄弟的反馈,我们登上服务器,试着启动几个SSD盘对应的OSD进程,反复观察比对进程的启动过程:
1、 用top命令发现这个OSD进程启动后就开始疯狂分配内存,高达20GB甚至有时达到30GB;有时因系统内存耗尽,开始使用swap交换分区;有时即使最后进程被成功拉起,但OSD任然占用高达10GB的内存。
2、 查看OSD的日志,发现进入FileJournal::_open阶段后就停止了日志输出。经过很长时间(30分钟以上)后才输出进入load_pg阶段;进入load_pg阶段后,再次经历漫长的等待,虽然load_pg完成,但进程仍然自杀退出。
3、 在上述漫长启动过程中,用pstack查看进程调用栈信息,FileJournal::_open阶段看到的调用栈是在做OSD日志回放,事务处理中是执行levelDB的记录删除;在load_pg阶段看到的调用栈信息是在利用levelDB的日志修复levelDB文件。
4、 有时候一个SSD盘OSD进程启动成功,运行一段时间后会导致另外的SSD盘OSD进程异常死掉。
从这些现象来看,都是跟levelDB有关系,内存大量分配是不是跟这个有关系呢?进一步查看levelDB相关的代码后发现,在一个事务处理中使用levelDB迭代器,迭代器访问记录过程中会不断分配内存,直到迭代器使用完才会释放全部内存。从这一点上看,如果迭代器访问的记录数非常大,就会在迭代过程中分配大量的内存。根据这一点,我们查看bucket中的对象数,发现有几个bucket中的对象数量达到了2000万、3000万、5000万,而且这几个大的bucket索引对象存储位置刚好就是出现问题的那几个SSD盘OSD。内存大量消耗的原因应该是找到了,这是一个重大突破,此时已是30日21:00,这两天已经有用户开始电话投诉,兄弟们都倍感“鸭梨山大”。已经持续奋战近48小时,兄弟们眼睛都红肿了,必须停下来休息,否则会有兄弟倒在黎明前。
31日8:30,兄弟们再次投入战斗。
还有一个问题,就是有些OSD在经历漫长启动过程,最终在load_pg完成后仍然自杀退出。通过走读ceph代码,确认是有些线程因长时间没有被调度(可能是因levelDB的线程长时间占用了CPU导致)而超时自杀所致。在ceph的配置中有一个filestore_op_thread_suicide_timeout参数,通过测试验证,将这个参数设置成一个很大的值,可以避免这种自杀。又看到了一点点曙光,时钟指向12:30。
有些进程起来后,仍然会占用高达10GB的内存,这个问题不解决,即使SSD盘OSD拉起来了,同台服务器上的其它SATA盘OSD运行因内存不足都要受到影响。兄弟们再接再厉啊,这是黎明前的黑暗,一定要挺过去。有人查资料,有人看代码,终于在14:30从ceph资料文档查到一个强制释放内存的命令:ceph tell osd.* heap release,可以在进程启动后执行此命令释放OSD进程占用的过多内存。大家都格外兴奋,立即测试验证,果然有效。
一个SSD盘OSD起来后运行一会导致其它SSD盘OSD进程退出,综合上面的分析定位,这主要是因为发生数据迁移,有数据迁出的OSD,在数据迁出后会删除相关记录信息,触发levelDB删除对象元数据记录,一旦遇到一个超大的bucket索引对象,levelDB使用迭代器遍历对象的元数据记录,就会导致过度内存消耗,从而导致服务器上的OSD进程异常。
根据上述分析,经过近2个小时的反复讨论论证,我们制定了如下应急措施:
1、 给集群设置noout标志,不允许做PG迁移,因为一旦出现PG迁移,有PG迁出的OSD,就会在PG迁出后删除PG中的对象数据,触发levelDB删除对象元数据记录,遇到PG中有一个超大的bucket索引对象就会因迭代器遍历元数据记录而消耗大量内存。
2、 为了能救活SSD对应的OSD,尽快恢复系统,在启动SSD对应的OSD进程时,附加启动参数filestore_op_thread_suicide_timeout,设置一个很大的值。由于故障OSD拉起时,LevelDB的一系列处理会抢占CPU,导致线程调度阻塞,在Ceph中有线程死锁检测机制,超过这个参数配置的时间线程仍然没有被调度,就判定为线程死锁。为了避免因线程死锁导致将进程自杀,需要设置这个参数。
3、 在目前内存有限的情况下,异常的OSD启动会使用swap交换分区,为了加快OSD进程启动,将swap分区调整到SSD盘上。
4、 启动一个定时任务,定时执行命令ceph tell osd.* heap release,强制释放OSD占用的内存。
5、 SSD对应的OSD出现问题的时候,按如下步骤处理:
a) 先将该服务器上的所有OSD进程都停掉,以腾出全部内存。
b) 然后启动OSD进程,并携带filestore_op_thread_suicide_timeout参数,给一个很大的值,如72000。
c) 观察OSD的启动过程,一旦load_pgs执行完毕,可以立即手动执行ceph tell osd.N heap release命令,将其占用的内存强制释放。
d) 观察集群状态,当所有PG的状态都恢复正常时,再将其他SATA盘对应的OSD进程启动起来。
按照上述步骤,我们从17:30开始逐个恢复OSD进程,在恢复过程中,那几个超大bucket索引对象在做backfilling的时候需要较长时间,在此期间访问这个bucket的请求都被阻塞,导致应用业务请求出现超时,这也是单bucket存储大量对象带来的负面影响。
5月31日23:00,终于恢复了全部OSD进程,从故障到系统全部成功恢复,我们惊心动魄奋战了72小时,大家相视而笑,兴奋过度,再接再厉,一起讨论制定彻底解决此问题的方案:
1、 扩大服务器内存到64GB。
2、 对新建bucket,限制存储对象的最大数量。
3、 Ceph 0.94版本经过充分测试后,升级到0.94版本,解决单bucket索引对象过大问题。
4、 优化Ceph对levelDB迭代器的使用,在一个大的事务中,通过分段迭代,一个迭代器在完成一定数量的记录遍历后,记录其当前迭代位置,将其释放,再重新创建一个新的迭代器,从上次迭代的位置开始继续遍历,如此可以控制迭代器的内存使用量。
前事不忘后事之师,汲取经验教训,我们总结如下几点:
1、 系统上线前必须经过充分的测试
A公司的系统上线前,虽然对ceph做了充分的功能、性能、异常测试,但却没有大量数据的压力测试,如果之前单bucket灌入了几千万对象测试,也许就能提前发现这个隐患。
2、 运维过程中的每一个异常都要及时引起重视
此案例中,在问题爆发前一段时间,运维部门已经有反馈SSD异常的问题,可惜没有引起我们重视,倘若当时就深入分析,也许可以找到问题根由,提前制定规避措施。
3、 摸清ceph的脾性
任何软件产品都有相应的规格限制,ceph也不例外。如果能提前深入了解ceph架构及其实现原理,了解单bucket过度存放大量对象所带来的负面影响,提前规划,也不会出现本案例中遇到的问题。RGW对配额的支持非常全面,包括用户级别的、bucket级别的,都可以配置单个bucket允许存放的最大对象数量。
4、 时刻跟踪社区最新进展
在Ceph的0.94版本中,已经支持了bucket索引对象的shard功能,一个bucket索引对象可以分成多个shard对象存储,可有效缓解单bucket索引对象过大问题。

原文链接:
http://stor.51cto.com/art/201803/567763.htm

【经验】Ceph对象存储运维的惊魂72小时相关推荐

  1. 存储运维知识点记录(netapp,华为,HP-3par,emc)

    netapp部分 (1)当netapp存储出现问题了,应该怎么收集日志? 一般当硬件(硬盘,电池)出现问题时,厂商会要求收集autosupport日志,收集时在netapp的命令号模式下: #syst ...

  2. V7000存储运维使用手册

    一.    IBM Storwize V7000简介 IBM Storwize V7000 适用于中端市场,它通过内置的自动精简配置.Easy Tier 自动存储分层和存储虚拟化,满足了虚拟环境中性能 ...

  3. 隐秘的角落——一个CIO的惊魂72小时

    摘要:200万,赎回你的前途. 关键词: CIO 刘庆宇 200万,赎回你的前途. 虽然已经确认无数次, 我仍然忍不住盯着手机发愣. 置身于一场注定的败局是什么感觉? 无法阻止,任人宰割. 深呼吸,我 ...

  4. 解决在ceph对象网关中使用s3fs报错“unable to access MOUNTPOINT /s3: Transport endpoint is not connected”

    s3fs简介   简要来说,就是将s3的存储桶,文件,文件列表可以通过挂载到本地形成一个本地文件系统,方便浏览和查看目录结构,由于ceph rgw服务兼AWS S3,所以通过s3fs工具我们也能够将c ...

  5. 10 年经验告诉你:运维的真正价值在哪里?

    点击上方"民工哥技术之路"选择"置顶或星标" 每天10点为你分享不一样的干货 前言 谈起运维工作,估计很多人会下意识的认为就是修电脑的.网管(上不去网,第一个被 ...

  6. ceph的数据存储之路(10) -----ceph对象存储的ls命令实现及思考

    2019独角兽企业重金招聘Python工程师标准>>> 更新:2016-10-19--------------------------------------- 前面更新的内容可能略 ...

  7. ios 将随意对象存进数据库

    要将一个对象存进数据库的blob字段,最好先转为NSData.一个对象要遵守NSCoding协议,实现协议中对应的方法,才干转成NSData. NSData *statusData = [NSKeye ...

  8. 【转】Ceph对象存储(rgw)的IPv6环境配置

    引言 在搭建成功Ceph集群后,对于如何使用,其实我还是一脸MB的,心想竟然提供三种存储接口(对象,文件,快),口气也未免太大.在结合项目需求之后,我选择了对象存储接口.那么问题又来了,如何配置IPv ...

  9. Ceph对象存储(rgw)的IPv6环境配置

    本文作者: lemon 本文链接: https://lemon2013.github.io/2016/11/09/Ceph对象存储-rgw-IPv6环境配置/ 版权声明: 本博客所有文章除特别声明外, ...

最新文章

  1. 链表问题11——两个单链表相交的系列问题(一):找到有环链表的环入口节点
  2. Java按钮哪个方法响应_当用户点击按钮时,Java程序采用什么方法来响应?()
  3. 进击的python【第一集】
  4. linux shell 替换字符串的几种方法,变量替换${},sed,awk
  5. GHOST系统时出现“A:\GHOSTERR.TXT”的解决方法
  6. thinkphp5.0l路由冲突原因及解决方法
  7. 1.1 Python 安装
  8. 逐渐显示的按钮和图片上下切换
  9. Demo分享丨看ModelArts与HiLens是如何让车自己跑起来的
  10. LeetCode - 44. Wildcard Matching
  11. vue、react隐式实例化
  12. Landsat8遥感数据大气校正
  13. 22道接口测试面试题答案。
  14. shuttle的DSA2LV板子逆向工程完成,Uboot和linux有源码了
  15. python批量处理excel——给指定单元格填充颜色
  16. html字体如何运用在ps上,PS文字排版工具的使用技巧
  17. DayDream模拟手柄操作
  18. java-No route to host 解决办法
  19. 巫宁坤 一滴泪 pdf mobi kindle
  20. Linux环境下安装部署运行Jmeter

热门文章

  1. restful风格编程知识补充
  2. 如何批量将png改为jpg图片,缩小空间占用大小
  3. 【英语:基础高阶_经典外刊阅读】L2.阅读理解必备技能—词义推测
  4. SPI驱动_linux
  5. 魔域mysql修改_魔域数据库修改方案.doc
  6. 几十本书籍、固态硬盘、蓝牙音箱等礼品免费送!
  7. 【硬件配置教程】海康NVR硬盘录像机接入海康RTSP摄像头操作步骤
  8. SQL DML 数据操纵语句
  9. 反欺诈子研究-特征衍生过程
  10. 在springboot项目中如何设计UrlFilter过滤器