从Gitlab误删除数据库想到的

从Gitlab误删除数据库想到的

昨天,Gitlab.com发生了一个大事,某同学误删了数据库,这个事看似是个低级错误,不过,因为Gitlab把整个过程的细节都全部暴露出来了,所以,可以看到很多东西,而对于类似这样的事情,我自己以前也干过,而在最近的两公司中我也见过(Amazon中见过一次,阿里中见过至少四次),正好通过这个事来说说一下自己的一些感想和观点吧。我先放个观点:你觉得有备份系统就不会丢数据了吗?

事件回顾

整个事件的回顾Gitlab.com在第一时间就放到了Google Doc上,事后,又发了一篇Blog来说明这个事,在这里,我简单的回顾一下这个事件的过程。

首先,一个叫YP的同学在给gitlab的线上数据库做一些负载均衡的工作,在做这个工作时的时候突发了一个情况,Gitlab被DDoS攻击,数据库的使用飙高,在block完攻击者的IP后,发现有个staging的数据库(db2.staging)已经落后生产库4GB的数据,于是YP同学在Fix这个staging库的同步问题的时候,发现db2.staging有各种问题都和主库无法同步,在这个时候,YP同学已经工作的很晚了,在尝试过多个方法后,发现db2.staging都hang在那里,无法同步,于是他想把db2.staging的数据库删除了,这样全新启动一个新的复制,结果呢,删除数据库的命令错误的敲在了生产环境上(db1.cluster),结果导致整个生产数据库被误删除。(陈皓注:这个失败基本上就是 “工作时间过长” + “在多数终端窗口中切换中迷失掉了”

在恢复的过程中,他们发现只有db1.staging的数据库可以用于恢复,而其它的5种备份机制都不可用,第一个是数据库的同步,没有同步webhook,第二个是对硬盘的快照,没有对数据库做,第三个是用pg_dump的备份,发现版本不对(用9.2的版本去dump 9.6的数据)导致没有dump出数据,第四个S3的备份,完全没有备份上,第五个是相关的备份流程是问题百出的,只有几个粗糙的人肉的脚本和糟糕的文档,也就是说,不但是是人肉的,而且还是完全不可执行的。(陈皓注:就算是这些备份机制都work,其实也有问题,因为这些备份大多数基本上都是24小时干一次,所以,要从这些备份恢复也一定是是要丢数据的了,只有第一个数据库同步才会实时一些

最终,gitlab从db1.staging上把6个小时前的数据copy回来,结果发现速度非常的慢,备份结点只有60Mbits/S,拷了很长时间(陈皓注:为什么不把db1.staging给直接变成生产机?因为那台机器的性能很差)。数据现在的恢复了,不过,因为恢复的数据是6小时前的,所以,有如下的数据丢失掉了:

  • 粗略估计,有4613 的项目, 74 forks,  和 350 imports 丢失了;但是,因为Git仓库还在,所以,可以从Git仓库反向推导数据库中的数据,但是,项目中的issues等就完全丢失了。
  • 大约有±4979 提交记录丢失了(陈皓注:估计也可以用git仓库中反向恢复)。
  • 可能有 707  用户丢失了,这个数据来自Kibana的日志。
  • 在1月31日17:20 后的Webhooks 丢失了。

因为Gitlab把整个事件的细节公开了出来,所以,也得到了很多外部的帮助,2nd Quadrant的CTO – Simon Riggs 在他的blog上也发布文章 Dataloss at Gitlab 给了一些非常不错的建议:

  • 关于PostgreSQL 9.6的数据同步hang住的问题,可能有一些Bug,正在fix中。
  • PostgreSQL有4GB的同步滞后是正常的,这不是什么问题。
  • 正常的停止从结点,会让主结点自动释放WALSender的链接数,所以,不应该重新配置主结点的 max_wal_senders 参数。但是,停止从结点时,主结点的复数连接数不会很快的被释放,而新启动的从结点又会消耗更多的链接数。他认为,Gitlab配置的32个链接数太高了,通常来说,2到4个就足够了。
  • 另外,之前gitlab配置的max_connections=8000太高了,现在降到2000个是合理的。
  • pg_basebackup 会先在主结点上建一个checkpoint,然后再开始同步,这个过程大约需要4分钟。
  • 手动的删除数据库目录是非常危险的操作,这个事应该交给程序来做。推荐使用刚release 的 repmgr
  • 恢复备份也是非常重要的,所以,也应该用相应的程序来做。推荐使用 barman (其支持S3)
  • 测试备份和恢复是一个很重要的过程。

看这个样子,估计也有一定的原因是——Gitlab的同学对PostgreSQL不是很熟悉。

随后,Gitlab在其网站上也开了一系列的issues,其issues列表在这里 Write post-mortem (这个列表可能还会在不断更新中)

从上面的这个列表中,我们可以看到一些改进措施了。挺好的,不过我觉得还不是很够。

相关的思考

因为类似这样的事,我以前也干过(误删除过数据库,在多个终端窗口中迷失掉了自己所操作的机器……),而且我在amazon里也见过一次,在阿里内至少见过四次以上(在阿里人肉运维的误操作的事故是我见过最多的),但是我无法在这里公开分享,私下可以分享。在这里,我只想从非技术和技术两个方面分享一下我的经验和认识。

技术方面

人肉运维

一直以来,我都觉得直接到生产线上敲命令是一种非常不好的习惯。我认为,一个公司的运维能力的强弱和你上线上环境敲命令是有关的,你越是喜欢上线敲命令你的运维能力就越弱,越是通过自动化来处理问题,你的运维能力就越强。理由如下:

其一,如果说对代码的改动都是一次发布的话,那么,对生产环境的任何改动(包括硬件、操作系统、网络、软件配置……),也都算是一次发布。那么这样的发布就应该走发布系统和发布流程,要被很好的测试、上线和回滚计划。关键是,走发布过程是可以被记录、追踪和回溯的,而在线上敲命令是完全无法追踪的。没人知道你敲了什么命令。

其二,真正良性的运维能力是——人管代码,代码管机器,而不是人管机器。你敲了什么命令没人知道,但是你写个工具做变更线上系统,这个工具干了什么事,看看工具的源码就知道了。

另外、有人说,以后不要用rm了,要用mv,还有人说,以后干这样的事时,一个人干,另一个人在旁边看,还有人说,要有一个checklist的强制流程做线上的变更,还有人说要增加一个权限系统。我觉得,这些虽然可以work,但是依然不好,再由如下:

其一、如果要解决一个事情需要加更多的人来做的事,那这事就做成劳动密集型了。今天我们的科技就是在努力消除人力成本,而不是在增加人力成本。而做为一个技术人员,解决问题的最好方式是努力使用技术手段,而不是使用更多的人肉手段。人类区别于动物的差别就是会发明和使用现代化的工具,而不是使用更多的人力。另外,这不仅仅因为是,人都是会有这样或那样的问题(疲惫、情绪化、急燥、冲动……),而机器是单一无脑不知疲惫的,更是因为,机器干活的效率和速度是比人肉高出N多倍的

其二、增加一个权限系统或是别的一个watch dog的系统完全是在开倒车,权限系统中的权限谁来维护和审批?不仅仅是因为多出来的系统需要多出来的维护,关键是这个事就没有把问题解决在root上。除了为社会解决就业问题,别无好处,故障依然会发生,有权限的人一样会误操作。对于Gitlab这个问题,正如2nd Quadrant的CTO建议的那样,你需要的是一个自动化的备份和恢复的工具,而不是一个权限系统。

其三、像使用mv而不rm,搞一个checklist和一个更重的流程,更糟糕。这里的逻辑很简单,因为,1)这些规则需要人去学习和记忆,本质上来说,你本来就不相信人,所以你搞出了一些规则和流程,而这些规则和流程的执行,又依赖于人,换汤不换药,2)另外,写在纸面上的东西都是不可执行的,可以执行的就是只有程序,所以,为什么不把checklist和流程写成代码呢?(你可能会说程序也会犯错,是的,程序的错误是consistent,而人的错误是inconsistent)

最关键的是,数据丢失有各种各样的情况,不单单只是人员的误操作,比如,掉电、磁盘损坏、中病毒等等,在这些情况下,你设计的那些想流程、规则、人肉检查、权限系统、checklist等等统统都不管用了,这个时候,你觉得应该怎么做呢?是的,你会发现,你不得不用更好的技术去设计出一个高可用的系统!别无它法。

关于备份

一个系统是需要做数据备份的,但是,你会发现,Gitlab这个事中,就算所有的备份都可用,也不可避免地会有数据的丢失,或是也会有很多问题。理由如下:

1)备份通常来说都是周期性的,所以,如果你的数据丢失了,从你最近的备份恢复数据里,从备份时间到故障时间的数据都丢失了。

2)备份的数据会有版本不兼容的问题。比如,在你上次备份数据到故障期间,你对数据的scheme做了一次改动,或是你对数据做了一些调整,那么,你备份的数据就会和你线上的程序出现不兼容的情况。

3)有一些公司或是银行有灾备的数据中心,但是灾备的数据中心没有一天live过。等真正灾难来临需要live的时候,你就会发现,各种问题让你live不起来。你可以读一读几年前的这篇报道好好感受一下《以史为鉴 宁夏银行7月系统瘫痪最新解析

所以,在灾难来临的时候,你会发现你所设计精良的“备份系统”或是“灾备系统”就算是平时可以工作,但也会导致数据丢失,而且可能长期不用的备份系统很难恢复(比如应用、工具、数据的版本不兼容等问题)。

我之前写过一篇《分布式系统的事务处理》,你还记得下面这张图吗?看看 Data Loss 那一行的,在Backups, Master/Slave 和 Master/Master的架构下,都是会丢的。

所以说,如果你要让你的备份系统随时都可以用,那么你就要让它随时都Live着,而随时都Live着的多结点系统,基本上就是一个分布式的高可用的系统。因为,数据丢失的原因有很多种,比如掉电、磁盘损坏、中病毒等等,而那些流程、规则、人肉检查、权限系统、checklist等等都只是让人不要误操作,都不管用,这个时候,你不得不用更好的技术去设计出一个高可用的系统!别无它法。(重要的事,得再说一篇)

另外,你可以参看我的另一篇《关于高可用系统》,这篇文章中以MySQL为例,数据库的replication也只能达到 两个9。

AWS 的 S3 的的高可用是4个加11个9的持久性(所谓11个9的持久性durability,AWS是这样定义的,如果你存了1万个对象,那么丢一个的时间是1000万年),这意味着,不仅仅只是硬盘坏,机器掉电,整个机房挂了,其保证可以承受有两个设施的数据丢失,数据还是可用的。试想,如果你把数据的可用性通过技术做到了这个份上,那么,你还怕被人误删一个结点上的数据吗?

非技术方面

故障反思

一般说来,故障都需要反思,在Amazon,S2以上的故障都需要写COE(Correction of Errors),其中一节就是需要Ask 5 Whys,我发现在Gitlab的故障回顾的blog中第一段中也有说要在今天写个Ask 5 Whys。关于Ask 5 Whys,其实并不是亚马逊的玩法,这还是算一个业内常用的玩法,也就是说不断的为自己为为什么,直到找到问题的概本原因,这会逼着所有的当事人去学习和深究很多东西。在Wikipedia上有相关的词条 5 Whys,其中罗列了14条规则:

  1. 你需要找到正确的团队来完成这个故障反思。
  2. 使用纸或白板而不是电脑。
  3. 写下整个问题的过程,确保每个人都能看懂。
  4. 区别原因和症状。
  5. 特别注意因果关系。
  6. 说明Root Cause以及相关的证据。
  7. 5个为什么的答案需要是精确的。
  8. 寻找问题根源的步骤,而不是直接跳到结论。
  9. 要基础客观的事实、数据和知识。
  10. 评估过程而不是人。
  11. 千万不要把“人为失误”或是“工作不注意”当成问题的根源。
  12. 培养信任和真诚的气氛和文化。
  13. 不断的问“为什么”直到问题的根源被找到。这样可以保证同一个坑不会掉进去两次。
  14. 当你给出“为什么”的答案时,你应该从用户的角度来回答。

工程师文化

上述的这些观点,其实,我在我的以住的博客中都讲过很多遍了,你可以参看《什么是工程师文化?》以及《开发团队的效率》。其实,说白了就是这么一个事——如果你是一个技术公司,你就会更多的相信技术而不是管理。相信技术会用技术来解决问题,相信管理,那就只会有制度、流程和价值观来解决问题

这个道理很简单,数据丢失有各种各样的情况,不单单只是人员的误操作,比如,掉电、磁盘损坏、中病毒等等,在这些情况下,你设计的那些流程、规则、人肉检查、权限系统、checklist等等统统都不管用,这个时候,你觉得应该怎么做呢?是的,你会发现,你不得不用更好的技术去设计出一个高可用的系统!别无它法。(重要的事得说三遍)

事件公开

很多公司基本上都是这样的套路,首先是极力掩盖,如果掩盖不了了就开始撒谎,撒不了谎了,就“文过饰非”、“避重就轻”、“转移视线”。然而,面对危机的最佳方法就是——“多一些真诚,少一些套路”,所谓的“多一些真诚”的最佳实践就是——“透明公开所有的信息”,Gitlab此次的这个事给大家树立了非常好的榜样。AWS也会把自己所有的故障和细节都批露出来。

事情本来就做错了,而公开所有的细节,会让大众少很多猜测的空间,有利于抵制流言和黑公关,同时,还会赢得大众的理解和支持。看看Gitlab这次还去YouTube上直播整个修复过程,是件很了不起的事,大家可以到他们的blog上看看,对于这样的透明和公开,一片好评。

(全文完)


关注CoolShell微信公众账号可以在手机端搜索文章

(转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)

——=== 访问 酷壳404页面 寻找遗失儿童。 ===——
好烂啊有点差凑合看看还不错很精彩 (71 人打了分,平均分: 4.83 )
Loading...

从Gitlab误删除数据库想到的》的相关评论

  1. 耗子哥总结的很棒~只恨当初耗子哥来趋势做分享的时候没多交流交流。
    我也干过一年的运维,也出现过一个region的数据库挂掉的问题,还好是做了HA的,挂了一个还有另外一台顶着,担惊受怕的恢复着另外一台数据库,都做另外一台再挂掉(流量太大了,怕撑不住)就导流量到其他region的准备了。

  2. “多一些真诚”真是最好的公关。这种事情敢直播玩,除了「真诚」,还说明人家有足够的技术实力和自信。几年前,听过的 VMWARE 上海研发中心的技术分享,提到灾备问题,那小哥说,「我们有跨机架、跨数据中心、跨区域,甚至跨大洲的各种备份方案,可以抵御除了《2012》以外的任何灾难」,我信了。不得不承认,正真的吹牛逼确实需要技术实力。

  3. 大多数的数据库备份很难配置,操作繁琐。
    至今还用命令方式导出数据,真是IT行业耻辱

    1. 我也正想说这个,看见你的评论。飞机应该也设计一个灯,一切正常可以倒车起飞。如果灯报警,再去一个个检查几十个仪表。

    2. 没有可靠的技术手段省掉人力,只能找可靠的人同时保证可靠的健康状况和精力来保证

  4. 没专职运维这一角色 但曾也负责过相关的事务好几年 文中有一句话 值得深省:“越是喜欢敲命令的 运维能力越弱 越是善用自动化的 运维能力越强” 看来以前走的路 方向不对啊

  5. 设计一个更好的高可用系统的思路是对的,即防未病–尽可能避免触发数据恢复流程。但从逻辑上讲,绝对的不掉数据是不可能的。因为人们也有快速完成“rm -rf”的需求。理论上每次删除前都可以触发一次秒级快照(这也是事实上的最佳解决方案),但在实际应用中依然有很多因素导致结果不尽如人意。

  6. 陈老师您好,感谢您的文章,让我学到了很多东西,特别是关于人肉运维那块的反思。
    也感谢您让我知道了5 Whys的问题分析方法。
    我在看5 Whys部分的时候感觉Wikipedia的14条原则中第8条有点难以理解,就找了原文看了下,感觉这里是不是应该翻译为“一步接一步”或者其他更合适的词语。另外我感觉第13条翻译是不是也与原文有点差异。
    很高兴与您交流,期望得到您的解答。

    1. 赞同,“寻找问题根源的频”这里的“频”不好理解。翻译成“一步一脚印地寻找问题根源”或许更好。

  7. 不太同意最后的观点,就像是路由器一样,专业路由的WEB有几个人在用啊,这种基础性的东西越简单越不容易出错,你再拿个运维工具来搞这些事情,只会造成更多的问题。

  8. 这其实是个低级失误,不是单纯的技术问题。说明即使是gitlab这个级别的维护也存在很多管理问题:

    1. 数据库的备份恢复定期要检查、测试,故障处理和备份数据恢复操作定期要进行训练和验证的。怎么可能多重安全设置都同时不起作用? 这说明整个系统的灾备方案根本就不健全。

    2. 重大操作必须有确认环节,即使是纯人肉维护只要训练到位也最多是比较慢一点而已,绝不会出这种问题。 当然如果有合适的工具来避免手动失误的发生那是更好。

  9. 谢谢陈老师的总结!个人感觉组件的高可用也不能完全解决人为的误操作。即使是S3这种高可用的系统,也还是怕误操作(人为、脚本bug),这种误操作在逻辑上对系统来说是正常的(区分于掉电等错误)。所以还是需要权限管控和Review(代码和操作)。

    1. 其一、解决人为的误操作的最佳途径是用更高级的工具。
      其二、高可用解决的问题是整个机器甚至整个机房坏掉数据还不丢,这已覆盖了人员误操作这种错误级别了。
      其三,无论怎么样,生产系统的变更不应该是以敲命令的方式进行的。

      1. 涉及到重要数据的时候,也不是许多人都敢使用高级工具的,还是靠人上肉去做,事故场合细节可能没有考虑到,工具比人肉更容易引起问题。

        以前搞了数据回滚,多数情况下工具可以解决一些问题,但是紧急情况下以及特殊场合,谁敢用工具?说起来容易做起来难。亚马逊云计算算是业界拔尖的吧,很多时候也是靠人肉运维的。至于亚马逊中国实力水平,我就不吐槽了。

  10. 原本我的注意力是在這個事件上…後來看到Google doc文檔後,我很好奇的點了進去…然而文檔不存在….

    以為完了?NO!我後遲鈍反應過來我在大陸誒,為啥打得開Google Docs?

  11. 迷失在终端中,的确很尴尬。以前做某视频服务器的业务调整,虽然只有六台,一个小节点,而且都标记了明确可辨别的hostname,没能战胜困意,还好有个吃饭时候回顾操作的习惯。还是工具省心。

  12. 收益良多!赞同人维护代码,代码管理机器的做法,而且线上操作必须是被记录和追踪的。在我看来,软件开发从头到尾,无论是代码的修改线上配置的变更,都应该是可以追踪的,并且必须有plan B进行保底,必要时还应对步骤进行演练和确认。

    但对于技术公司应该更多的相信技术,而非管理,还是有点不同看法。因为存在人维护代码,就需要有codereview,有checklist, 有流程化的管控来把握前一个环节,保证最终生产的代码是正确高效的,这样才能保证代码管理机器的过程是正确的,结果是预期的。所以管理可以简化宽松,但不能忽视,应该是对技术的一个补充完善。

    当然,我理解强调技术的原因,在于不断通过技术的改进,不断提高系统的可用性,无论自动化维护,还是原始的命令行维护,无论是代码出了问题,还是人出了问题,都很难玩死一个系统,这才是我们应该追求的!

  13. 完全live的同步复制也不一定能解决误删,因为删除的对象也在各节点间同步进行的。。而真正有效的备份机制恰恰能还原出历史数据。。

  14. 关于多窗口,我一般都是用不同的终端。
    生产环境用putty,字体用system,给人一种严肃的感觉;
    其它环境用xshell,字体用consilas,字体圆润,时间久了不会视觉疲劳。

  15. 人管代码,代码管机器,首先得有管得住代码的实力。n多人口若悬河说高可用,但落到实处,代码根本不可用。

  16. Gitlab 挂掉的那天我正好在 clone 一个项目到本地,长时间的等待修复并为是我感到恼火,可见透明性的好处。

    另外,陈皓前辈,我把 此文章放到了 linkedinfo.co,我的一个业余小项目。如您觉得不妥,请随时联系我将之撤下。

    linkedinfo.co 是一个集合了各类优秀技术文章的站点,它并不展现全文,所有条目都附上作者与原文链接,读者最终都会进入到作者原文的站点。做这个项目的初衷是想方便自己且方便其他想学习的朋友,能更方便地找到自己感兴趣的技术文章。同时这也是一个我自己练习的过程,比如将正在学习的 Semantic Web 技术用来更好地连接不同的知识。

    各位感兴趣的朋友可以去看看,非常希望能得到你们的意见与建议(可在 about 页面留言)。

  17. 陈皓前辈,我把 coolshell.cn 的一些文章放到了 linkedinfo.co,我的一个业余小项目。如您觉得不妥,请随时联系我将之撤下。

    linkedinfo.co 是一个集合了各类优秀技术文章的站点,它并不展现全文,所有条目都附上作者与原文链接,读者最终都会进入到作者原文的站点。做 linkedinfo 的初衷是想方便自己且方便其他想学习的朋友,能更方便地找到自己感兴趣的技术文章。同时这也是一个我自己练习的过程,比如将正在学习的 Semantic Web 技术应用到 linkedinfo 来更好地连接不同的知识。

    各位感兴趣的朋友可以去 linkedinfo.co 看看,非常希望能得到你们的意见与建议(可在 about 页面留言)。

  18. 哈哈,学习到了,最重要的一句话:生产系统的变更不该由敲命令的方式进行!生产系统的变更不该由敲命令的方式进行!生产系统的变更不该由敲命令的方式进行!

  19. 我反对的一点是,安全问题是无法用技术解决的,如果没有警察只有锁,你还觉得这个世界安全吗?

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*