3 億用戶的美版“小紅書”Pinterest 是如何建立 Kubernetes 平臺的?

導讀: 可能國內讀者不太熟悉 Pinterest,但它在美國,可是坐擁 3 億用戶的美版“小紅書”,媲美社媒巨頭!如果你熟悉“小紅書”,那麼你就很容易理解 Pinterest 的定位了。在如此龐大體量的 Pinterest,是如何建立 Kubernetes 平臺的?

爲什麼選擇 Kubernetes?

在過去的幾年裏,有 3 億多 Pinner 在 Pinterest 上保存了超過 2000 億次 Pin,覆蓋了超過 40 億個 Board。爲了服務於這個龐大的用戶羣和內容池,我們開發了數以千計的服務,從少數幾個 CPU 的微服務到佔用整個虛擬機羣的巨大整體服務。還有來自各種不同框架的批處理作業,它們可以是 CPU、內存或 I/O 密集型。

譯註: 要理解這段話,譯者有必要在這裏簡單介紹一下 Pinterest 及其基本元素。Pinterest 是一個圖片社交平臺,堪稱圖片版的 Twitter,用戶可以發表自己的 Pin,也可以轉發自己喜歡的圖片。Pinterest 採用的是瀑布流的形式展現圖片內容,無需用戶翻頁,新的圖片不斷自動加載在頁面底端,讓用戶不斷的發現新的圖片。Pinterest 裏面有一些基本元素。如 Pin。Pin 即你在 Pinterest 上發表的帖子,發佈 Pin 的人統稱被稱爲 Pinner。一個 Pin 通常是由一張圖片,一個到外部網頁的鏈接和幾句簡短的描述組成,並且發佈的時候需要將其歸類到它所屬的 Board 裏。

爲了支持這些不同的工作負載,Pinterest 的基礎架構團隊面臨着多種挑戰:

  • 工程師在啓動工作負載時並沒有統一的體驗。無狀態服務、有狀態服務和批處理作業由完全不同的技術棧部署和管理。如此一來,給工程師們帶來了陡峭的學習曲線,同時也給基礎架構團隊帶來巨大的維護和客戶支持負擔。
  • 管理自己的虛擬機羣的工程師給 infra 團隊帶來了巨大的維護負擔。操作系統或 AMI 升級等簡單的操作可能需要耗時數週到數月的時間才能完成。生產工作負載在這些過程中也會遇到干擾,而這些過程本應對生產工作負載是透明的。
  • 很難在獨立的管理系統之上構建基礎架構治理工具。對我們來說,更難確定哪些機器的歸屬,以及它們是否可以安全回收。

容器編排系統提供了統一工作負載管理的方法。它們還爲更快的開發速度和更容易的基礎架構治理鋪平了道路,因爲所有運行的資源都由集中式系統管理。

圖 1:基礎架構優先級(服務可靠性、開發人員生產力和基礎架構效率)

Pinterest 的雲管理平臺團隊早在 2017 年就開始了在 Kubernetes 的旅程。到 2017 年上半年,我們將大部分生產工作負載進行了容器化(包括核心 API 和 Web 服務器集羣)。然後,通過構建產品集羣並在其上運行實際工作負載,來對不同的容器編排系統進行廣泛的評估。到 2017 年底,我們決定沿着 Kubernetes 的道路走下去,因爲它具有靈活性,而且還有廣泛的社區支持。

到目前爲止,我們已經基於 Kops 構建了自己的集羣引導工具,並將現有的基礎架構組件集成到 Kubernetes 集羣中,如網絡、安全性、指標、日誌記錄、身份管理和流量等。我們還引入了 Pinterest 特定的自定義資源來模擬我們的獨特工作負載,同時對開發人員隱藏運行時的複雜性。我們現在工作的重點是集羣穩定性、可擴展性和客戶支持。

Kubernetes:Pinterest 選擇的路

運行 Kubernetes 來支持 Pinterest 這樣規模的工作負載,同時又要讓它成爲我們工程師喜愛的平臺,真的是一個很大的挑戰。

作爲一個大型組織,我們在基礎架構工具上投入了大量資金,例如處理證書和密鑰分發的安全工具、支持服務註冊和發現的流量組件,以及提供日誌和指標的可見性組件。這些組件都是基於艱難的經驗教訓上構建的,因此我們希望將它們整合到 Kubernetes 內,而不是“重新發明輪子”。這一做法也使得遷移變得更加容易,因爲我們的內部應用已經獲得了所需的支持。

另一方面,Kubernetes 本機工作負載模型(如部署、作業和守護進程集)並不足以爲我們自己的工作負載進行建模。可用性問題是採用 Kubernetes 的巨大障礙。例如,我們曾經聽到服務開發人員抱怨丟失或錯誤配置的原因“擾亂”了他們的終端。我們還看到批處理作業用戶使用模板工具生成數百個同一作業規範的副本,最終導致了調試噩夢。

對工作負載的運行時支持也在不斷髮展,因此在同一個 Kubernetes 集羣上支持不同版本將會變得異常困難。想象一下,如果我們需要面對許多版本的運行時,客戶支持的複雜性,以及爲它們進行升級或修補 bug 該有多大的困難。

Pinterest 自定義資源和控制器

爲了讓我們的工程師更容易地採用 Kubernetes,並使基礎架構開發更快速、更順暢,我們設計了自己的自定義資源(Custom Resource Definitions,CRD)

CRD 提供了以下功能:

  1. 將各種本機 Kubernetes 資源捆綁在一起,使它們作爲單一工作負載進行工作。例如,PinterestService 資源將部署、服務、入口和應用配置管理組合在一起,因此服務開發人員無需擔心爲他們的服務設置 DNS。
  2. 爲應用程序注入必要的運行時支持。用戶只需關注自己業務邏輯的容器規範即可,而 CRD 控制器將必要的邊車容器(sidecar)、初始容器、環境變量和卷(volume)注入到它們的容器節點(pod)規格中。這爲應用工程師帶來了開箱即用的體驗。
  3. CRD 控制器還可以對本機資源進行生命週期管理,並處理可見性和可調試性。這包括但不限於協調所需的規格和實際規格、CRD 狀態更新和事件記錄。如果沒有 CRD 的話,應用工程師必須管理更多的資源,而且這個過程已經被證明很容易出錯。

下面是 PinterestService 和由控制器轉換的本機資源的示例:

圖 2:CRD 到本機資源。左邊是用戶編寫的 Pinterest CR,右邊是控制器生成的本機資源定義。

如圖所示,爲了支持用戶的容器,我們需要插入一個初始容器和幾個邊車容器,以保證安全性、可見性和網絡流量。此外,我們在批處理作業中引入了應用配置管理模板和 PVC 模板支持,以及許多環境變量來跟蹤身份、資源利用率和垃圾收集。

難以想象工程師會願意在沒有 CRD 支持的情況下手工編寫這些配置文件,更不用說維護和調試配置了。

應用程序部署工作流

圖 3:Pinterest CRD 概述

圖 3 展示瞭如何將 Pinterest 自定義資源部署到 Kubernetes 集羣:

  1. 開發人員通過命令行界面(CLI)和用戶界面(UI)與我們的 Kubernetes 集羣進行交互。
  2. CLI/UI 工具從 Artifactory 檢索工作流配置 YAML 文件和其他構件屬性(如版本 ID),並將它們發送到作業提交服務。這樣可以確保只向 Kubernetes 集羣提交已審查和已登錄的工作負載。
  3. 作業提交服務是各種計算平臺(包括 Kubernetes)的“網關”。用戶身份驗證、配額強制和部分 Pinterest CRD 配置驗證都在這裏進行。
  4. 一旦 CRD 通過了作業提交服務驗證,它就會被髮送到 Kubernetes API。
  5. 我們的 CRD 控制器監視所有自定義資源上的事件。它將 CR 轉換爲 Kubernetes 本機資源,將必要的邊車容器添加到用戶定義的容器節點中,設置適當的環境變量,並執行其他必要的內務處理工作,以確保用戶的應用程序容器具有足夠的基礎架構支持。
  6. 然後,CRD 控制器將生成的本機資源寫回 Kubernetes API 中,以便調度器(scheduler)可以提取這些資源並開始運行。

注意:這是新的基於 Kubernetes 的計算平臺的早期採用者使用的預發佈部署工作流。我們正對這一體驗進行改進,使其與我們新的 CI/CD 平臺完全繼承,以避免暴露過多 Kubernetes 具體的細節。我們期待在即將發佈的博文《爲 Pinterest 構建 CI/CD 平臺》中分享我們的動機、進展和後續影響。

自定義資源類型

基於 Pinterest 的具體需求,我們設計了以下適合不同工作流的 CRD:

  • PinterestService 是長期運行的無狀態服務。許多核心繫統都基於一組此類服務。
  • PinterestJobSet 爲運行到完成的批處理作業建模。Pinterest 中一個非常常見的模式是,多個作業並行運行相同的容器,每個作業都只佔用工作負載的一小部分,而不依賴於彼此。
  • PinterestCronJob 被據用輕量級週期性工作負載的團隊廣泛採用。PinterestCronJob 是圍繞本機 cron 作業的包裝器,支持 Pinterest 特有的安全性、流量、日誌和指標等。
  • PinterestDaemon 僅限於與基礎架構相關的守護進程。隨着我們在集羣上添加更多的支持,PinterestDaemon 的家族仍在增長。
  • PinterestTrainingJob 封裝了 TensorFlow 和 PyTorch 作業,提供了與所有其他 CRD 相同級別的運行時支持。由於 Pinterest 大量使用 TensorFlow 和其他機器學習框架,因此圍繞他們構建專門的 CRD 是有意義的。

我們還有正在構建的 PinterestStatefulSet ,將很快被用於存儲和其他有狀態系統。

運行時支持

當應用程序容器節點在 Kubernetes 上啓動時,它會自動獲得一個證書標識自己。此證書用於通過 mTLS 訪問機密存儲或與其他服務進行通信。同時,配置管理初始容器和守護進程將確保在應用程序容器啓動之前就下載好所有必需的依賴項。當應用程序容器準備就緒時,流量邊車容器和守護進程將會向容器節點註冊到 Zookeeper,以便讓客戶端可以發現它。甚至在容器節點啓動之前,網絡守護進程就已經爲容器節點設置好了網絡。

以上就是服務工作負載的典型運行時支持的示例。其他工作負載類型可能需要稍微不同的支持,但他們都是以容器節點級邊車容器、節點級守護進程集或虛擬機級守護進程的形式出現的。我們確保所有這些應用程序都是由基礎架構團隊部署,以便它們在所有應用程序之間保持一致,從而極大減少我們的維護和客戶支持的負擔。

測試與質量保證

我們在本機 Kubernetes 測試基礎上構建了一個端到端的測試管道。這些測試部署到所有的集羣。這個管道在到達生產集羣之前就已經經歷了多次迴歸。

除了測試基礎架構之外,還有監視和報警系統,這些系統持續監控系統組件的健康狀態、資源利用率和其他關鍵指標,在需要人工干預時通知我們。

備選方案

我們考慮了一些自定義資源的備選方案,比如變異許可控制器和模板系統。但是,所有的備選方案都存在重大問題,因此我們選擇了 CRD 的路徑。

  • 變異許可控制器以用於注入邊車容器、環境變量和其他運行時支持。然而,它很難講資源捆綁在一起以及管理它們的生命週期,而 CRD 則需要協調、狀態更新和生命週期管理功能。
  • 模板系統(如 Helm charts)也被廣泛用於啓動具有類似配置的應用程序。但是,我們的工作負載過於多樣化,無法通過模板進行管理。我們還需要支持持續部署,這在使用模板時很容易出錯。

未來的工作

目前,我們在所有的 Kubernetes 集羣上運行混合工作負載。爲了支持不同大小和類型的工作負載,我們正在開展一下方面的工作:

  • 集羣聯邦(Cluster Federation)將大型應用程序分佈在不同的集羣上,以實現可擴展性和穩定性。
  • 集羣穩定性、可擴展性和可見性,確保應用程序到達其服務級別協議。
  • 資源和配額管理,以確保應用程序不會相互干擾,集羣規模得到控制。
  • 新的 CI/CD 平臺,支持 Kubernetes 上的應用程序部署。

作者介紹:

本文作者爲 Lida Li、June Liu、Rodrigo Menezes、Suli Xu、Harry Zhang、Roberto Rodriguez Alcala。他們均爲 Pinterest 軟件工程師,負責雲計算管理平臺。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章