GitLab二月一日事故报告

sorra 发表于 02/22 18:18 修改于 02/22 18:20 阅读数277

译者TimWei 出处https://github.com/TimWei/Gitlab_database_incident_170201 Original Post

GitLab.com 数据库事故 - 2017/01/31

备注: 此事故影响了数据库 (包含 issues 与 merge requests) 但无影响到 GIT Repo's (repositories 与 wikis)。

YouTube直播 - 瞧瞧我们如何思考与解决问题

影响

  1. 六小时左右的数据丢失
  2. 粗估有4613个普通project丶74 forks及350 imports的数据丢失,共计影响了5037个project. 由於 Git repositorie 并没有丢失,如project的User/Group於数据丢失前已存在,project将可以被重建,但project issues之类的无法重建
  3. 接近5000条留言丢失
  4. 从Kibana的记录上,粗估有707名用户活跃度受影响
  5. 於01/31 17:20之後建立的WebHooks丢失

时间轴(世界协调时)

  1. 2017/01/31 16:00/17:00 - 21:00
  • YP正在staging调适pgpool与replication,并创建了LVM快照同步production数据至staging,希望能以此快照创建其它复本,这些操作大概在数据丢失前六小时完成了。
  • LVM快照所创建的复本并没有照着YP预期般的有用,在恶意流量与GitLab.com的高负载下,创建replication非常耗时且容易产生问题。YP需要另外一位同事的协助,但该同事该日并无上班,所以此工作中断了。
  1. 2017/01/31 21:00 -恶意流量造成的数据库高负载-Twitter|Slack
  • 依照IP地址阻挡恶意用户流量
  • 移除了一个将repository当成某种形式CDN的用户,该用户从47000个不同的IP位址登入(造成数据库高负载),这是与设备组与技术支持组沟通後的决定。
  • 移除了恶意流量的用户 - Slack
  • 数据库负载回到正常,检视了PostgreSQL的状况後,排除了许多的dead tuples
  1. 2017/01/31 22:00 - PagerDuty告警replication延迟 -Slack
  • 开始修复db2,此时db2延迟了约4GB的数据
  • 因db2.cluster同步失败,清空了/var/opt/gitlab/postgresql/data
  • db2.cluster无法连线至db1,提示max_wal_senders配置值过低,此配置用以限制WAL连线数(通常配置值=replication数量)
  • YP调整了db1的max_wal_senders至32,重新启动PostgreSQL
  • PostgreSQL 提示连线数过多,启动失败
  • YP调整max_connections,从8000改为2000,重新启动PostgreSQL (尽管配置8000已经接近一年了)
  • db2.cluster依旧同步失败,这次并无产生任何错误提示,就只是挂在那
  • 在早些时间前(大概当地时间23:00),YP就说时间太晚了,他该离线了,却因为处理这些突发的同步问题而无法离线。
  1. 2017/01/31 23:00左右
  • YP想到可能是因为data文件夹存在,使得pg_basebackup出问题,决定删除整个data文件夹。几秒後他发现自己在db1.cluster.gitlab而不是db2.cluster.gitlab.com
  • 2017/01/31 23:27 YP - 中止删除,但是太迟了。310 GB左右的数据被删到只剩下4.5 GB - Slack

修复过程 - 2017/01/31 23:00 (从约17:20 UTC左右开始记录)

  1. 建议修复的方法
  • 导入db1.staging.gitlab.com的数据(约六小时前的数据)
  • CW: Staging环境并没有同步WebHook
  • 重建LVM快照(约六小时前的快照)
  • Sid: 试着回覆删除的文件如何?
  • CW: 不可能! `rm -Rvf` Sid: 好吧
  • JEJ: 可能太晚了,但有没有可能将硬盘快速的切换成read-only?或process正在使用遭删除文件,有可能存在遭删除文件的file descriptor,根据http://unix.stackexchange.com/a/101247/213510
  • YP: PostgreSQL并不会随时都开启这些文件,所以这办法没效;而且Azure删除数据的速度太快了,也不会留存副本。也就是说,遭删除的数据没有办法从硬盘恢复。
  • SH: 看起来db1 staging运行了独立的PostgreSQL process在gitlab_replicator文件夹。会同步db2 production的数据。但由於之前replication延迟的关系,db2在 2016-01-31 05:53就砍了,这也使得同步中止。好消息是我们可以用在这之前的备份来还原WebHook数据。
  1. 采取行动
  • 2017/02/01 23:00 - 00:00: 决定将db1.staging.gitlab.com的数据导入至db1.cluster.gitlab.com(production环境),这将会使数据回到六小时前,并且无法还原WebHooks,这是唯一能取得的快照。YP自嘲说今天最好不要让他再执行带有sudo的指令了,将复原工作交给JN处理。
  • 2017/02/01 00:36 - JN: 备份 db1.staging.gitlab.com 数据
  • 2017/02/01 00:55 - JN: 将 db1.staging.gitlab.com同步到 db1.cluster.gitlab.com
  • 从staging /var/opt/gitlab/postgresql/data/ 复制文件至production /var/opt/gitlab/postgresql/data/
  • 2017/02/01 01:05 - JN: 使用nfs-share01 服务器做为/var/opt/gitlab/db-meltdown的暂存空间
  • 2017/02/01 01:18 - JN: 复制剩馀的production环境数据,包含压缩後的pg_xlog(压缩後为 '20170131-db-meltodwn-backup.tar.gz')
  • 2017/02/01 01:58 - JN: 开始从stage同步至production
  • 2017/02/01 02:00 - CW: 更新发布页面解释今日状况。 Link
  • 2017/02/01 03:00 - AR: 同步率大概有50%了 (依照文件量)
  • 2017/02/01 04:00 - JN: 同步率大概56.4% (依照文件量)。数据传输速度变慢了,原因有两个,us-east与us-east2的网路I/O与Staging的硬盘吞吐限制(60 Mb/s)
  • 2017/02/01 07:00 - JN: 在db1 staging /var/opt/gitlab_replicator/postgresql内发现一份未过滤(pre-sanitized)的数据副本,在 us-east启动了db-crutch VM来备份该数据。 不幸的是,这个系统最多120GM RAM,无法支持production环境负载,这份副本将用来检查数据库状态与汇出WebHook
  • 2017/02/01 08:07 - JN: 数据传输太慢了: 传输进度用数据大小来看的话才42%
  • 2017/02/02 16:28 - JN: 数据传输完成
  • 2017/02/02 16:45 - 开始进入重建阶段
  1. 重建阶段
  1. 数据重建後的待办事项
  • 创一个Issue去改变终端机的格式或颜色,让你能清楚的知道自己正在身处Production环境或Staging环境(红色:Production环境 黄色:Staging环境)。并默认所有使用者在命令栏显示完整的主机名称(例如: 用"db1.staging.gitlab.com"取代原本的"db1"): https://gitlab.com/gitlab-com/infrastructure/issues/1094
  • 或许禁止rm -rf掉PostgreSQL的data文件夹? 我不确定这样是否恰当,如果我们有更完善的replication後,是否还有必要这麽做。
  • 增加备份预警: 检查S3之纇的储存空间,增加曲线图来监控备份文件大小,当跌幅超过10%时会发出警告: https://gitlab.com/gitlab-com/infrastructure/issues/1095
  • 考虑新增最近一次备份成功的时间到数据库内,管理者就能轻松的检视(此为顾客建议 https://gitlab.zendesk.com/agent/tickets/58274)
  • 试着了解为何PostgreSQL会在max_connections配置为8000时发生故障,尽管他从 2016-05-13就是这个配置。此次事件中,有很大一部份令人沮丧的原因都来自这个突然发生的故障。: https://gitlab.com/gitlab-com/infrastructure/issues/1096
  • 看看如何建立WAL archiving或PITR(point in time recovery),这在更新失败时也相当有帮助: https://gitlab.com/gitlab-com/infrastructure/issues/1097
  • 建立排错指南,用户之後说不定也会碰到一样的问题
  • 实验以AzCopy来对传数据中心的资料: Microsoft説这应该比rsync快多了 *这看起来是个Windows才有的东西,然而我们并没有任何Windows专家(或是任何够熟悉,懂得如何正确测试的人)

遭遇之问题

  1. LVM快照默认24小时一次,是YP在六小时之前手动执行了一次
  2. 常态备份似乎也是24小时执行一次,虽然YP也不知道到底存在哪里;根据JN的说法,备份是无效的,备份的结果只有几Bytes。
  • SH: 看起来pg_dump是失败的,PostgreSQL 9.2二进位文件取代了 9.6的二进位文件,因为omnibus需配置data/PG_VERSION为9.6,而workers上并没有这个配置文件所以使用了默认的9.2版本,没有结果也不会产生警告,而更旧的备份则可能是被Fog gem给清除了
  1. Azure硬盘快照只在NFS服务器启动,在数据服务器并无启动
  2. 当同步至Staging时并不会同步WebHooks,除非我们能从常态备份中拉取,不然将会丢失
  3. 产replication的程序超级脆弱丶容易出错丶需依靠一些不一定的Shell脚本丶缺少文件
  • SH: 从这次事件後我们学到了如何翻新Staging的数据库,先对gitlab_replicator的文件夹做快照,更改replication设定,然後重新启动一台新的PostgreSQL服务器。
  1. 我们到S3的备份显然也没有作用,整个都是空的
  2. 我们并没有一个稳固的预警,来监控备份失败的状况,将会着手研究

总的来说, 我们部属了五种备援技术,没有一个可靠或是发挥大用处 => 六小时前做的备份反而还较有用

http://monitor.gitlab.net/dashboard/db/postgres-stats?panelId=10&fullscreen&from=now-24h&to=now

外部协助

HugOps

(将任何热心关心此事的人加入至此,推特或是任何来源)

Stephen Frost

https://twitter.com/net_snow/status/826622954964393984 @gitlabstatus 嘿,我是PG的提交者,也是主要的贡献者之一,非常喜欢你们所做的一切,有需要我帮忙的话随时连络我,我很乐意帮忙。

Sam McLeod

Hey Sid, 很遗憾听到你遭遇的数据库/LVM问题,偶而就是会发生这些BUG,嘿,我们也证运行了相当多的PostgreSQL群集(主从架构),然而我从你的报告中发现些事情,

  1. 你使用Slony - 那货是坨燃烧的狗屎, 甚至连http://howfuckedismydatabase.com 都拿Slony来嘲笑,PostgreSQL就内建的二进位串流较可靠且快多了,我建议你们改用内建的。
  2. 没有提到连接池,还在postgresql.conf配置了上千的连线数 - 这些听起来相当糟糕且没有效率,我建议你用pg_bouncer当做连接池 - https://pgbouncer.github.io/ ,并将PostgreSQL的max_connection设置512-1024内,实际上当你连接数超过256时,你该考虑横向扩展,而不是垂直扩展。
  3. 报告中你提到了你的失效切换与备份程序有多脆弱,我们也写了一个简易的脚本,用来做PostgreSQL的失效切换,也写了一些文件,如果你有兴趣我可以提供给你,而说到备份上,我们使用pgBaRMan来处理日益繁重的备份工作,能每日备份两次都是靠BaRMan与PostgreSQL自带的pg_dump指令,异地备援是非常重要的,能保证性能与可移值性。
  4. 你还在用Azure?!?! 我会建议你快点离开那个垃圾桶,这个Microsoft平台有许多内部DNS丶NTP丶路由丶储存IO的问题,太荒谬了。我也听过几个恐怖故事,关於这些问题同时发生的。如果你想听更多调校PostgreSQL的建议欢迎联络我,我有非常多的经验可以分享。

Capt. McLeod 一并问下,你的数据库大概占用磁盘多大空间? 我们是在讨论TB等级的数据而不是GB对吧? 7h 7 hours ago

Capt. McLeod 我开源了我的失效切换与replication同步的脚本,同时我看见你们在讨论Pgpool,我不建议使用那个,试试看Pgbouncer替代吧 7h 7 hours ago

Capt. McLeod Pgpool 有一堆问题,我们是经过测试才弃用的 5h 5 hours ago

Capt. McLeod 同时我想知道,既然这件事情了,我能否透过Twitter发表言论,或是其它方式来增加这次事件的透明度,我了解发生这些事情有多鸟,我们都有资讯交换至上的精神,当我第一次遇到这些事情时,我非常的紧张甚至呕吐了。 4h 4 hours ago

Sid Sijbrandij Hi Sam,感谢你的协助,介意我将你贴的那些放到公开文件上分享给团队其它人吗? 3m 3 minutes ago

Capt. McLeod 你说那个失效切换的脚本? 3m 2 minutes ago

Sid Sijbrandij 一字一句。 2m 1 minute ago