Skip to content

SRE: How Google Runs Production Systems 讀書筆記(一)

  • Ops
  • Google SRE 全球共計約 1000 人
  • SRE 是一群天生的懷疑論者,懷疑一切「高大尚」技術,以及任何「神奇的產品」
  • SRE 在確保系統可靠性方面沒有什麼萬靈丹,有的只是極度的務實(progmatic)
  • 如果用一個詞來描述 Google 的歷史,那就是不斷的 scaling up
  • 系統維運本質上是人與電腦共同參預的一項系統性工程
  • IT 產業大多自我封閉,交流過少,很多從業人員或多或少受到教條主義的限制
  • 今天我們能感受到整個業界都在鼓吹厚顏無恥的「給我程式碼,其餘免談」;開源社群內部也正在形成一種「別問我問題」的風氣,過於強調平等卻忽略專家的意見
  • 相對於最終的軟體結果、架構設計,真實的設計過程和作者本身的思考歷程更具價值
  • 一套軟體的 40% ~ 90% 成本,其實是花費在建置之後的不斷維護過程

SRE 的工作範疇

  • 維運具體服務
  • 設計研發大型分散式系統
  • 協助產品部門開發其系統的額外元件,如負載平衡,同時盡可能重複使用這些元件
  • 想出各式各樣的方法,利用現有元件解決新的問題
  • 對架構設計、維運流程不斷最佳化,讓這些大型系統有更好的「可靠性」

  • 可靠性(reliability)——系統能夠在指定環境下,在要求的時間內成功持續執行某個功能的機率
  • SRE 的 「S」最開始指的是 google.com
  • SRE 是從 Google 的內部職位、從 Web 社群中誕生的
  • 與 DevOps 一詞不同的是,SRE 同樣認同 IaC,但 SRE 最關注的是可靠性(或者說是風險),甚至可以為了可靠性而「消除維運的需求」
  • 可靠性就像安全性,愈早關注愈好
  • 「無論對一套系統的執行原理掌握得多麼透徹,也不能阻止人為的意外錯誤。」
  • SRE 的 「E」可以指事 —— Engineering,也可以是指人——Engineer

入門

傳統的分工模式:Dev/Ops 分離,有以下問題:

  • 直接成本:系統管理員(sysadmin)大部分依賴人工來處理/維護事件及變更,隨著系統複雜度增加,會需要更多人力成本
  • 間接成本:兩個部門的落差/代溝,代價通常會比直接成本高很多

兩個業務目標本質上是矛盾的

  • Dev: 如何快速部署、迭代版本(隨時改動)
  • Ops: 如何避免故障(不要改動)

  • SRE 模型是為了解決 Dev/Ops 的矛盾——請軟體工程師開發軟體/系統,來維護系統執行
  • SRE 運用軟體工程的思維和方法,建構自動化工具來取代人工操作(傳統 sysadmin 做的事)
  • Google SRE 的組成:
    • 50-60%:軟體工程師
    • 40-50%:具備 85-99% 軟體工程師標準,但同時具備其他能力(UNIX、layer 1-3 的網路經驗)
  • SRE 必須要有足夠時間開發自動化程式—— Google SRE 的傳統維運工作最多只能佔 50% (工單處裡、on-call、手動操作)
  • SRE 應致力於消除所有基本維運工作,不只是人工作業自動化(automated),終極目標是讓系統能自動修復、自主執行的無人化(automatic)
  • 管理階層維持 SRE 團隊的工作均衡的手段:
    • 持續衡量每個團隊的工作時間分配
    • 將一般維運工作做交還產品研發團隊負責
    • 從產品研發團隊調人參與 on-call
    • 要求停止任何新增的維運工作
  • SRE 文化在公司內部是代表一種快速、創新、擁抱變化的文化
  • SRE 和研發團隊之間的成員可以自由流動,整個產品部門的人員都有機會學習和參與大規模部署活動
  • 如何招聘合適的 SRE 是一個大難題:要求更高、需要和 RD 部門競爭
  • SRE 有時需要採取違反傳統的作法,須要管理階層強力支持
  • 可將 DevOps 視為 SRE 核心理念的通用版,反之,SRE 是 DevOps 模型在 Google 的具體實踐

SRE 的核心方法論

持續關注開發

  • 維運工作限制在 50% 以內,避免過度維運,超過的話須採取暫時性措施,此模式需要產品部門的認同與配合
  • 每 8~12 小時 on-call 期間最多只能處理兩個緊急事故,確保有足夠時間追蹤、排除故障、撰寫事後報告
  • 事後檢討(postmortem):沒有觸發警報的事故(漏洞)更值得檢討、對事不對人

符合 SLO 的同時維持最快的更迭速度(Maximum Change Velocity)

  • 不以「零故障」為目標、任何產品都無法作到 100% 可靠
  • 建立合理的可靠性目標(Service-Level Objective, SLO),如果可靠性是 99.99%,那錯誤預算(error budget)就是 0.01%。
  • 可靠性目標考慮下列幾點:
    • 基於使用者習慣,怎樣的可靠度是使用者滿意的?
    • 如果服務的可靠性不夠,使用者是否有別的替代選擇?
    • 服務的可靠性是否會影響使用者的使用模式?
  • 錯誤預算用在發行新功能,幫助衡量新功能何時可以最快上線

監控系統

  • 超過監控值自動發信這種策略效益很有限
  • 警報訊息應該由系統自動分析,只有須人為介入時才通知
  • 三種輸出:
    • alert:須立即做出回應與處理
    • ticket:沒有立即性的危害,允許幾天內完成操作
    • logging:用於調校與分析,平時不會看

緊急應變

  • 衡量可靠性的指標是平均故障間隔時間(MTTF)、平均修復時間(MTTR)
  • 透過事先模擬、將最佳處理方法紀錄在「維運手冊(playbook)」上,通常至少可讓 MTTR 降低 3 倍

變更(change)管理

  • 大約 70% 的系統事件是因部署變更導致的
  • 使用自動化來完成:
    • 漸進式(progressively)更新
    • 發生問題時迅速退回變更(roll-back)
    • 快速、準確定義問題

容量(capacity)規劃

  • 是一個容易被忽略的一般性概念
  • 有幾個必要步驟:
    • 自然成長的需求預測(demand forecast)
    • 自然成長以外的需求來源(demand-resources)統計
    • 週期性壓力測試,用來對比實際數字
  • 跟資源部署一樣,應由 SRE 主導

Provisioning(譯做資源配置)

  • 是變更管理與容量規劃的結合
  • 必須盡快完成(要精確)、必要才做,因為資源很昂貴
  • 風險較高

效率與效能

  • 改善資源使用率(透過容量規劃)可以有效降低成本
  • 整體資源使用情況受下列三者影響:
    • 流量
    • 服務的可用容量
    • 軟體的演算法
  • 設定一個特定的延遲時間(response speed)作為目標,來規劃容量
  • SRE 團隊和產品研發團隊應該共同監控系統效能

從 SRE 視角看 Google 正式環境

這章開頭的問題意識是為什麼 Google 要把伺服器明確區分成「實體 machine」跟「軟體 server」,並以資料中心的拓樸結構來說明

img

其中一個原因是想把硬體故障跟實際業務使用者區隔開來,因為硬體的損壞率極高(每年幾千起,損失幾千顆硬碟)

具體管理方法是用了 Borg 做叢集管理跟資源分配——也就是 Kubernetes 的前身


硬體伺服器

實體伺服器的網路通訊是透過自建的 Switch,以 Clos 結構連接(inlet x outlet 的一個 2-d 矩陣,無論在什麼負載情況下都能保證連線的建立),集合成一個虛擬 Switch 擁有上萬個虛擬通訊埠

各個資料中心透過主幹廣域網路(WAN) B4,特色是透過動態管理,達到最大平均頻寬(最佳化)

Borg 負責安排叢集內的實體伺服器執行 job(由多個 task 組成),由於 task 跟 machine 不是一對一,必須透過一個抽象層:由 BNS(Borg Naming Server)去分配一個名稱跟索引,例如 /bns/<cluster>/<user>/<job name>/<task number>,連線時,透過這個名稱去跟 BNS 問 <IP address>:<port>

為了提高實體伺服器的使用率,根據 task 定義的資源,Borg 會選擇最適合的機器去執行,同時盡量分散 job 的 task 避免單點故障

如果 task 超用資源,會被重啟——緩慢、不斷重啟比洩漏資源不重啟更好


叢集持久化(persistent)的部份,透過兩個重要的底層服務:D、Clossus

每台實體機器都跑 D(無論是 HDD 還是 SSD),再透過上層的 Clossus 整合整個叢集的硬碟,提供單一介面——這種儲存系統跟 HDFS 類似

再上去的話可以透過幾個資料庫服務存取:BigTable、Spanner


跟資源分配一樣,頻寬也是動態分配(由 Bandwidth Enforcer, BwE 分配),要作到這點,必須透過集中式的路由計算(分散式的路由會有流向遷徙問題)

服務可能是跨叢集的,為了降低延遲,請求會盡量導到地理位置最近的 BNS(透過全球負載平衡系統 GSLB)


Q: 如果同時有五台閒置實例,要分派給那一台?

透過名為 Chubby 的 lock service,做 master-election——保障了 Reliability 和 Consistency(透過類似檔案系統的 API 來鎖定,可跨地)


監控系統運行在資料中心層級,從實例中擷取「監控指標」 (metric)


軟體伺服器

軟體大多採用多執行緒去提高 CPU 利用率

每個軟體伺服器都有一個 HTTP 服務用於查詢 task 的運行情況

所有 Google 軟體服務通訊都透過名為 Stubby 的遠端程序呼叫(RPC)——開源版本就是 gRPC,傳輸格式是 protobuf(比 xml 小 3-10 倍,序列化快 20-100 倍)

軟體伺服器透過它的前端(frontend/client) 接收 RPC 請求,轉發到它的後端(backend/server) 處理


開發環境

所有專案都放在同一個共享 repo,有個優點是開發者可以直接提交修正(changelist, CL)到基礎元件的專案


請求的處理過程

img

  1. 訪問服務站點,DNS 解析後向 GSLB 取得 IP 位址
  2. 訪問該 IP 位址,連接到反向代理(layer 4, TCP)
  3. 反向代理透過 GSLB 找到服務可用的前端,發送一份 RPC 請求(含請求內文)
  4. 服務的前端解析 RPC 中的 HTTP 請求內文、建構一個新的 protobuf,一樣再透過 GSLB 找到服務可用的後端,轉發
  5. 後端處理請求,回傳給前端後,由前端去建構 HTTP 響應內文

從這個流程,可以看出集中式的路由怎麼運作的,尤其突顯 GSLB 的重要性(DNS、GFE、App FE、App BE 都要詢問它)


N+2 模式

假設服務可處理的 qps 為 100,調查得出尖峰流量為 3470,至少需要 35 個實例,N+2 後為 37 實例

  • 系統更新時(例如 rolling update),只有 36 個可用
  • 同時又有一台實例出問題,剩下 35 個可用,剛好滿足尖峰需求

為了更進一步降低延遲,也須觀察流量來源地區(例如 70% 來自北美),根據各個地區的流量分別部署不同數量的服務

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *