本文已超過一年。較舊的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
Kubernetes 效能測量和藍圖
無論您的容器編排系統有多麼彈性且可靠,最終,您都有一些工作要做,並且希望它能快速完成。對於大型問題,常見的解決方案是投入更多機器。畢竟,更多的計算能力 = 更快,對吧?
有趣的是,新增更多節點有點像火箭方程式的暴政 - 在某些系統中,新增更多機器實際上可能會使您的處理速度變慢。但是,與火箭方程式不同,我們可以做得更好。v1.0 版本的 Kubernetes 支援最多 100 個節點的叢集。但是,我們的目標是在 2015 年底前將我們將支援的節點數量增加 10 倍。這篇部落格文章將涵蓋我們目前的進展以及我們打算如何實現下一個效能等級。
我們測量什麼?
我們需要回答的第一個問題是:「Kubernetes 可以管理 N 節點叢集」是什麼意思?使用者期望它能「合理地快速」處理所有操作,但我們需要對此進行精確的定義。我們決定根據以下兩個指標定義效能和可擴展性目標
1.「API 回應速度」:99% 的 API 呼叫都在 1 秒內返回
2.「Pod 啟動時間」:99% 的 Pod (使用預先提取的映像檔) 在 5 秒內啟動
請注意,對於「Pod 啟動時間」,我們明確假設運行 Pod 所需的所有映像檔都已預先提取到將要運行的機器上。在我們的實驗中,映像檔之間存在高度的變異性 (網路吞吐量、映像檔大小等),而這些變異性與 Kubernetes 的整體效能幾乎無關。
選擇這些指標的決定是基於我們在 Google 每週啟動 20 億個容器的經驗。我們明確希望測量面向使用者的流程的延遲,因為這才是客戶真正關心的。
我們如何測量?
為了監控效能改進並偵測回歸,我們建立了持續測試基礎架構。每隔 2-3 小時,我們從 HEAD 建立一個 100 節點的叢集,並在其上運行我們的可擴展性測試。我們使用 GCE n1-standard-4 (4 核心,15GB RAM) 機器作為主節點,並使用 n1-standard-1 (1 核心,3.75GB RAM) 機器作為節點。
在可擴展性測試中,我們明確地僅關注完整叢集案例 (完整 N 節點叢集是在其中運行 30 * N 個 Pod 的叢集),這是從效能角度來看要求最高的場景。為了重現客戶實際可能執行的操作,我們執行以下步驟
填充 Pod 和複製控制器以填滿叢集
產生一些負載 (建立/刪除額外的 Pod 和/或複製控制器、擴展現有的 Pod 和/或複製控制器等) 並記錄效能指標
停止所有正在運行的 Pod 和複製控制器
抓取指標並檢查它們是否符合我們的預期
值得強調的是,測試的主要部分是在完整叢集 (每個節點 30 個 Pod,100 個節點) 上完成的 - 在空叢集中啟動 Pod,即使它有 100 個節點,也會快得多。
為了測量 Pod 啟動延遲,我們使用非常簡單的 Pod,其中只有一個容器運行「gcr.io/google_containers/pause:go」映像檔,該映像檔啟動然後永遠休眠。保證容器已預先提取到節點上 (我們將其用作所謂的 pod-infra-container)。
效能資料
下表包含 100 節點叢集中 Pod 啟動時間的百分位數 (第 50、90 和 99 個),這些叢集已滿 10%、25%、50% 和 100%。
10% 滿 | 25% 滿 | 50% 滿 | 100% 滿 | |
---|---|---|---|---|
第 50 百分位數 | .90 秒 | 1.08 秒 | 1.33 秒 | 1.94 秒 |
第 90 百分位數 | 1.29 秒 | 1.49 秒 | 1.72 秒 | 2.50 秒 |
第 99 百分位數 | 1.59 秒 | 1.86 秒 | 2.56 秒 | 4.32 秒 |
至於 API 回應速度,以下圖表顯示了按操作種類和資源類型分組的 API 呼叫延遲的第 50、90 和 99 百分位數。但是,請注意,這也包括內部系統 API 呼叫,而不僅僅是使用者發出的呼叫 (在本例中是由測試本身發出的)。
某些資源僅出現在某些圖表上,這取決於該操作期間運行的內容 (例如,當時沒有放置命名空間)。
正如您在結果中看到的那樣,即使在完全填滿的叢集中,我們的 100 節點叢集的 Pod 啟動時間也比目標提前,在第 99 個百分位數中快了 14%。值得指出的是,LIST 列出 Pod 的速度明顯慢於任何其他操作。這是合理的:在完整叢集中有 3000 個 Pod,每個 Pod 大約幾 KB 的資料,這意味著每次 LIST 都需要處理 MB 級的資料。
#####已完成的工作和一些未來計畫
使 100 節點叢集穩定到足以在其上運行任何測試的初始效能工作涉及許多小修復和調整,包括增加 apiserver 中檔案描述符的限制以及重複使用對 etcd 的不同請求之間的 TCP 連接。
但是,建立穩定的效能測試只是將我們的叢集支援的節點數量增加十倍的第一步。作為這項工作的成果,我們已經投入大量精力來消除未來的瓶頸,包括
將控制器重寫為基於 watch:以前,它們每隔幾秒鐘重新列出給定類型的物件,這會在 apiserver 上產生巨大的負載。
使用程式碼產生器產生轉換和深度複製函數:雖然使用 Go 反射的預設實作非常方便,但它們被證明非常慢,與產生的程式碼相比,速度慢了 10 倍之多。
在 apiserver 中新增快取以避免多次反序列化從 etcd 讀取的相同資料
降低更新狀態的頻率:鑑於狀態變更緩慢的特性,僅在變更時更新 Pod 狀態,以及僅每 10 秒更新節點狀態才有意義。
在 apiserver 實作 watch 而不是將請求重新導向到 etcd:我們希望避免多次從 etcd 監看相同的資料,因為在許多情況下,它無論如何都會在 apiserver 中被篩選掉。
展望我們 1000 節點叢集的目標,提出的改進包括
將事件從 etcd 中移出:它們更像是系統日誌,既不是系統狀態的一部分,也不是 Kubernetes 正確運作的關鍵。
使用更好的 json 解析器:在 Go 中實作的預設解析器非常慢,因為它基於反射。
重寫排程器以使其更有效率和並行
提高 apiserver 和 Kubelet 之間通訊的效率:特別是,我們計畫減少每次更新節點狀態時傳輸的資料大小。
這絕不是一份詳盡的清單。我們將根據運行現有的可擴展性測試和新建立的測試時觀察到的瓶頸,新增新元素 (或移除現有元素)。如果您有希望我們解決的特定用例或場景,請加入我們!
- 我們每週四太平洋標準時間上午 11 點舉行 Kubernetes Scale 特別興趣小組的每週會議,在會議上我們討論正在進行的問題以及效能追蹤和改進計畫。
- 如果您在那之前有特定的效能或可擴展性問題,請加入我們 Slack 上的可擴展性特別興趣小組:https://kubernetes.slack.com/messages/sig-scale
- 一般問題?請隨時加入我們 Slack 上的 Kubernetes 社群:https://kubernetes.slack.com/messages/kubernetes-users/
- 提交提取請求或提交問題!您可以在我們的 GitHub 儲存庫中執行此操作。也熱情鼓勵所有人貢獻自己的實驗 (及其結果) 或 PR 貢獻,以改進 Kubernetes。