早前有人贴的事故详情
因为与自身工作较有关,翻起来放着等未来踩坑
一些专用词保持着原文,避免歧义
翻译可能不是很好,有兴趣帮忙更正的可以直接發 PR 到这边
>> 备注: 此事故影响了数据库 (包含 issues 与 merge requests) 但无影响到 GIT Repo's (repositories 与 wikis)。
YouTube 直播 - 瞧瞧我们如何思考与解决问题
影响
- 六小时左右的数据丢失
- 粗估有 4613 个普通 project 丶 74 forks 及 350 imports 的数据丢失,共计影响了 5037 个 project. 由於 Git repositorie 并没有丢失,如 project 的 User/Group 於数据丢失前已存在, project 将可以被重建,但 project issues 之类的无法重建
- 接近 5000 条留言丢失
- 从 Kibana 的记录上,粗估有 707 名用户活跃度受影响
- 於 01/31 17:20 之後建立的 WebHooks 丢失
时间轴(格林威治标准时间)
-
2017/01/31 16:00/17:00 - 21:00
- YP 正在 staging 调适 pgpool 与 replication ,并创建了 LVM 快照同步 production 数据至 staging ,希望能以此快照创建其它复本,这些操作大概在数据丢失前六小时完成了。
- LVM 快照所创建的复本并没有照着 YP 预期般的有用,在恶意流量与 GitLab.com 的高负载下,创建 replication 非常耗时且容易产生问题。 YP 需要另外一位同事的协助,但该同事该日并无上班,所以此工作中断了。
-
2017/01/31 21:00 - 恶意流量造成的数据库高负载 - Twitter | Slack
- 依照 IP 地址阻挡恶意用户流量
- 移除了一个将 repository 当成某种形式 CDN 的用户,该用户从 47000 个不同的 IP 位址登入(造成数据库高负载),这是与设备组与技术支持组沟通後的决定。
- 移除了恶意流量的用户 - Slack
- 数据库负载回到正常,检视了 PostgreSQL 的状况後,排除了许多的 dead tuples
-
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 就说时间太晚了,他该离线了,却因为处理这些突发的同步问题而无法离线。
-
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 左右开始记录)
-
建议修复的方法
- 导入 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 数据。
-
采取行动
- 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 - 开始进入重建阶段
-
重建阶段
- [x] - 建立一份 DB1 的服务器快照 - DB2 或 DB3 也可以 - 於 16:36 UTC 完成
- [x] - 由於 production 的 PostgreSQL 版本为 9.6.0 , staging 是使用 9.6.1 ,升级 db1.cluster.gitlab.com 的 PostgreSQL 至 9.6.1
- 安装 8.16.3-EE.1
- YP 将 chef-noop 移至 chef-client (noop 禁用了手动配置)
- 16:45 , YP 运行 chef-client
- [x] - 启动数据库 - 16:53 UTC
- [x] - 更新 Sentry DSN ,错误讯息才不会回传至 staging
- [x] - 为了确保创建 project/note 的安全,对所有 table 的 ID 增加 10k ,使用 https://gist.github.com/anonymous/23e3c0d41e2beac018c4099d45ec88f5 完成
- [x] - 更新 Rails/Redis 快取
- [x] - 尽可能的重建 WebHooks
- [x] 使用尚未移除 WebHook 备份的快照,启动 Staging
- [x] 检查是否留有 WebHook
- [x] 汇出“ web_hooks ”内的资料(如果有的话)
- [x] 复制汇出结果至 production
- [x] 汇入至 production 数据库
- [x] - 测试是否 workers 能透过 rails 终端连线
- [x] - 逐步启动 workers
- [x] - 关闭发布页面
- [x] - 用 @gitlabstatus 的推特发文
- [x] - 创建 issue 说明未来的计画与行动
- [ ] - 替没有 Project 记录的 Git repositories 创建 Project 记录,并使用现存的 User/Group 做为 repositories 的命名空间
- <del> PC - 我想弄份这些 repos.的清单,我们就可以从数据库中确认了</del>已经有了
- [ ] - 删除未知(丢失)命名空间的 repositories
- [x] - 再次移除恶意使用者(好让他们不能再次造成问题)
- [x] 有着 47000 个 IP 的 CDN 老兄
-
数据重建後的待办事项
遭遇之问题
- LVM 快照默认 24 小时一次,是 YP 在六小时之前手动执行了一次
- 常态备份似乎也是 24 小时执行一次,虽然 YP 也不知道到底存在哪里;根据 JN 的说法,备份是无效的,备份的结果只有几 Bytes 。
- SH: 看起来 pg_dump 是失败的, PostgreSQL 9.2 二进位文件取代了 9.6 的二进位文件,因为 omnibus 需配置 data/PG_VERSION 为 9.6 ,而 workers 上并没有这个配置文件所以使用了默认的 9.2 版本,没有结果也不会产生警告,而更旧的备份则可能是被 Fog gem 给清除了
- Azure 硬盘快照只在 NFS 服务器启动,在数据服务器并无启动
- 当同步至 Staging 时并不会同步 WebHooks ,除非我们能从常态备份中拉取,不然将会丢失
- 产 replication 的程序超级脆弱丶容易出错丶需依靠一些不一定的 Shell 脚本丶缺少文件
- SH: 从这次事件後我们学到了如何翻新 Staging 的数据库,先对 gitlab_replicator 的文件夹做快照,更改 replication 设定,然後重新启动一台新的 PostgreSQL 服务器。
- 我们到 S3 的备份显然也没有作用,整个都是空的
- 我们并没有一个稳固的预警,来监控备份失败的状况,将会着手研究
总的来说, 我们部属了五种备援技术,没有一个可靠或是发挥大用处 => 六小时前做的备份反而还较有用
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