GitLab服務災難與危機處理的啟示:開誠布公,才能贏回信任
就在年假即將收假的昨天(2017年2月1日),網路上發生了一件堪稱工程師惡夢的事件。
在業界常被用來當程式碼版本控制倉庫的GitLab網站,因為各種意想不到的狀況,突然停止服務了。GitLab服務離線,首當其衝的就是使用GitLab儲存程式碼的個人與單位;如果沒有本地備份或是備援機制,放在GitLab的程式碼、issue tickets與commit logs,就相當於從網路世界中憑空消失。
災難發生
根據 GitLab 所提供的事件紀錄,GitLab 工程師在台北時間2月1日凌晨五點時進行資料庫維護作業,刪除一批造成資料庫異常負載的大量spam users;起初操作都沒甚麼問題,工程師即開始進行資料庫清理作業[footnote]PostgreSQL 刪除資料行後不會立即釋放空間,而是標記為刪除;當垃圾資料量過大時,可能會造成讀寫效能低落,因此需要設定定期自動清理,或是手動下指令清理,減少資料檔案的容量。[/footnote]。
在操作完成後,系統看似回復正常,但很快地因為大量資料同步不及,監控系統開始回報資料庫複寫作業[footnote]Replication,在此為資料庫叢集節點間的資料同步備份。[/footnote]出現延遲;此時發出警訊的是db2。工程師嘗試了幾種作法都無效,之後決定刪掉資料庫的目錄,讓db2重新從其他台節點同步資料。
但被資料庫搞了一天,可能身心俱疲的工程師,下了指令之後,才發現他刪掉的是db1,也就是應該要拿來當做資料同步來源的檔案;在緊急中斷作業後,原先310GB的資料只剩下4.5GB。於是GitLab服務就因而中斷了。
GitLab的大客戶。
雪上加霜的是,GitLab所採行的五種備份還原機制全部失效:
LVM(一種邏輯磁碟架構)備份:每日執行,工程師在進行維護的前六小時有手動備份一次。
資料庫備份:資料庫版本與備份程式的版本不同,無法備份資料。
微軟Azure的儲存體鏡像:在資料庫的機器上沒有啟用。
資料庫叢集備份:架構極為脆弱,用了很多神秘的shell script,檢視後發現似乎也不是完整備份。
Amazon S3備份:不知何故資料是空的。
最後,工程師只得採用六小時前的備份檔來還原資料庫,再從其他備份來源試圖拼湊出這份備份裡缺少的資料。
明快且公開的危機處理
在事件發生後,GitLab 技術團隊很快地公布了事件的始末與處置方式,並同步在Twitter上更新復原狀況,以及資料庫恢復狀態的即時監控圖表,甚至還直播工程師們修復系統的畫面。這在外人眼中看起來似乎是在惡搞,但看在同是工程師的眼裡,卻是很實在的災後重建進度報告。
GitLab明快而公開的危機處理態度,除了展現過人的技術力與自信外,也極大地挽回了客戶的信任。
身為工程師的筆者,看到GitLab這樣明快而公開的危機處理態度,真的十分讚賞。GitLab公開了所有問題發生的過程與修復細節,甚至還將數據直接公開直播,要是沒有過人的技術能力和信心,是很難下決心這樣做的;二來此舉也展現出GitLab負責到底的態度,對於挽回客戶信心可說大大加分。
相較之下,某些公司在發生技術災難時,面對客戶和媒體詢問,多半遮遮掩掩,避重就輕;和GitLab的開誠布公,實在有著天壤之別。
亡羊補牢
這次的事件包含了許多巧合,但不幸中的大幸,是手動備份的資料還在;整個GitLab的服務也看似能在資料還原後恢復正常(但有著幾個小時的時差)。GitLab的工程師也提出了未來的幾個修正方向:
修改線上運作機器的終端機文字提示,在BASH的PS1[footnote]PS1是BASH的其中一個環境變數,用以變更命令提示字元的文字。[/footnote]設定顯示完整的機器名稱,像是db1.staging.gitlab.com,而不是只有db1,用以提示工程師正在操作的是哪台機器。
從系統端禁用刪除指令,或是對刪除指令增加使用限制。
備份完成後會送出警示,並監控備份檔案的大小,如果比運作中資料庫還小10%便送出警示。
紀錄最後成功備份的時間。
找出PostgreSQL設定檔參數造成啟動失敗的原因:文件指出在去年五月便修改設定,當時啟動並無問題,但不知何故在這次事件中失效。
深入研究資料庫備份運作方式,建立線上備份與及時恢復(PITR,Point-In-Time Recovery)機制。
建立障礙排除頁面,協助使用者排除GitLab離線時可能遭遇的問題。
實驗Azure的資料複製工具AzCopy,根據微軟官方文件指出此一方式較rsync[footnote]Linux/BSD系統中常用的檔案拷貝工具。[/footnote]快(但文件中也指出團隊中並無熟悉Windows的專家)。
目前GitLab已經順利恢復系統,大家又能繼續快快樂樂地寫code了。
延伸閱讀
有點挖苦的世界備份日。