提交需求
*
*

*
*
*
立即提交
点击”立即提交”,表明我理解并同意 《美创科技隐私条款》

logo

    产品与服务
    解决方案
    技术支持
    合作发展
    关于美创

    申请试用
      详述Gitlab 300G数据误删背后的故事
      发布时间:2017-02-13 阅读次数: 1358 次

      鸡年刚开年,有一家IT公司和该公司的系统管理员火了。

      2017年1月31日晚上,著名的源码托管平台GitLab.com一位忙碌一整天、身心疲惫的系统管理员,在进行数据库复制过程中不小心在一台错误的服务器上不慎删除了约300GB的数据,当他清醒过来,并及时取消rm -rf删除命令后,仅4.5GB 数据被保留了下来。

      经过漫长的抢修恢复,GitLab 数据库虽然恢复了,但最近的数据还是6小时前备份的。

      造成的损失是惨烈的:

      1.6小时的数据丢失

      2.大约丢失5037个项目(4613个常规项目,74个fork, 350个import)

      3.可能丢失了707个用户

      4.网站宕机超过12个小时

      5.大约丢失4979个提交记录

      而GitLab 号称的五重备份机制:

      常规备份(24小时一次)

      自动同步、LVM快照(24小时一次的)

      Azure 备份(支队NFS启用,数据库无效)

      S3 备份

      在这个关键时候,全部都失效了!!

       

      这个消息一出,网上炸开了锅。

      数据备份是无用功?数据库安全运维又该注意什么?

      下文,美创科技技术团队资深运维专家详细分析,300G数据误删故障背后的故事。

      在详述故障之前,有必要先给GitLab后续故障处理点个赞。GitLab 在 Youtube 上直播了整个数据恢复过程(GitLab 心真大),第一时间在Google Doc对整个事件进行了回顾,事后又发了一篇博客来说明这个故障,相较于别的公司对故障遮遮掩掩的做法,必须给GitLab如此透明正面对待故障的态度竖大拇指。

      详述Gitlab 300G数据误删背后的故事

      正文来了,借鉴GitLab博客上对故障的说明,描述一下整个故障:

      一个叫YP的同学通宵在给GitLab的线上数据库做一些负载均衡的工作,由于前期某些原因导致有个staging的数据库(db2.staging)已经落后生产库4GB的数据,于是YP同学在Fix这个staging库的同步问题的时候,发现db2.staging有各种问题都和主库无法同步,在这个时候,YP同学已经工作的很晚了,在尝试过多个方法后,发现db2.staging都hang在那里,无法同步,于是他想把db2.staging的数据库删除了,这样全新启动一个新的复制。结果,删除数据库的命令错误的敲在了生产环境上(db1.cluster),导致整个生产数据库被误删除。等到YP同学发现并终止了这个操作后发现,310GB的数据,只剩4.5GB了,99%的数据已经被误删除。

      在官方的故障报告里,GitLab针对数据库进行了5重备份机制,我们来解读一下:

      https://docs.google.com/document/d/1GCK53YDcBWQveod9kfzW-VCxIABGiryG7_z_6jHdVik/pub

      1. LVM snapshots are by default only taken once every 24 hours. YP happened to run one manually about 6 hours prior to the outage

      LVM的快照是每24小时执行一次,YP同学在6小时前手工执行过一次。这也是本次故障唯一能用的备份。

      解读:LVM快照备份是常见的一种备份机制。但由于其“通用性”并不适合所有对象的备份,如高并发的数据库。另外,LVM快照备份由于备份的“透明性”,也很难去真正验证备份的有效性和正确性。但作为本次故障唯一能用的备份,LVM快照备份还是功不可没!墨菲定律没有把所有的窗都关闭。

      2. Regular backups seem to also only be taken once per 24 hours, though YP has not yet been able to figure out where they are stored. According to JN these don’t appear to be working, producing files only a few bytes in size.

      常规备份也是24小时执行一次,不过YP同学一开始找不到它在哪,等找到了发现备份文件只有几个字节。

      解读:这说明YP同学甚至GitLab团队根本没有做过备份的恢复测试。

      3. Disk snapshots in Azure are enabled for the NFS server, but not for the DB servers.

      Azure 的备份只对NFS服务器启用了磁盘快照,没有在DB服务器启用磁盘快照。

      解读:现在云是热点,很多企业都在把系统往云上迁移,使用云服务商提供的备份服务,这就必须保证云备份的覆盖度、安全性和有效性。很显然,GibLab在Azure云上备份的覆盖度不全,缺少对数据库服务器的备份,导致需要快速恢复时无法使用。所以,这一层备份相当于一个摆设而已。

      4. The synchronisation process removes webhooks once it has synchronised data to staging.

      同步进程在一次同步完成后就把 webhooks 删了。

      解读:从程序设计上看,理想状态下,同步完成并校验无误后删除webhooks本身并没有什么问题。但是实际工作中,往往就没有理想状态。如果考虑到可能发生的故障,这种webhooks至少要保留3份甚至更多。hacker news讨论区里面有一个哥们说起他多年前的类似经历:

      My very first job - ~25 years ago.

      Destroyed the production payroll database for a customer with a bug in a shell script.

      No problem - they had 3 backup tapes.

      First tape - read fails.

      Second tape - read fails.

      Third tape - worked.... (very nervous at this point).

      这也就是为什么我们要保留多重备份的原因,因为总有我们意想不到的情况发生。

      5. The replication procedure is super fragile, prone to error, relies on a handful of random shell scripts, and is badly documented

      备份过程是依赖一些凌乱的SHELL脚本,非常脆弱且容易出错,而且没有良好的文档支持。

      解读:成熟的运维管理流程、丰富的脚本化工具、完善的文档是体现一个运维团队成熟度的3个重要指标。尤其是当管理的服务器越来越多时,仅仅依靠零散的shell脚本做运维,显然是不够的。

      6. Our backups to S3 apparently don’t work either: the bucket is empty

      S3备份是空的。

      解读:备份是空的,很久没有发现,说明GitLab的运维团队平常并不检查这些备份集。

      虽然设置了多重备份的,唯一可用的是YP同学在6小时前手工执行的一个LVM的快照。最终,GitLab从db1.staging上把6个小时前的数据拷贝回来,但是由于备份节点的性能相对较差,拷贝时间较长导致恢复时间较久,最终导致6个小时的数据丢失。

      故障全过程,大致如上文所述。从这个故障中,得到了哪些教训,学习到哪些经验呢?接下来,从运维管理和版本控制的角度来聊一聊。

      l 运维管理:

      1. 高风险操作的运维机制

      我们提倡DBA或者运维人员的工作一定要设置A、B角,重要操作必须同时到场,特别是晚上通宵加班,任何操作都都需要A、B角相互监督进行,没有人可以保证自己的操作是一定正确的。本次故障最大的起因,我们觉得应该就是运维人员长时间工作+操作窗口的切换导致故障的发生。

      2. 良好的文档习惯

      一般来说,重大的变更操作或者故障处理操作,原则上需要先制定方案,在形成方案文档的情况下,依据文档进行操作。有些技术人员可能会觉得自己的技术非常的牛,做任何操作都是直接在生产环境噼里啪啦一顿命令敲,但是,再牛的技术也抵挡不住一个误操作。作为甲方工程师,你需要对自己的操作负责任,作为乙方工程师,你需要对自己的客户负责任,再边缘的生产系统,也承受不起一次误操作带来的伤害。所以,灾备流程必须文档化,日常服务器维护流程中的注意事项也写成 checklist(或脚本化)。

      3. 危险命令的避讳

      本次操作就是因为运维人员在错误的窗口敲下了rm –rf这个命令,作为运维人员,看到这个命令不寒而栗。作为一线的运维人员,有时候我们不得不进行一些危险的命令操作,比如 kill -9,rm –rf *, chown –R ,chmod –R 等等。但是很多命令是可以用一些更加相对安全的命令替代,比如rm –rf * 很多时候,用?替代*更加的安全,对于权限赋予的时候一般严禁用-R参数等等。如果是针对一些避无可避的危险操作,那就需要A、B角共同参与完成。

      4. 良好的备份恢复机制

      平心而论,虽然本次故障因为运维人员误操作而产生,但是如果有一个良好的备份恢复机制,我们是否可以在最大程度上缩短恢复时间和数据丢失呢,所谓的5重备份又有哪一重备份完全成功的呢,又有哪一重是在定期做恢复演练的呢?

      定期做灾备演习,校验是否可以正确的从备份中恢复,以及此过程需要多少时间和资源,是备份恢复机制的重要组成部分。

      5. 建立完善的容灾机制

      一个系统是需要做数据备份的,但是,当我们回过头来看GitLab的5重备份机制,就算所有的备份都可用,也一定会存在有数据的丢失,或许也会有很多问题。原因如下:

      备份通常意味着丢失数据。因为备份通常来说都是周期性或者阶段性的的,所以,一旦你需要用到备份进行恢复,从备份时间到故障时间的数据都丢失了。

      其次,很多银行金融类客户都搭建有非常完善的灾备的数据中心,但是灾备的数据中心没有一天真正工作过。等真正灾难来临需要切换到灾备机房运行时,你会发现你所设计的精良的“备份系统”或是“灾备系统”并不给力。

      美创科技DBRA灾备产品能够保证数据0丢失、数据实时捕捉传送、误操作快速回退,可以在不影响生产系统正常运行的的情况下,随时校验容灾系统的数据是否正常。

      6. 建立完善的应急流程和机制

      再好的系统,也肯定存在故障点,也肯定会有误操作,而作为运维人员,在出现误操作或者严重故障的时候,如何做到处乱不惊,在第一时间对故障或者事故进行及时响应,需要认真思考。建立完善的应急流程和应急故障处理机制,定期的演练应急流程,做到真正故障发生的时候保持一颗平常心。

      l 版本控制:

      1. 建立Shell脚本的版本管理

      从官方的故障报告中我们可以看到,备份过程是依赖一些凌乱的、脆弱并且很容易出错的SHELL脚本,没有良好的文档支持。作为一个一线DBA,我见过太多类似的情况,很多客户的生产环境上就是一些各个运维人员依据自己的习惯写的几个零碎的脚本在跑。事实上,就算是小小的shell scripts,我们一样需要用心对待。尤其是用于生产备份的脚本,每次运行的结果如何,有没有日志输出,有没有Monitoring 和 Alert,每次修改过后是否依然还能正确运行。

      我们提倡,对每一个在生产上运行的脚本程序,要像项目代码一样做到版本管理和文档管理。保证每一次脚本修改都要目的明确、注释明确、文档明确。

      2. 开发代码的版本控制

      GitLab是一个用于版本管理系统的开源项目。很多个人和团队的项目代码就托管在上面。庆幸的是,目前来看最终丢失一小部分线上数据中,主要是6个小时的issues、comments、merge requests等,代码和wiki文档不受影响。从开发团队的角度看,即便对于 GitLab这样的成熟团队也难免会出现如此重大的事故,那么如果保障自己的项目代码不受类似问题的影响也是需要重新思考的问题。

      我想,每天定时在本地保留一份最新的代码或许也是一个不错的建议^-^。

      3. 提倡 IAC的最佳实践

      Infrastructure As Code,这个就不多说了,大家都在DevOps,有多重要自行掂量。

      最后提几个问题大家反思一下:

      你们的核心数据库距离上一次恢复测试有多久?

      如果你们的生产系统完全崩溃,你能保证多久完成业务恢复,数据丢失多少?

      你们的恢复流程能够保障绝对正确不出问题吗?

      你们的DBA是否存在单点故障,如果失踪了,系统还能照常运行吗? 

      免费试用
      服务热线

      马上咨询

      400-811-3777

      回到顶部