支援 Hugging Face 生產基礎設施的三大警報
Hugging Face 的基礎設施團隊很高興能與大家分享 Hugging Face 生產基礎設施的幕後工作,我們有幸參與了其構建和維護。我們的團隊致力於設計和實施一個強大的監控和警報系統,這對確保我們平臺的穩定性和可擴充套件性至關重要。我們時刻銘記,警報對於我們識別和響應潛在問題,防止其演變成重大事件的能力有著巨大的影響。
在這篇博文中,我們將深入探討在支援我們的生產基礎設施方面發揮獨特作用的三個強大警報,並探討它們如何幫助我們維持社群所依賴的高水平效能和正常執行時間。
高 NAT 閘道器吞吐量
在雲計算架構中,資料在私有網路和公共網路之間流動,實施 NAT(網路地址轉換)閘道器通常是一項堅定的最佳實踐。這個閘道器充當一個戰略性的守門員,監控並促進所有流向公共網際網路的出站流量。透過集中管理出口流量,NAT 閘道器為全面的可見性提供了一個戰略制高點。我們的團隊可以輕鬆查詢和分析這些流量,使其成為處理安全、成本最佳化或各種其他調查場景時的寶貴資產。
成本最佳化是雲基礎設施管理的一個關鍵方面,而理解定價動態是關鍵。在資料中心,定價結構通常區分東西向流量(通常是同一機架或建築物內的通訊)和南北向流量(較遠的私有網路之間或與網際網路的通訊)。透過監控網路流量,Hugging Face 可以獲得有關這些流量模式的寶貴洞察。這種認知使我們能夠就基礎設施配置和架構做出明智的決策,確保我們限制不必要的成本產生。
我們的一個關鍵警報旨在當我們的網路流量超過預定義閾值時通知我們。這個警報有多種用途。首先,它作為一個預警系統,提醒我們任何可能指示潛在問題或意外行為的異常流量激增。其次,它促使我們定期審查我們的流量趨勢,確保我們跟上基礎設施的增長和不斷變化的需求。這個警報設定了一個靜態閾值,我們隨著時間的推移對其進行了微調,以確保其保持相關和有效。當它被觸發時,通常與我們重構基礎設施的時期相吻合。
例如,在整合第三方安全和自動擴充套件工具時,我們觀察到從我們的節點流出的遙測資料增加,這觸發了警報並促使我們最佳化配置。
在另一次調整基礎設施時,我們錯誤地避開了一條連線特定產品基礎設施(例如,從 Space 到 Hub 用於與倉庫資料互動的流量)的私有、低成本路徑。更詳細地說,我們發現對成本節約影響最大的工作負載是那些訪問物件儲存的工作負載。直接獲取物件比透過 CDN 託管的資產為我們的 LFS 倉庫儲存獲取更便宜,並且與到達我們前端的公共請求相比,它不需要我們 WAF 提供的同樣的安全措施。利用 DNS 覆蓋來切換私有網路路徑和公共網路路徑之間的流量已成為我們的一項寶貴技術,這得益於 CDKTF AWS 提供商。
new Route53ResolverFirewallRule(
stack,
`dns-override-rule-${key}-${j}`,
{
provider: group?.provider!,
name: `dns-override-${dnsOverride.name}-${rule[0]}`,
action: 'BLOCK',
blockOverrideDnsType: 'CNAME',
blockOverrideDomain: `${rule[1]}.`,
blockOverrideTtl: dnsOverride.ttl,
blockResponse: 'OVERRIDE',
firewallDomainListId: list.id,
firewallRuleGroupId: group!.id,
priority: 100 + j,
},
);
最後需要說明的是,雖然我們有“配置即程式碼”來確保期望的狀態始終有效,但在此基礎上增加一個警報層有助於在透過程式碼表達期望狀態時出錯的情況下提供保障。
Hub 請求日誌歸檔成功率
Hugging Face 的日誌基礎設施是一個複雜的系統,旨在收集、處理和儲存由我們的應用程式和服務生成的大量日誌資料。該系統的核心是 Hub 應用程式日誌管道,這是一個架構精良的解決方案,確保 Hub 模型使用資料被高效地捕獲、豐富和儲存,以用於報告和歸檔。該管道始於 Filebeat,這是一個輕量級的日誌收集器,在每個 Kubernetes 叢集中作為守護程序集與我們的應用程式 Pod 一起執行。Filebeat 的作用是從各種來源(包括應用程式容器)收集日誌,並將它們轉發到管道的下一階段。
一旦日誌被 Filebeat 收集,它們就會被髮送到 Logstash,一個強大的日誌處理工具。Logstash 充當資料處理的主力,對傳入的日誌應用一系列的修改和轉換。這包括用 GeoIP 資料豐富日誌以獲得地理位置洞察,根據預定義的標準將日誌路由到特定的 Elasticsearch 索引,以及透過新增、刪除或重新格式化日誌欄位來操縱它們,以確保一致性和分析的便利性。在 Logstash 處理完日誌後,它們會被轉發到一個 Elasticsearch 叢集。
Elasticsearch 是一個分散式搜尋和分析引擎,構成了我們日誌儲存和分析平臺的核心。它從 Logstash 接收日誌,並透過 Elasticsearch 管道應用自己的一套處理規則。這些管道執行最少的處理任務,例如新增時間戳欄位以指示處理時間,這對於日誌分析和關聯至關重要。Elasticsearch 提供了一個可擴充套件且靈活的儲存解決方案,允許我們為運營使用和即時分析緩衝日誌。
為了管理 Elasticsearch 內的日誌生命週期,我們採用了一個強大的儲存和生命週期管理策略。這確保日誌在 Elasticsearch 中保留一段定義的時間,為運營和故障排除提供快速訪問。在這個保留期之後,日誌被解除安裝到長期歸檔儲存。歸檔過程涉及一個自動化工具,該工具從 Elasticsearch 索引中讀取日誌,將它們格式化為 Parquet 檔案(一種高效的列式儲存格式),並將它們寫入我們的物件儲存系統。
我們日誌管道的最後階段利用了 AWS 資料倉庫服務。在這裡,我們使用 AWS Glue 爬蟲來發現和分類我們物件儲存中的資料,自動生成一個 Glue 資料目錄,它提供了一個統一的元資料儲存庫。Glue 表的模式會定期重新整理,以確保它與我們日誌資料不斷變化的結構保持同步。與 AWS Glue 的這種整合使我們能夠使用 Amazon Athena(一個無伺服器的互動式查詢服務)來查詢歸檔的日誌。Athena 允許我們直接對物件儲存中的資料執行 SQL 查詢,為日誌分析和歷史資料探索提供了一個成本效益高且可擴充套件的解決方案。
日誌管道雖然設計得非常精細,但並非沒有挑戰和潛在的故障點。其中最關鍵的漏洞之一在於系統的彈性,特別是在 Elasticsearch 叢集中。作為一個分散式系統,Elasticsearch 在各種情況下都可能遇到背壓,例如高入口流量、密集的查詢或像分片重定位這樣的內部操作。當發生背壓時,它可能導致整個管道出現一系列問題。例如,如果 Elasticsearch 叢集不堪重負,它可能會開始拒絕或延遲日誌攝入,導致 Logstash 甚至 Filebeat 出現積壓,這可能導致日誌丟失或處理延遲。
另一個脆弱點是 Elasticsearch 中的自動模式檢測機制。雖然它旨在適應變化的日誌結構,但當應用程式日誌的欄位型別發生重大變化時,它可能會失敗。如果模式檢測未能識別新的欄位型別,可能會導致從 Logstash 到 Elasticsearch 的寫入失敗,從而引起日誌處理瓶頸和潛在的資料不一致。這個問題凸顯了主動日誌模式管理以及需要強大的監控來及時檢測和解決此類問題的重要性。
記憶體管理也是管道穩定性的一個關鍵方面。日誌處理層,包括 Logstash 和 Filebeat,為了控制成本,在有限的記憶體資源下執行。當發生背壓時,這些元件可能會遇到記憶體不足(OOM)問題,尤其是在系統減速期間。隨著日誌積壓和背壓增加,這些程序的記憶體佔用會增長,使它們更接近其極限。如果不能及時處理,這可能導致程序崩潰或進一步加劇背壓問題。
負責將日誌從 Elasticsearch 傳輸到物件儲存的歸檔作業也遇到了挑戰。有時,這些作業可能資源密集,其效能對節點大小和記憶體可用性變得敏感。在垃圾資料或異常大的日誌條目透過管道的情況下,它們可能會給歸檔過程帶來壓力,導致因記憶體耗盡或節點容量限制而失敗。這強調了在管道早期進行資料驗證和過濾的重要性,以防止此類問題到達歸檔階段。
為了減輕這些潛在的故障,我們實施了一個強大的警報系統,其動機獨特:驗證端到端的日誌流。該警報旨在 **比較我們的應用程式負載均衡器(ALB)收到的請求數量與成功歸檔的日誌數量**,從而全面瞭解整個管道中的日誌資料流。這種方法使我們能夠快速識別任何可能指示潛在日誌丟失或處理問題的差異。
警報機制基於一個簡單而有效的比較:我們 ALB 收到的請求數(代表進入系統的總日誌量)與我們長期儲存中成功歸檔的日誌數。透過監控這個比率,我們可以確保輸入和輸出一致,從而為我們的日誌基礎設施的健康狀況提供一個有力的驗證。當警報被觸發時,它表示可能存在不匹配,促使立即進行調查和修復。
在實踐中,這個警報被證明是一個有價值的工具,尤其是在基礎設施重構期間。例如,當我們將 ALB 遷移到一個 VPC 源時,該警報在識別和解決由此產生的日誌流差異方面起到了關鍵作用。然而,它也在一些不太明顯的情況下拯救了我們。例如,當歸檔作業因不可預見的問題未能執行時,該警報標記了缺失的歸檔日誌,使我們能夠迅速調查和解決問題,以免影響我們的日誌分析和保留過程。
雖然這個警報是一個強大的工具,但它只是我們全面監控策略的一部分。我們不斷完善和調整我們的日誌基礎設施,以處理不斷增長的日誌資料量和複雜性。透過結合主動監控、高效的資源管理以及對我們系統行為的深刻理解,Hugging Face 確保我們的日誌管道保持彈性、可靠,並能夠支援我們平臺的增長和不斷變化的需求。這個警報證明了我們致力於維護一個強大而透明的日誌系統,為我們的團隊提供他們所需洞察,以保持 Hugging Face 的平穩執行。
Kubernetes API 請求錯誤和速率限制
在運營雲原生應用和基於 Kubernetes 的基礎設施時,即使是看似微小的問題,如果不加檢查,也可能升級為嚴重的停機。對於 Kubernetes API 尤其如此,它作為 Kubernetes 叢集的中樞神經系統,協調容器的建立、管理和網路。在 Hugging Face,我們透過經驗認識到,監控 Kubernetes API 錯誤率和速率限制指標是一項至關重要的實踐,可以防止潛在的災難。
Hugging Face 的基礎設施與 Kubernetes 深度整合,而 kube-rs
庫在高效構建和管理這個生態系統中起到了關鍵作用。kube-rs
提供了一種以 Rust 為中心的 Kubernetes 應用開發方法,為開發者提供了一個熟悉而強大的工具包。其核心是,kube-rs
引入了三個關鍵概念:反射器 (reflector)、控制器 (controller) 和自定義資源介面 (custom resource interface)。反射器確保 Kubernetes 資源的即時同步,使應用程式能夠對變化做出迅速反應。控制器,作為決策者,持續協調資源的期望狀態和實際狀態,使 Kubernetes 具有自愈能力。自定義資源介面擴充套件了 Kubernetes,允許開發者定義特定於應用的資源,以實現更好的抽象。
此外,kube-rs
還引入了監視器 (watcher) 和終結器 (finalizer)。監視器監控特定資源的變化,以響應事件觸發動作。另一方面,終結器透過定義自定義邏輯來確保資源的正確清理和終止。透過為這些 Kubernetes 概念提供基於 Rust 的抽象,kube-rs
使開發者能夠構建健壯、高效的應用程式,利用 Kubernetes 平臺的能力和靈活性,同時保持以 Rust 為中心的開發方法。這種整合簡化了構建和管理複雜 Kubernetes 應用程式的過程,使其成為 Hugging Face 基礎設施中的一個寶貴工具。
Hugging Face 與 Kubernetes 的整合是我們基礎設施的基石,而 kube-rs
庫在管理這個生態系統中扮演著關鍵角色。kube::api::
模組在自動化各種任務中起著重要作用,例如為支援我們 Spaces 產品的自定義域名管理 HTTPS 證書。透過程式設計方式處理證書生命週期,我們確保了服務的安全性和可訪問性,為使用者提供了無縫的體驗。此外,我們在日常維護中也在面向使用者的特性之外使用了這個模組,以促進節點排空和終止,從而在基礎設施更新期間保證叢集的穩定性。
kube::runtime::
模組對我們同樣至關重要,它使我們能夠開發和部署自定義控制器,從而增強我們基礎設施的自動化和彈性。例如,我們在我們的託管服務中為賬單管理實現了控制器,其中客戶 Pod 上的監視器和終結器確保了準確的資源跟蹤和計費。這種級別的定製化使我們能夠根據我們的具體需求調整 Kubernetes。
透過 kube-rs
,Hugging Face 在我們的雲原生應用上實現了高水平的效率、可靠性和控制。該庫以 Rust 為中心的設計與我們的工程理念相符,使我們能夠利用 Rust 在管理 Kubernetes 資源方面的優勢。透過自動化關鍵任務和構建自定義控制器,我們建立了一個可擴充套件、自愈的基礎設施,以滿足我們使用者和企業客戶多樣化且不斷變化的需求。這種整合展示了我們致力於充分利用 Kubernetes 的潛力,同時保持一種為我們獨特需求量身定製的開發方法。
雖然我們的基礎設施很少遇到與 Kubernetes API 相關的問題,但我們仍然保持警惕,尤其是在部署期間和部署之後。Kubernetes API 在我們使用 kube::runtime::
管理客戶 Pod 和雲網絡資源方面是一個關鍵元件。API 通訊中的任何中斷或低效都可能對我們的服務產生連鎖效應,可能導致停機或效能下降。
監控這些 API 指標的重要性,可以從其他 Kubernetes 使用者的經驗中得到印證。例如,OpenAI 分享了一份 狀態更新,詳細說明了 DNS 可用性問題如何導致了重大停機。雖然這與 Kubernetes API 不直接相關,但他們的經歷凸顯了各種基礎設施元件之間的相互關聯性以及連鎖故障的可能性。正如 DNS 可用性對應用程式的可訪問性至關重要一樣,一個健康且響應迅速的 Kubernetes API 對於管理和協調我們的容器化工作負載也至關重要。
作為一項最佳實踐,我們已將這些 API 指標整合到我們的監控和警報系統中,確保任何異常或趨勢都能及時引起我們的注意。這使我們能夠採取主動的方法,在問題影響客戶之前進行調查和處理。例如,有一次一個叢集開始對 Kubernetes API 的請求進行速率限制。我們追溯到這是由於我們的一個第三方工具遇到了一個 bug,它反覆請求排空一個已經排空了的節點。作為回應,我們能夠在系統出現任何明顯的使用者影響之前,將這個故障作業從系統中清除。這是一個很好的例子,說明警報場景不僅僅是在部署我們自定義控制器的新版本後立即發生——bug 可能需要一些時間才能表現為生產問題。
總之,雖然我們的基礎設施是穩健且架構良好的,但我們認識到,警惕和主動監控對於維持其健康和穩定至關重要。透過密切關注 Kubernetes API 的錯誤率和速率限制指標,我們保護我們的託管服務,確保順暢的客戶體驗,並堅守我們對可靠性和效能的承諾。這證明了我們的信念:在雲原生技術的世界裡,每個元件,無論多小,都在我們平臺的整體彈性和成功中扮演著重要角色。
附加警報:新叢集傳送零指標
感謝您閱讀到這裡,這是一個附加警報!
在 Hugging Face,我們的實驗不斷變化,隨著我們迭代功能和產品,通常會有特定用途的叢集啟動和關閉。為了增加這種混亂度,我們的增長也是一個重要因素,叢集會擴充套件到其極限,然後觸發類似減數分裂的拆分以保持平衡。為了在這種動態環境中導航,而無需硬編碼或引入額外的叢集發現層,我們設計了一個巧妙的警報來適應這些變化。
(
(sum by (cluster) (rate(container_network_transmit_packets_total{pod="prometheus"}[1h] ) ) > 0)
or
(-1 * (sum by (cluster) (rate(container_network_transmit_packets_total{pod="prometheus"}[1h] offset 48h) ) > 0))
) < 0
此查詢中使用的指標是 **`container_network_transmit_packets_total`**,它表示容器傳輸的總資料包數。該查詢正在過濾來自叢集本地 Prometheus 例項的指標,該例項負責指標收集以及向我們的中央指標儲存——Grafana Mimir 進行遠端寫入。資料包的傳輸近似於健康的遠端寫入,這是我們希望在所有活動叢集中確保的。
查詢的第一部分執行當前速率檢查。查詢的第二部分透過使用與當前速率檢查相同的計算加上一個 **`offset 48h`** 子句來執行歷史速率檢查。**`-1 *`** 乘法用於反轉結果,因此如果歷史速率大於 0,結果將小於 0。
**`or`** 運算子將查詢的兩個部分結合起來。如果滿足以下任一條件,查詢將返回 **`true`**:
- 叢集的當前資料包傳輸速率大於 0。
- 叢集的歷史資料包傳輸速率(48 小時前)大於 0,但當前速率不是。
外部的 **`< 0`** 條件檢查 **`or`** 操作的結果是否小於 0。這意味著查詢只有在兩個條件都不滿足時才會觸發,即當一個叢集從未傳送任何指標時(當前和歷史速率都為 0)。
在兩種情況下查詢會觸發:
- 沒有指標的新叢集:添加了一個新叢集,但它還沒有傳送任何指標。在這種情況下,當前和歷史速率都將為 0,查詢將觸發。
- 從未傳送過指標的叢集:一個叢集已經存在超過 48 小時,但它從未傳送過任何指標。在這種情況下,歷史速率將為 0,當前速率也將為 0,從而觸發查詢。
在這兩種情況下,查詢都會檢測到叢集沒有傳送任何指標並觸發警報。
這個簡單而有效的解決方案在我們指標基礎設施崩潰、叢集設定期間以及它們被拆除時都會觸發,為我們提供了對基礎設施健康的及時洞察。雖然它可能不是我們武器庫中最關鍵的警報,但它有一個特殊的位置,因為它誕生於協作。這是透過 Hugging Face 基礎設施團隊同事的專業知識和樂於助人精神,經過嚴格的程式碼審查,實現團隊合作力量的證明 🤗
總結
在這篇文章中,我們分享了一些我們最喜歡的、支援 Hugging Face 基礎設施的警報。我們也想聽聽你們團隊最喜歡的警報!
您是如何監控您的 ML 基礎設施的?哪些警報讓您的團隊不斷回來進行修復?您的基礎設施中經常出問題的是什麼?或者反過來,您從未監控過但一直執行良好的又是什麼?
請在下面的評論中與我們分享!