從 GCP 故障看 17 Media 工程團隊的災難應變

GCP 在萬聖節隔天發生了三年來最大規模的故障,17 Media 也是嚴重受災戶之一,但它們是如何迅速恢復並改進的?請見本文詳述。
評論
評論

本文來自 17 Media Tech Blog,並獲作者授權轉載,作者Roy Chung-Cheng Lou,軟體和數學愛好者,喜歡透過技術來幫助人和企業。

Google Cloud Platform (GCP) 在萬聖節隔天發生了三年來最大規模的故障,在故障的 12 小時內,因為網路問題造成無法新增機器。這次故障也是個好機會來檢視 17 Media 的 Site Reliability Engineering (SRE) 團隊平日的防護及練習的成果。筆者有幸參與故障排除全程,本文將以一位 17 Media SRE 觀點來介紹當天發生經過,探討為何這次 17 Media 受影響特別大,以及日後的改進事項,與大家一同交流。

17 Media 系統概述

目前主要負擔線上流量的有十組伺服器,全都以容器透過 Google Kubernetes Engine (GKE) 運行,利用 CPU 用量自動擴容。每日尖峰及離峰流量差距約為六倍,尖峰約在晚上 11 點鐘左右,QPS 超過 10,000。這對開發團隊是相當刺激的一件事,因為每天晚上都是個小小的雙十一挑戰,如果不小心寫出了 bug,當天晚上就會收到很真實的用戶反饋。

17 Media 線上系統QPS流量圖,每日峰值約在 11:00 pm,凹下去那塊就是故障當晚的流量。

17 Media 的主要用戶分布於亞洲及美國,主力開發由台灣團隊負責,整個後端程式由 Golang 所撰寫。為了要讓開發團隊更為敏捷,SRE 每個上班日都會佈署新版本:透過 Jenkins 在凌晨四點自動將前一日 master branch 的代碼佈署到 staging 環境,SRE 則是在上班後將 staging 環境測試穩定後的代碼佈署到生產(production)環境。

發生經過

事故發生於 11/1 中午,當時一位 SRE 發現 staging 環境的伺服器無法正常部署新版本,一段時間後在 GCP 狀態頁面確定是 GCP 的故障,造成無法開啟新機器。這對我們意味著幾件事:

  1. 無法佈署新版本。
  2. 當 GKE 認為某個容器健康狀態異常而決定關閉時,將會無法開啟新機器替換。
  3. 當系統有擴容需求時,將會無法開啟新機器。

其中 3. 的影響最大。在故障剛發生時(12:00)系統處於離峰狀態,依照過往的流量波形,預估稍晚流量上升後系統會無法支撐。但由於以往 GCP 故障多在一小時內修復,當下我們不太擔心。

SRE team lead 在 Slack 的公告,為了要讓各團隊即時同步資訊所以翻譯成英日文。

數個小時過後從 GCP 狀態頁面仍看不出修復跡象,這時團隊開始緊張了,因為晚上就是高峰期,現有的系統資源肯定支撐不住流量。SRE 團隊很快討論後決定了以下應變措施:

  • 用戶限流
  • 關閉次要功能
  • 卸載運算需求低的容器,改運行關鍵容器
  • 跨雲佈署服務

由於無法佈署新版本,需要改動後端代碼的 hotfix 就不在考慮範圍內,所以這次的應變措施大多以運維的角度出發,跟以往與後端團隊合作的模式不同。以下分別介紹各項應變措施:

用戶限流

當新上線用戶因為限流而被無法使用時,app 會顯示爆氣的 17 寶寶

這是一項限制用戶數的功能。系統會持續追蹤目前線上人數,當發現無法支撐過多的用戶時,會將超出上限的新上線用戶擋在系統外。新上線的用戶會看到超載訊息,而已經在線上的用戶可以繼續保有良好的直播體驗。

我們預估了當前系統可以支撐的用戶數並開啟限制功能。從事後看來這個措施效果最好,因為這是一個開發成熟的功能,當下只要定義人數上限就會產生效果。

關閉次要功能

目前 17 Media 線上服務大多為 CPU bounded。當 CPU 成為限制資源時,我們只好透過重新分配 CPU 的運用來讓重要的工作可以順利完成。對於直播平台來說,最重要的體驗就是直播本身,任何佔用 CPU 的非直播功能都可以關閉。但由於這些改動不能牽涉代碼改變(因為無法佈署新版本)所以可以關閉的功能有限。最後僅關閉了一些可以動態開關的功能,例如排行榜以及發送紅包。

卸載運算需求低的容器,改運行關鍵容器

當可以使用的運算資源無法擴充時,除了關閉次要功能外,另一個方式是重新分配各個服務所運行的容器數量。對於某些延遲要求比較低的服務(例如 job queue worker),可以進一步降低機器數,把運算資源分配給延遲要求高的服務(例如 API service)。

這個方式說起來容易做起來難。由於更換容器不屬於 SRE 團隊日常工作之一,實際執行上只能土法煉鋼進入一台一台機器手動更換,而且更換到第三台後就因為不明原因失敗了。相信大家都有聽過寵物跟牲畜的故事,一時要將牲畜當作一隻隻的寵物看待並不是件容易的事。

手動跨雲佈署

17 Media 的伺服器位於美西,剛好是各大雲服務供應商都有機房的位置。如果當下沒辦法在 GCP 開機器,那就在 AWS 開機器吧!

因為總故障時間長達 12 小時,前面幾項工作也很快的嘗試完了,我們大部分的時間花在跨雲佈署的準備。團隊已經好一陣子沒接觸 AWS 的容器服務,我們不確定哪個解決方案能在短時間解決問題,所以決定分頭嘗試不同的服務,包括 EKS / ECS / EC2 以及 Elastic Beanstalk,能夠嘗試的我們都試了。後來每個人分別遭遇了不同的問題,由於團隊對於 GCP 黏著度較深,導致這項方案完全失敗。現在反思當時應該要所有人專注在同一項 AWS 服務,或許能在時限內找出一項解決方案。

為何 17 Media app 受影響特別大?

這是全球性故障,我們原先預期全球各大 app 都會發生問題。但在網路上搜尋一輪的結果超出意料:各大 app 都運作正常。相較於其他公司,17 Media 受到的影響相當大。事後研究發現可能原因有二:

  • 故障發生於台灣時間中午 12:00,也就是美西時間凌晨 2:00,對於大部分美國的 app 來說已經過了尖峰時段,不會有擴容需求,受到的影響也低。相對 17 Media app 從下午過後流量就一路往上到半夜的高峰,無法擴容的影響相當大。
  • 17 Media 的主要功能集中在少數服務上,當服務所承載的一部分功能耗盡服務資源時(例如CPU),該服務上承載的其他功能也跟著異常,造成全面性災難。其他公司的 app 當下僅有部分功能異常。這也是大家所熟知的單體服務(monolith)與微服務(micro services)在災備隔離(fault isolation)上的差異,但實際發生時感受還是特別深刻。

改進事項

SRE 團隊的風格是快速嘗試且不責怪(blamelessness),在故障後的隔天上班日,團隊就開會檢討了當天的應變以及日後的改進。從事後反思當下的措施,真正奏效的反而是平日已經準備好的災難預備方案。這也讓我們認真檢討改進方案,若日後發生一樣的故障時服務能繼續運行。以下兩項是團隊討論之後得出的改進方案:混合雲及微服務,分別屬於 SRE 及 backend 的工作範疇:

混合雲佈署服務

混合雲佈署是個解決雲服務故障的好方法,畢竟各大雲服務商從來沒有同時故障過;當其中一個雲服務故障時,可以將流量導至另一個雲來排除問題。但由於其運維複雜度以及可能帶來的延遲上升,之前並不是 SRE 團隊的工作重心。這次故障讓我們認真思考混合雲的可能性。我們計畫從無狀態(stateless)服務開始,原因如下:

  • 無狀態服務特性:因為無狀態特性,這類服務很適合隨著流量動態增減機器。也因為這個特性,在這次故障受到影響的幾乎是無狀態的服務。
  • 影響範圍廣:17 Media 的服務大部分為無狀態,如果解決了這類服務的單點故障(single point of failure)問題等於解決了大部分的問題。

一般來說無狀態服務前面有一層 load balancer 分散流量,服務之下會有另一層服務或資料庫(database)來儲存或提供狀態。同時因為資料庫的存取延遲較長,前面多半有一層快取(cache)來降低延遲,同時降低資料庫負擔。也有人稱這為 3-tier architecture

一般常見的 3-tier architecture 結構

這一類運維層面的改動有個重點,必須對開發人員無感,也就是不能造成開發人員額外負擔。

  • 對於下層服務的讀寫比例約為 9:1。
  • 資料庫讀寫:較慢,但因為前面放了快取所以對用戶影響較低。
  • 快取讀取:必須要快,因為大量的資料來自於快取。
  • 快取寫入:也需要快,但因為寫入比例低,對用戶影響較小。
  • 快取跟資料庫之間可以是最終一致(eventual consistency),但是誤差時間不能太長(例如不能超過一分鐘)。

基於以上假設,我們計畫做以下架構改動:在 AWS 建立另一組無狀態服務,前面由 weighted DNS 分散流量;在兩個雲服務商各建立一組快取以加速服務讀取速度,但寫入一律透過 GCP;資料庫讀寫依舊透過 GCP 。下圖描述了計畫中的改動。

計畫中的混合雲服務

在開發人員眼中,這個策略是非常合適的,因為開發人員對於資料庫及快取的假設不因這個策略而改變,也就是說工程師可以在不知道底層複雜度的前提下進行開發。原因如下:
GCP 這側的讀寫快取是位於同個雲內,所以快且穩定。

  • AWS 側的快取寫入 GCP,延遲較高。但因為寫入量少所以影響不大。
  • AWS 側的讀取來自同個雲內的快取,延遲低。但會有短暫的資料不一致:資料跨雲寫
  • GCP的快取後,需要一陣子才會同步回AWS的快取,這會造成讀取到錯誤的舊資料。但拿常用的快取服務 Redis 來說,如果兩個資料中心距離很近,兩座 Redis 之間資料差距遠小於一秒,對 17 Media 的應用場景來說可忽略不計。

在 SRE 眼中,這個策略略有風險:17 Media 的 DNS 服務直接面向用戶,切換 DNS weighting 的時候會有 DNS cache poisoning 的問題;但這可以透過後續架構微調解決(例如前面再搭一層 load balancer),所以目前較不擔心。

微服務

在之前提到,這次 17 Media 會成為重災戶,其中一個原因是主要功能集中在少數服務,解決方法就是將單體服務(monolith)分拆成微服務(micro services)。但要怎麼拆就是個大學問,拆分方式需要視團隊組成而決定,後端團隊正在討論不同拆分的可行性。

結語

在這次故障的處理過程中,讓我感到產品團隊的責任越來越重大。目前團隊支撐的已經是個多元的直播產品,平台上包括早期用戶大多來自台灣,系統故障的內部 Slack 訊息只需準備中文;但現在已經跨足許多地區,這次故障時內部更新訊息包含中英日等語言。

以上改進事項正在進行中,有興趣歡迎一起討論。也歡迎你參與進化的過程,17 Media 工程團隊持續徵才中,包括 backend 以及 SRE。在 17 你可以遇到頂尖好手,這是一個多元化 app 的壯大旅程,歡迎加入我們!

職缺列表:http://bit.ly/2qnPLwm

責任編輯:Chris



開發者享受 CI/CD 價值!運用 Amazon EKS 整合 GitLab 創建自動化部署

企業如何在 Amazon EKS(Elastic Kubernetes Services)上使用 GitLab 創建自動化部署,減輕人力負擔,提升專案服務運作效率?
評論
評論

所謂現代化智慧 IT,所有工程師最希望的境界,莫過於只要輕鬆點幾下設定,系統就會自動跑起來,管理者再也不用隨時待命在機台旁邊,從此工作悠哉又快樂!儘管這樣情境還沒到來,但隨著敏捷式開發的流行,除了 DevOps 人員,有越來越多開發者將 CI/CD 概念融入到工作流程當中,例如從 build code、執行 unit test、到部署應用程式。

打造第一個在 AWS 上的應用程式

上述種種反覆步驟自動化執行,也就能提昇服務品質、主動通知開發人員以減輕人力負擔,讓專案服務能持續運作。

其中,GitLab 是執行 CI/CD 常用的工具之一,也是開發者使用程式碼儲存庫的地方。為了讓 GitLab Runner 在雲端快速實踐 CI/CD,《AWS 開發者系列》透過影片分享,如何在 Amazon EKS(Elastic Kubernetes Services)上使用 GitLab 創建自動化部署。

以下節錄工作坊影音內容,幫助開發者快速理解如何運用 Amazon EKS 的高可用性且安全的叢集,將修補、部署節點、更新等關鍵任務,全部做到自動化設定。同時影片也會示範 Amazon EKS 搭配 GitLab 如何展開自動部署,幫助工程團隊實踐 CI/CD 價值。

Amazon EKS 對容器管理輕鬆簡單、維運省時省力

容器化服務越來越興盛,當容器(Container)越來越多,在複雜的微服務(Microservice)系統環境之下,運維團隊的管理成本可能相對會增加不少,為了有效調度容器部署, 導入Kubernetes 無疑是近年企業熱門的話題之一。

建構 Kubernetes Cluster 流主要可區分兩大塊,一是安排容器調度的Control Plane、另一則是容器運行時需要用到的 Worker Node。

Control Plane 裡面涵蓋有儲存狀態的 ETCD、CoController manager 、Scheduler 的調度管理、甚至是操作時進行互動的 APIServer,若是自己創建 的 Kubernetes Cluster ,需要自己安裝這些元件,後續仍需要對 Control Plane 進行相關管理、維護、升級工作。為了減少上述 Components 的繁複維護,在透過 AWS EKS 代管的 Kubernete Control Plane 部可以獲得以下三大好處。

透過 AWS 增加雲端技能 在組織發揮影響力

Amazon EKS 一鍵式部署,展現三大優勢

第一,Amazon EKS代管的 Control Plane實踐了跨AZ的高可用部署,使用者不需要擔心單一節點故障的風險。

第二,Amazon EKS 支持至少四個 Kubernetes版本,持續跟進每季 CNCF 的發佈,同時 EKS 也完全符合上游 CNCF 規範。

第三,部署 Amazon EKS 之後,可直接使用 AWS 平台上現成的服務工具,在安全性管理、網路設定方面,可以做到無縫整合。

最後 AWS 台灣解決方案架構師也提到,若想在容器環境進行 CI/CD 及應用程式的管理,可以進一步透過 IaC 整合部署 Amazon EKS 叢集,透過使用 Console、把 EKS 變成 Cloudformation 的模板、使用 AWS 所開發出來的 eksctl.io、或指令是採用 AWS CDK 可以讓開發者用自身熟悉的語言,在 AWS 平台整合 CI/CD 工具進行維運及部署 EKS。

了解 Amazon EKS 整合 GitLab ,獲得三面向價值

對開發者而言,想把 Amazon EKS 整合到 CI/CD 工具之一的 GitLab 平台上,可以看到那些實際的優勢?

在 DevOps 開發者示範工作坊當中,GitLab 資深解決方案架構師指出,GitLab 使用到 Kubernetes 技術,主要有三種搭配方法,包含 GitLab Server、GitLab Runner、以及創建 Deployment Environment。

本次示範教學會主要聚焦在 GitLab Runner 如何採取 Auto-scaled 方式進行 Build、Test、Package Apps;以及在 Deployment Environment 運用 Kubernetes 技術,做到 Auto Deploy、Review App。

正因為 Amazon EKS 能夠在 DevOps 過程提供所需要的彈性計算資源,幫助開發者在 GitLab 平台上面獲得以下三個層次的優勢:

  • 在 GitLab 內建的部署工作流程當中,自動生成整套 CI/CD 最佳實踐腳本。
  • Review App 過程,從 Merge Request 中可直接訪問應用程式 /App 的 UI 介面,並且根據 Git branch 名稱、專案名稱,自動生成 Review App 的 URL,以及在 Merge 前的最後防線進行 Approval 檢查。
  • 加速 CI/CD 流水線,GitLab Runner 運行時候還可藉由 Amazon EKS Cluster 進行 Auto-scaled 的支援。

Amazon EKS 整合 GitLab ,需要兩大流程

影片最後,GitLab 資深解決方案架構師示範如何把 Amazon EKS 整合至 GitLab 執行 Auto Deploy,主要可分為兩大區塊流程,第一部分聚焦在 Amazon EKS cluster 的設置,第二部分則執行 Auto Deploy 設置。

第一塊可拆分為四個階段,首先教學怎麼創建 EC2 節點的 EKS cluster,第二階段示範把 EKS Cluster 連接到開發者的 GitLab Instance、Group 或 Project,下一步則使用 Cluster Management Project Template 創建一個 Cluster Management Project,以及最後一階段透過 Cluster Management Project 自帶的 Helm Chart,安裝在 Cluster 所需要的內建 App。

第二塊執行 Auto Deploy 設置,針對需要部署的 App 創建一個 GitLab Project,接著再把 gitlab-ci.yml 添加到 Project,並從 Web IDE 選擇及導入 Auto Deploy 的 CI 模版,讓 GitLab 自動生成最佳實踐的整套流水線。

幫助開發者更了解 Amazon EKS 整合 GitLab 的 QA 系列

Q:使用 Amazon EKS 之後,如何更有效率或優化資源去配置 Worker Node 的機器數量,以及如何有效空管開發維運的成本?

A:Kubernetes 除了本身有 HPA(Horizontal Pod Autoscaling)可根據使用程度自動調整資源流量,另外也能延伸使用 AWS Auto Scaling 方案,針對可擴展資源去設定自動擴展管理。另外在成本管控,雖然 Amazon EKS 會收取額外管理費用,但可透過 AWS 平台的 Calculato r計算每個 EKS 的價格,你會發現自動化部署及管理的費用,相對工程師人力的成本更加便宜。

Q:越來越多客戶考慮把現有 Application 變成容器部署,大多是爲了加快部署的效率,那麼變成容器模式之後,對 CI/CD 的工作流程有什麽影響嗎?

A:運用容器技術最直接的效果,可以讓應用程式的環境更一致化,例如 testing 環節、stage production,讓容器避開一些差異問題。至於 CD 部分要 delivery 一些 usage 不太一樣的時候,容器會幫忙做配置,所以 CI/CD 對容器的效益是相輔相成的。

Q: 客戶在開發流程漸漸會把 Infrastructure 變成代碼或文檔,是不是可以把程式碼跟現有的應用程式的 CI/CD 流水線整合在一起,達到一套完整的 CI/CD 部署流程?

A:觀察目前市場作法,主要分成兩個階段去做整體部署。如果規模比較小的團隊,會把 Infrastructure 代碼跟 App 代碼分開,在管理上會比較靈活;如果企業規模比較大,會有另外一個 Infrastructure 團隊來控制部署事情,這種情况之下,APP 的項目會生成一個 APP package,主要做到 delivery 這個階段爲止。而 Infrastructure 的項目會指定把需要版本的文檔,部署到他們的 Kubernetes Cluster。

填寫表單 找到適合的快速上雲服務與工具!