阿里、蚂蚁、晟腾、中科加禾精彩分享 AI 基础设施洞见,现购票可享受 9 折优惠 |AICon 了解详情
写点什么

左耳朵耗子:我对 GitLab 误删除数据库事件的几点思考

  • 2017-02-06
  • 本文字数:5891 字

    阅读完需:约 19 分钟

更多左耳朵耗子的独家干货,请订阅极客时间出品的陈皓全年专栏《左耳听风》,一次订阅、永久阅读。即日起,戳此订阅立享以下两大福利:

福利一:原价 ¥199/ 年,极客时间新用户注册立减 ¥30

福利二:每邀请一位好友购买,你可获得 36 元现金返现,多邀多得,上不封顶,立即提现(提现流程:极客时间服务号 - 我的 - 现金奖励提现)

太平洋时间 2017 年 1 月 31 日晚上,GitLab 通过推特发文承认 300GB 生产环境数据因为 UNIX SA 的误操作,已经被彻底删除(后发文补充说明已经挽回部分数据),引起业界一片哗然。知名博主陈皓在其博客中详细回顾了此次事件,并做了思考和总结,聊聊架构经原作者授权发布此文。

昨天,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 (这个列表可能还会在不断更新中)。

  • infrastructure#1094 – Update PS1 across all hosts to more clearly differentiate between hosts and environments
  • infrastructure#1095 – Prometheus monitoring for backups
  • infrastructure#1096 – Set PostgreSQL’s max_connections to a sane value
  • infrastructure#1097 – Investigate Point in time recovery & continuous archiving for PostgreSQL
  • infrastructure#1098 – Hourly LVM snapshots of the production databases
  • infrastructure#1099 – Azure disk snapshots of production databases
  • infrastructure#1100 – Move staging to the ARM environment
  • infrastructure#1101 – Recover production replica(s)
  • infrastructure#1102 – Automated testing of recovering PostgreSQL database backups
  • infrastructure#1103 – Improve PostgreSQL replication documentation/runbooks
  • infrastructure#1104 – Kick out SSH users inactive for N minutes
  • infrastructure#1105 – Investigate pgbarman for creating PostgreSQL backups

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

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

我的思考:技术方面 人肉运维

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

  1. 如果说对代码的改动都是一次发布的话,那么,对生产环境的任何改动(包括硬件、操作系统、网络、软件配置……),也都算是一次发布。那么这样的发布就应该走发布系统和发布流程,要被很好的测试、上线和回滚计划。关键是,走发布过程是可以被记录、追踪和回溯的,而在线上敲命令是完全无法追踪的。没人知道你敲了什么命令。
  2. 真正良性的运维能力是——人管代码,代码管机器,而不是人管机器。你敲了什么命令没人知道,但是你写个工具做变更线上系统,这个工具干了什么事,看看工具的源码就知道了。

另外,有人说,以后不要用 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 条规则:

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

工程师文化

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

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

事件公开

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

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

2017-02-06 16:524782

评论

发布
暂无评论
发现更多内容

LabVIEW实现应用程序停止或退出

不脱发的程序猿

LabVIEW

AtomicIntegerArray源码分析与感悟

爱好编程进阶

Java 面试 后端开发

世界读书日:我想推荐这几本书

宇宙之一粟

书籍推荐 书单 4月月更

一个快速追踪密切接触者的开源脚本方案

冯骐

Python 数据分析 流调 密接 新冠疫情

读《Software Engineering at Google》(14)

术子米德

架构师成长笔记

[Day22]-[链表]相交链表

方勇(gopher)

链表 LeetCode 算法和数据结构

redis优化系列(二)Redis主从原理、主从常用配置

乌龟哥哥

4月月更

甲辰篇 創世紀《「內元宇宙」聯載》

因田木

元宇宙 貴人網 電子書

将新增和编辑的数据同步更新到列表

岛上码农

flutter ios开发 安卓开发 4月月更 跨平台开发

Robot OS系统架构设计

轻口味

android 架构 Robot 4月月更

采用百度飞桨EasyDL完成指定目标识别

DS小龙哥

4月月更

[Day23]-[数据结构]手写LRU

方勇(gopher)

LeetCode LRU 数据结构算法

顶级元宇宙游戏Plato Farm,近期动作不断利好频频

小哈区块

解决方案架构师的小锦囊 - 架构图的 5 种类型

亚马逊云科技 (Amazon Web Services)

技术 职业 亚马逊云科技

自动化的艺术

俞凡

架构 大厂实践 PayPal

k8s client-go源码分析 informer源码分析(1)-概要分析

良凯尔

Kubernetes 容器 云原生 Client-go

“亿”点点技术情怀

不脱发的程序猿

程序员 程序人生 技术情怀

在docker上编译openjdk8

程序员欣宸

Java JVM 4月月更

Plato Farm-以柏拉图为目标的农场元宇宙游戏

西柚子

读《Software Engineering at Google》(13)

术子米德

架构师成长笔记

LabVIEW控制电脑关机、休眠、注销和重启

不脱发的程序猿

LabVIEW LabVIEW控制电脑

初探 Lambda Powertools TypeScript

亚马逊云科技 (Amazon Web Services)

typescript Serverless Lambda AWS

2021年秋招,薪资排行NO

爱好编程进阶

Java 面试 后端开发

22道Java Spring Boot高频面试题

爱好编程进阶

Java 面试 后端开发

Pandas+Numpy+Sklearn随机取数

Peter

Python pandas

Pandas索引的操作

Peter

Python pandas

读《Software Engineering at Google》(11)

术子米德

架构师成长笔记

读《Software Engineering at Google》(12)

术子米德

架构师成长笔记

我是如何用 Amazon Serverless 创建一个门铃的

亚马逊云科技 (Amazon Web Services)

Serverless Lambda AWS showdev

解锁OpenHarmony技术日!年度盛会,即将揭幕!

OpenHarmony

大会 OpenHarmony

机器学习算法:关联规则分析

Peter

Python 机器学习 算法

左耳朵耗子:我对GitLab误删除数据库事件的几点思考_数据库_陈皓_InfoQ精选文章