试着翻了下 Gitlab 早前的事故详情

2017-02-02 19:20:16 +08:00
 timwei

早前有人贴的事故详情

因为与自身工作较有关,翻起来放着等未来踩坑

一些专用词保持着原文,避免歧义

翻译可能不是很好,有兴趣帮忙更正的可以直接發 PR 到这边


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 需要另外一位同事的协助,但该同事该日并无上班,所以此工作中断了。
  2. 2017/01/31 21:00 - 恶意流量造成的数据库高负载 - Twitter | Slack

    • 依照 IP 地址阻挡恶意用户流量
    • 移除了一个将 repository 当成某种形式 CDN 的用户,该用户从 47000 个不同的 IP 位址登入(造成数据库高负载),这是与设备组与技术支持组沟通後的决定。
    • 移除了恶意流量的用户 - Slack
    • 数据库负载回到正常,检视了 PostgreSQL 的状况後,排除了许多的 dead tuples
  3. 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 就说时间太晚了,他该离线了,却因为处理这些突发的同步问题而无法离线。
  4. 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 数据。
  2. 采取行动

    • 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 - 开始进入重建阶段
  3. 重建阶段

  4. 数据重建後的待办事项

    • 创一个 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 给清除了
  3. Azure 硬盘快照只在 NFS 服务器启动,在数据服务器并无启动
  4. 当同步至 Staging 时并不会同步 WebHooks ,除非我们能从常态备份中拉取,不然将会丢失
  5. 产 replication 的程序超级脆弱丶容易出错丶需依靠一些不一定的 Shell 脚本丶缺少文件
    • SH: 从这次事件後我们学到了如何翻新 Staging 的数据库,先对 gitlab_replicator 的文件夹做快照,更改 replication 设定,然後重新启动一台新的 PostgreSQL 服务器。
  6. 我们到 S3 的备份显然也没有作用,整个都是空的
  7. 我们并没有一个稳固的预警,来监控备份失败的状况,将会着手研究

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


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 嘿,我是个程序员, 时常提交修改,也是主要的贡献者,非常喜欢你们所做的一切,有需要我帮忙的话随时连络我,我很乐意帮忙。

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

4184 次点击
所在节点    GitLab
6 条回复
sorra
2017-02-02 22:07:07 +08:00
可以转载吗?会注明作者和出处
julyclyde
2017-02-02 23:17:57 +08:00
首先,“格林威治标准时间”就是错的。应该是协调世界时。
timwei
2017-02-03 00:08:49 +08:00
@sorra 转呀

@julyclyde
我也有查过的。不过怕世界协调时太少人懂
bluesky139
2017-02-03 12:59:38 +08:00
感谢翻译,好长。
官方的这种透明做法很不错。
julyclyde
2017-02-03 15:52:01 +08:00
@timwei 那更没几个人知道格林威治在哪儿了……会有人问你咋不用北京时间
错了就是错了,不要嘴硬
timwei
2017-02-03 16:47:58 +08:00
@julyclyde

我嘴可軟了,會改下的 lulz

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/337755

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX