採集層:資料怎麼進來——OpenTelemetry 與 Alloy

· tech

#observability#opentelemetry

📑 目錄

三支柱講完了,但有個前提一直被我跳過:訊號要先「進得來」,才有得看第一篇資料流圖中間那格「採集層」,這篇把它拆開。兩個主角:OpenTelemetry(統一三種訊號的標準)與 Grafana Alloy(收集、處理、轉送的那隻 agent)。而理解採集層的價值,先看沒有它的世界有多糟。

為什麼要一層 collector:把 M×N 變成 M+N

最直覺的做法,是讓每個 app 直接把 metrics 寫給 Mimir、log 寫給 Loki、trace 寫給 Tempo。app 一多,這條路就崩了:

✗ 直連:M × N 條耦合 app 1 app 2 app 3 Mimir Loki Tempo 每個 app 都要懂每個後端(位址/格式/重試) 換一個後端 → 改「所有」app ✓ 經過 collector:M + N 條 app 1 app 2 app 3 OTLP 一種協定 Collector(Alloy)批次・重試・脫敏・路由 Mimir Loki Tempo 換後端 → 只改 collector 設定,app 一行不動 M 個 app × N 個後端 → M + N:app 只認一種協定(OTLP),後端只面對 collector
直連是 M×N 條耦合:每個 app 都得知道每個後端的位址、格式,自己搞批次與重試;換一個後端(Loki 換版、搬家、換廠商)得改所有 app。加一層 collector 把它變成 M+N:app 只用 OTLP 一種協定丟給本地的 Alloy,批次、重試、脫敏(把 PII 濾掉)、路由全部集中在一處;換後端只改 collector 設定。跟 Schema RegistryCNI 同一種「中間標準層」的智慧——解耦生產者與消費者,是基礎設施百用不膩的一招

OpenTelemetry:三種訊號,一套標準

採集層能這麼乾淨,靠的是 OpenTelemetry(OTel) 這個業界統一標準。它解決的歷史問題是:以前三支柱各有各的 SDK 與協定——metrics 用 Prometheus client、log 用各家 shipper、trace 用 Jaeger/Zipkin——三套東西各自為政,log 裡想帶個 trace-id 都要自己接。OTel 把三者統一:一套 SDK、一個協定(OTLP)、共用同一份 context。實務上兩層:

  • Instrumentation(埋測):自動埋測先上——各語言的 OTel agent 自動幫 HTTP server/client、DB driver、訊息佇列產生 trace 與 metrics,常常零改碼就有八成覆蓋;手動埋測再補——業務關鍵處自己開 span、記自訂 metric。
  • 共用 context 是關鍵紅利:因為三種訊號出自同一套 SDK,trace-id 會自動塞進 log、exemplar 會自動掛上 metric——上一篇說「找 trace-id 的活交給 metric 和 log」,能成立的前提就是這裡接好了。這也是下一篇「三支柱互跳」的地基。

Grafana Alloy 就是那隻在你環境裡跑的 collector(OTel Collector 的 Grafana 發行版,前身 Grafana Agent):收 OTLP、也能像 Prometheus 一樣主動 scrape /metrics、也能撿容器的 log 檔——收齊後統一處理、轉送 LGTM。

在 K8s 上怎麼佈:DaemonSet、sidecar,還是 gateway

① DaemonSet(預設首選) node pod pod Alloy ×1(收整台) 每 node 一隻,成本固定 共享:一隻掛,整台暫時失明 ② Sidecar(特例才用) pod app agent每 pod 一隻 隔離最好、設定可各自客製 成本 × pod 數,貴 ③ 中央 gateway gateway(Deployment)統一出口・可水平擴 跨節點的處理放這: tail sampling(整條 trace 聚一處才能判斷) 全域限流・統一對外出口(防火牆只開一個洞) 單獨用少;通常搭 ① 當第二層 實務常見「兩層」:DaemonSet 就地收(便宜)→ gateway 集中管(取樣/限流/出口) 起步只要 ①;要 tail sampling 或多叢集統一出口時,再加 ③
① DaemonSet:每台 node 跑一隻 Alloy,收本機所有 pod 的訊號——成本固定、佈署簡單,預設首選② Sidecar:每 pod 塞一隻,隔離最好但成本乘上 pod 數,特殊隔離需求才用。③ 中央 gateway:一組可水平擴的 Deployment 當統一出口,跨節點的處理只能放這——最典型的是 tail sampling:要「看完整條 trace 再決定留不留」,而一條 trace 的 span 散在多台 node,必須先聚到一處。實務常見兩層:DaemonSet 就地收、gateway 集中管——起步只要 ①,痛了再加 ③

反思

「中間加一層標準」是基礎設施最划算的一筆投資

M×N 變 M+N 這張圖,畫的時候我一直有既視感——Schema Registry 之於事件格式、CNI/CSI 之於 K8s 的網路與儲存、OTLP 之於觀測訊號——全是同一招:在生產者與消費者之間立一個標準,兩邊就再也不用認識彼此。 它的回報在「變動的那天」兌現:換掉 Loki、加一個新後端、或哪天離開 Grafana 生態,app 一行不用改。所以我把「埋測一律走 OTel,不用任何廠商私有 SDK」當成團隊的硬規矩——埋測是散在幾百個服務裡、最難回頭改的程式碼,它必須綁標準,不能綁廠商。 這是可觀測性領域裡,少數「現在多想一步、未來省一個大型專案」的決策。

OTel 真正的殺手級價值,是「共用 context」

很多人把 OTel 理解成「又一套 SDK」,但它真正的殺手鐧是三種訊號出自同一套 context:trace-id 自動進 log、exemplar 自動掛上 metric——「從指標尖峰跳到那條 trace、再跳到那行 log」這條黃金路徑,不是 Grafana 端的魔法,是採集端就把關聯 ID 種好了。這讓我想通一個常見的失敗模式:很多團隊三支柱都有、卻各自為政(metrics 一套 agent、log 一套 shipper、trace 另一套),結果事故當下三邊資料對不起來,一塊玻璃變三個孤島。關聯不是查詢時才做的事,是採集時就要種下的事——這句話是我看採集層架構時的第一檢查點,也是下一篇「三支柱互跳」的引子。

佈署拓撲的選擇,又是那道「成本 vs 隔離 vs 集中」的老題

DaemonSet、sidecar、gateway 三選,判準跟我在整個 infra 之旅看過的每一次都同構:共享省錢(DaemonSet)、隔離貴但乾淨(sidecar)、集中才能做全域決策(gateway)。最有意思的是 tail sampling 這個例子——它從原理上就規定了拓撲:整條 trace 的 span 散在多台機器,「看完再決定」就必須先聚到一處,所以這功能只能活在 gateway 層。這提醒我一件事:佈署拓撲很多時候不是風格選擇,是功能的物理需求反推出來的。我的實務順位照舊:DaemonSet 起步,別過早架 gateway——等你真的需要 tail sampling 或多叢集統一出口,那個「痛」自然會把第二層叫出來。先確認痛點,在採集層一樣適用。