Facebook 網絡故障,到底是怎么回事?
Facebook史上最嚴重宕機,全網宕機近七小時,高管赴推特道歉。近7個小時時間,全都掛了Facebook全網宕機,連內網都廢了。Twitter成為了最大贏家。對一家互聯網巨頭來說,這樣的狀況實在太尷尬。這已經是Facebook創辦以來最嚴重的一次網絡訪問事故。直到下線近7個小時,美國西部時間下午三點左右,Facebook、Instagram等諸多產品才恢復正常訪問。(目前只是美國地區恢復正常,全球其他國家和地區依然沒有恢復。)
整個事件可以概況為:Facebook負責BGP變更的工程師,將包含Facebook權威(Authorized)域名服務器的網段185.89.218.0/23和129.134.30.0/23過濾掉了,從而造成的連鎖反應。
以下是完整的整個事件的前因后果:
Facebook網絡工程師,更新BGP路由配置時,將185.89.218.0/23和129.134.30.0/23這兩條路由過濾掉了,這兩條路由分別包含512個IP地址,一共1024個IP地址,其中:
185.89.218.0/23代表IP地址從185.89.218.0開始到185.89.219.255結尾的512個地址。
129.134.30.0/23代表IP地址從129.134.30.0開始到129.134.31.255結尾的512個地址。
意味著Internet上其他路由器將沒有通往這1024個IP地址的路由,怎么辦?
丟棄處理!
可是要命的是,這1024個IP地址恰恰包含Facebook公司權威DNS服務器的IP地址。這樣就出大事了。要想透徹理解為何要出大事,首先要了解DNS是如何工作的?
當用戶在瀏覽器里輸入Facebook.com之后敲回車鍵,瀏覽器需要將facebook.com解析成IP地址之后才能建立TCP連接,然后TLS安全連接,然后是http交易。
通常用戶的本地DNS服務器就是家庭網關IP、或者公司網關、或者公司DNS Server,比如192.168.1.1 、10.0.0.1、172.16.1.1之類的,也有的用戶使用諸如1.1.1.1 、8.8.8.8、114.114.114.114的DNS服務器。但是這些這些DNS服務器,僅僅是域名解析的搬運工。當用戶的解析Facebook.com請求到來時,它們先檢查自己的緩存里是否有facebook.com與IP地址的條目,如果有,直接返回給用戶。
如果沒有,需要這些域名解析的搬運工比如1.1.1.1,去根域名服務器(一共13個虛擬IP地址)去查詢,返回com域名服務器(一級)IP地址列表。
1.1.1.1這臺不知疲倦的搬運工再聯系com域名服務器(使用IP地址聯系),com域名服務器給1.1.1.1 返回facebook.com域名服務器的IP地址列表。就是這么幾臺服務器才是最權威的數據源頭,因為它們才真正知曉facebook內部服務器域名與IP地址的映射關系。
可是當1.1.1.1這臺搬運工嘗試聯系facebook.com域名服務器的IP地址列表時,無法連接,因為Internet上沒有facebook.com域名服務器的IP地址列表的路由表,Facebook域名服務器的IP地址為何從Internet全球路由表里消失了,因為Facebook網絡工程師將它們(185.89.218.0/23和129.134.30.0/23)過濾出去了。
這樣1.1.1.1就無法將Facebook.com域名解析返回給用戶,用戶就無法訪問facebook的網站。
為何Facebook全球有30多億用戶,該次事件只影響到其中的8000多萬的用戶?
如上文所說,域名解析搬運工如1.1.1.1、8.8.8.8,如果成功解析facebook網站的域名,通常會緩存一段時間,這樣當下一個用戶訪問facebook網站時,可以立馬將結果返回給用戶,這樣可以省卻不少的時間,同時刷新緩存定時器。
這就意味著,如果一臺域名搬運工一直有用戶在解析facebook域名,一直在刷新緩存定時器,那么這個緩存一直不會被刪除,一直可以被直接返回給用戶。所以,即使在互聯網無法訪問facebook權威域名服務器,但是依靠分布在全球各地的域名解析搬運工的緩存機制,依然有很多用戶可以訪問Facebook網站。畢竟Facebook其他服務器是可路由的、是可以到達的!
當然如果有的域名搬運工,緩存的內容由于沒有域名解析的刷新,超時最后被刪除。當域名搬運工試圖聯系facebook權威服務器時,就出現問題了。
Facebook負責變更BGP的工程師為何不在第一時間做回滾(Rollback)操作?
做變更的工程師通常都是遠程VPN操作,而做路由變更操作是一種極度高風險的操作,因為一旦路由配置出錯,工程師就無法再訪問正在遠程操作的路由器了。為了保險起見,為了不和路由器失去聯系,工程師在commit變更代碼時,會使用一個confirm選項,后面跟著一個數字,單位是分鐘。比如
Commit confirm 2
這條代碼的意思是,將當前的修改配置commit, 兩分鐘之后自動回滾到修改前的版本。在這兩分鐘內,工程師發現遠程SSH軟件與路由器的遠程SSH連接依然沒有斷,那么就認為當前的修改沒有問題,于是再次使用 commit命令確認當前修改,那么修改的配置就真正的生效了。
相反,如果工程師敲完命令立馬自己的遠程軟件SSH斷了,說明當前的修改讓路由器與Internet失去了聯系,路由出問題了。好在這種影響只會影響2分鐘,2分鐘之后自動回滾到修改前的版本,工程師依然可以再次聯系到路由器,檢查自己的配置哪里出了問題。
很顯然,在這兩分鐘內facebook工程師沒有嘗試去Ping一下Facebook內部權威域名服務器。否則他們一定不會commit這次變更操作。
為了簡化操作,工程師在等待confirm 的時間內,可以使用自動化的腳本,將公司內部最關鍵的服務器Ping一遍,其中包括域名服務器、域控制器、時間服務器等等,確保它們全部沒有問題再commit配置版本。