云原生下的可觀測數據采集實踐,看這一篇就夠了!
本文根據余韜老師在 GOPS 2022·上海站演講整理而成,更多精彩,請關注高效運維公眾號。
作者簡介:
余韜,阿里巴巴技術專家。
10年工作經驗,目前就職于阿里巴巴日志服務可觀測平臺團隊,負責iLogtail開源,主要關注大數據分析、數據采集Agent、海量數據接入治理等領域。
曾負責百度統計、百度分析云產品的研發工作。
一、可觀測數據類型與價值
1.1 IT系統的可觀測性
“可觀測性”最早起源于電氣領域,指的是一個系統如果是可觀測的,它的狀態可以由外部輸出來推斷。比如一個汽車引擎,普通告警只能知道它的總體狀態,如果加入儀表盤,比如水溫、氣壓、轉速,我們就可以大致定位它的故障方向,如果要解決這個問題,還是要依賴于組件內每個傳感器的詳細觀測數據。

在IT系統領域,可觀測性卻是近幾年才越來越熱的,我覺得和IT系統的發展有一定關系。最初軟件系統相對簡單,開發工作僅由幾個人就能完成,每個人都對整個系統有完整了解。隨著業務越來越復雜,涉及到的模塊越來越多,很難有一個人了解系統全貌,此時就需要通過將它的可觀測性數據展示出來以定位問題。
隨著軟件的復雜性增加,跨團隊合作也會越來越多,團隊間的溝通或排障也需要提高效率,防止推諉,因此需要拿數據說話,對可觀測性數據的需求也越來越突出。軟件運行環境也隨著系統的基礎組件云化趨勢,變得越來越復雜。從單機到容器化,再到現在的云原生。越來越多的組件依賴第三方或者云上的云原生接口,使這個系統越來越像一個黑盒,不利于穩定性運行。
可觀測性數據暴露就是希望將這些黑盒的東西白盒化。通常我們會把可觀測性數據分為三類:Log,Traces,Metric。
1.2 IT系統可觀測性場景與應用演進
這三類數據的定義是比較寬泛的,并不局限于運維領域。例如在線上運營領域,通過在APP上增加埋點數據,可以觀測到用戶使用中的卡點問題,進行針對性的用戶體驗改進;在線下運營領域,通過在商場使用 WIFI 或者監控設備來統計人流,可以解決新店選址或人流疏導難題。在交通領域,通過地圖數據或者車聯網數據,可以解決城市交通治理問題。
可以看到可觀測性數據的應用價值和潛力非常巨大。我們回到大會的運維主題,現在很多企業上云,第一件事就是把應用部署到 K8s。下面我們簡單介紹一下 K8s 下業務部署特點及數據采集需求。
二、K8s下業務部署特點及數據采集需求
2.1 自動裝箱、彈性擴縮容

K8s 具有自動裝箱和彈性擴縮容的能力,部署應用只需要進行聲明即可實現編排,大大解放了研發人員部署的精力和時間。同時,也因為應用部署效率提高,使得應用的版本迭代變得非常快,應用的混布也會變得頻繁,單節點資源利用率大幅提高。為了幫助不同需求的應用進行不同形態的部署K8s提供了非常豐富的控制器并提供擴展能力。有些控制器提供了水平拓展、滾動更新能力,都是非常常見且實用的,這些功能也會使得系統中的容器創建和消亡比較快。
2.2 資源抽象、混合使用
第二個是資源抽象,K8s使得不同軟件和硬件的節點都可以在一個集群中統一調度混合使用。為了更好地管理這些異構資源,我們通常將相似的資源節點分配到同一個節點池里,比如說有的節點池是linux系統的主機,有些是windows系統的主機,有些是配備 GPU 的主機。將這些節點統一由一個K8s Master管理時,能使機器資源利用最大化。
而節點本身除了可以是物理主機外,也可以是虛擬節點。比如說阿里云的 ECI 服務,其實就是把一個 pod 模擬成一個 Virtual Kubelet,使得它也能當做一個節點接受任務調度。當資源向其調度的時候,它的容器實際跑在云上的 Serverless 資源上,而不是物理的節點上。這種資源抽象能力,使得應用部署的靈活性大大提高。比如說混合云場景,有些客戶會在線下自建一個機房,將穩定流量工作負載放在自建機房上,對于一些可能有流量突增的工作負載則放在具備彈性伸縮能力的云節點上。
2.3 存儲抽象、靈活編排
K8s 對存儲進行了比較好的抽象,可以滿足應用不同的數據持久化需求。同時這樣的抽象也使得容器再不用關心底層存儲的細節,如磁盤從哪里掛載,只需要聲明存儲的類型、容量和IO需求。這使得部署在 K8s 的應用可以突破單機磁盤限制,一定程度上讓所有應用都有了一定的存算分離能力。
三、K8s下可觀測數據采集的常見挑戰
K8s 給我們提供了一系列靈活和方便的部署能力的同時也給可觀測性的數據采集帶來一些挑戰。下面以這四點進行講解:
3.1 采集部署運維復雜
K8s 部署方便靈活,導致一個節點上的容器有可能非常多,我們怎么能夠部署一個采集端采集這么多異構混布容器,怎么管理這么多采集對象。在 K8s 環境下容器部署變化非常快,比如說進行動態擴縮容的時候,很可能流量上來和下去的時候容器就很快創建和銷毀了;而節點資源不足的時候,容器的被驅逐現象也是非常常見的,這就使得容器的生命周期可能非常短暫,需要采集端快速發現容器,同時避免數據采集丟失。
3.2 容器和節點運行環境多樣
隨著容器技術發展,容器運行的環境越來越多樣化。以前都是用 Docker 進行容器運維,隨著 K8s 崛起,逐漸地 Docker 運行時邊緣化,目前最新的版本都是默認支持 Containerd 運行時,同時還有 CRI-O 等新興的容器運行時。這些運行時的出現使采集節點上的容器數據不再只有一種格式,同時不同運行時的通信機制也可能不同,對應容器的內容存放路徑也各不相同,這就使得采集器需要適配多樣的運行時環境。
而容器運行的節點環境,包括物理機、VM、虛擬節點。對于虛擬節點的部署模式和物理機是不同的,特別是容器元信息和數據保存周期和物理機不同,這些都需要采集端和節點具備合理的配合方案,避免數據采集不到。

3.3 單節點日志規模大
多種因素的作用下使得節點的日志規模變大。
- 混合部署,單機部署比較傾向于部署一個單體結構應用。但在 K8s上,一個節點部署 50 個以上實例也非常常見。
- 磁盤,傳統節點使用的是本機硬盤(HDD/SSD),即使是SSD IO吞吐極限也只有約 500MB/s;K8s 節點(特別是云上節點),可以利用云盤,最高規格速率可以達到 1 GB/s。
- 存儲擴展能力,單機部署通常掛載 NAS,K8s 則支持多種存儲種類的掛載,使用 PVC 實現靈活擴展,突破單機的讀寫速度和容量瓶頸。
在實際應用中也遇見過單節點產生巨量日志的用戶,比如某打車APP,在一個節點上同時部署APP埋點定位數據/GPS定位數據/車輛實時后臺數據接收等等,使得單節點采集200M/s以上的日志。
3.4 可觀測數據異構

K8s 節點本身就有多種媒介,例如有標準輸出、PVC日志、容器日志。
同時在 Log/Metric/Traces 上會分別有不同數據輸入源:在 Log 方面因為應用混部,同時要收集多種格式日志,像業務應用、MySQL binlog、Nginx Access Log 等數據。在 Metric 方面,通常需要采集 Prometheus 指標。在 Traces 方面,則又有 SkyWalking 等數據需要收集。如此復雜的采集需求使得單節點上采集的客戶端需要同時支持采集多種類型的可觀測數據才能達到使用要求。
這些情形都對端上采集構成了新的挑戰。
四、對應問題處理方案與實踐
我們從采集部署、環境、日志規模和異構數據四方面來分享。
4.1 采集部署
部署模式

通常端上的采集器在 K8s 有兩種部署模式:一種是 DaemonSet,一種 Sidecar。DaemonSet 是在一個節點上部署一個采集器讓它來采集節點上所有容器的日志,Sidecar 模式是在業務容器中同時起一個并行的采集容器并通過共享存儲來采集業務容器的日志。
DaemonSet 模式有幾個明顯優點:耦合性比較低,每個應用不需要單獨為它修改部署,直接可以進行采集;性價比高,只需要使用一份容器的資源就可以采到整個節點數據,和業務部署數量有解耦。
Sidecar 也有它的應用場景,比如日志量特別大的容器,采集需要和其他進行隔離,可以提供比較高的隔離性,同時它的靈活性也有一定好處。
配置分發
采集客戶端部署之后,如何管理這些采集對象?涉及到配置分發。比較簡單的做法是利用 K8s ConfigMap 分發配置,但它的缺點也比較明顯:
- ConfigMap 有大小限制
- 分發不靈活,每組采集器需要單獨配置
為了解決這些問題,可以用 ConfigServer 進行中心化配置下發,有圖形界面支持,對運維人員管控比較方便;在各個 Agent 上有標識,可以靈活實現分組;也不受 ConfigMap 大小限制,可以支持大量的配置,單節點最多能夠穩定支持 1000 個配置。

這樣的部署方式已經可以滿足大規模的應用,但在某些場景下也有些不足:
比如用戶在 CI/CD 流水線里部署應用的同時希望下發日志配置將日志采集上來,這時候用 ConfigServer 的 API 就需要定制一個組件來通信,不太方便。
配置自動化
我們也能夠通過 CRD 的方式進行配置,這種方式能夠獲得 ConfigServer 的所有好處,同時能夠更好地在自動化流水線中集成采集配置的下發,直接使用 CRD 這一標準 K8s資源對于這些流水線組件沒有額外的開發代價。

如圖所示,綠色的是 log-controller,它會實時監聽采集的 CRD,CRD 是由 YAML 文件描述,如果 YAML 文件新增、刪除或變更,這些事件會觸發 log-controller 將配置同步到 ConfigServer 上,在容器中部署的 iLogtail 則從 ConfigServer 拉取采集配置,這樣就實現了采集配置的聲明式部署。
這種方法在某些特殊場景下也不是完全適用,比如說配置特別多,而且 K8s 的 APIServer 存儲沒有改造,對 APIServer 壓力也是個需要考慮的。
Job場景支持
我們知道 K8s 場景下容器快速變化,比較典型的是 Job 控制器部署的容器。Job 的特點是跑完就結束了,所以增刪 Pod 的頻率很高。例如,有些 CI/CD 任務非常短,僅僅幾秒,就容易丟數據。還例如,在無人車模擬場景里,會同時起幾千個 Pod,瞬時新增容器并發量極大,這都是我們在采集時要考慮的因素。
實踐中得出以下經驗:
- 需要盡快發現容器,鎖定文件句柄。
- 需要召回探測間隔期間退出的容器,有些容器可能因出錯在探測間隔期間剛創建就退出了,這時候在下一次探測時我們不能忽略掉已經退出的容器,需要對退出容器也進行采集,保證數據完整。
- 對于一些關鍵日志,需要打在標準輸出中。因為無論如何,容器銷毀之后,容器內的文件都是無法訪問的,但是標準輸出不太一樣,標準輸出由 Kubelet 單獨管理的,有保存的策略,通常不會立刻被刪除,這樣可以保證在容器快速變化的場景下數據不會丟失。
4.2 運行環境
容器運行時
接下來談一下運行環境適配的問題,首先我們看一下常見的開源 Agent 對于不同部署模式下的采集支持情況。DaemonSet 下容器內文件采集只有 iLogtail 是支持的,iLogtail 是如何做到這一點的?

我們看右邊的圖,iLogtail 發現容器的方式和其他開源軟件不太一樣,不是通過 API Server,它是直接和本地的容器運行時通信來獲得容器的運行元信息。這些信息里會有 Overlay 的信息,這就是容器存放容器內文件的數據位置信息,還有 Mount point和對應掛載的路徑,我們通過這些信息,通過 DaemonSet 可以直接采集到這些數據,不需要如共享卷的方式來采集數據。
但是為了實現這一點,需要對各種運行時進行適配。比如說 Docker 和 Containerd,它們通信的方式就不一樣,我們要自動檢測,它們的標準輸出格式也不一樣,它們對容器內文件存放的位置也不一樣,這些都需要進行特定的適配。我們適配之后,用戶用起來就會比較簡單,只需要通過配置容器上的路徑就能采集,不需要其他的額外工作。
Serverless 支持
剛才談到過容器的運行節點環境比較多樣,其中 Serverless 這種場景怎么支持?Serverless 沒有物理節點,無法部署 DaemonSet,而 Sidecar 采集不了標準輸出,都不是完美解決方案。更為復雜的情況是通過 Virtual Kubelet 實現 HPA 的場景,一部分容器已經運行在實體節點上并使用 DaemonSet 在采集日志,但一旦發生彈性擴縮容,容器創建到虛擬節點上,沒有 DaemonSet 容器,但日志還要采集上來,怎么辦?

來看一下我們是怎么做的。Virtual Kubelet 虛擬節點收到新建容器請求,會通過 ECI 創建一個容器,在 ECI 中同時運行業務容器和 iLogtail 容器。iLogtail 容器用戶不感知,這種模式稱為 hidecar 模式。
ECI 中業務容器的信息,包括 Mount Point 和容器內文件在主機上的位置等,都通過靜態文件發給 iLogtail,這種情況下 iLogtail 的工作模式和 DaemonSet 時非常像,它會通過靜態文件發現容器,同時通過掛載在 iLogtail 容器中的 ECI 根目錄去采集 ECI 節點上的業務容器日志。
通過這種方式,我們就可以比較平滑地讓用戶在沒有感知情況下只考慮使用 DaemonSet 也能采集 ECI Serverless 的容器日志。為了避免丟失數據,ECI 會保證 iLogtail 收到退出信號晚于業務容器。
4.3 單節點日志規模大
單個采集端

首先,iLogtail 的采集性能在各個開源采集器里是比較領先的,極簡模式下可以達到440MB/s,然而默認部署通常會限制 iLogtail 資源,可能達不到極限速度,這時候如果產生日志延時,可以從幾個方面判斷:
- 客戶端。可以增加資源并且調大 iLogtail 并行處理和發送的參數。
- 服務端。日志服務具備自動擴容能力,但對于一些特殊場景,如日志積壓,自動擴容可能有一些延遲,這時候需要手動調整。
- 網絡鏈路。發送端和接受端帶寬是否足夠;中間存在代理則要檢查 VIP、SLB 是否達到上限。如果涉及跨境傳輸,可能需要改進鏈路,比如啟用全球加速或使用企業云網。
多個采集端
如果做了上面優化,仍然有客戶端瓶頸導致的日志延時怎么辦?可以用借用 Sidecar 部署思路(在一個節點上運行多個采集容器),把吞吐量較大的日志拆分出去,部署到多個容器,這樣單節點采集能力不受到一個 DaemonSet 采集器上限限制。
4.4 異構數據的支持
插件框架
iLogtail 誕生之初主要是為了采集文件日志,隨著整個服務上云,云上開放生態建設越來越多,需要接入的數據也越來越多。iLogtail 除了寫入 SLS,也要支持寫入第三方日志庫。
為了應對大量輸入輸出需求,我們為 iLogtail 做了插件化的框架方便擴展,C++部分主要是處理文件、接受采集配置、發送數據等核心功能,插件負責接入一些別的輸入源,例如 Binlog、Syslog 都是通過插件實現的;同時對接第三方數據源也是通過插件輸入,在改造過程中也是把一些 iLogtail 處理能力進行了插件化,使得處理不局限于 Parse 一種,而是可以利用多個處理插件在端上進行靈活組合,實現端上輕量級處理流水線。
iLogtail可觀測性數據生態支持

目前 iLogtail 的生態在 Log 方面,一直是 iLogtail 的強項,除了支持容器數據采集外,還增加了 Windows Event、eBPF 等一些數據源。在 Metric 方面,有 Telegraf、Prometheus 數據源,OpenTelemetry 數據格式接入也在進行中。Trace 方面主要接入 Skywalking 的數據。輸出方面除了支持阿里云的 SLS,也支持了 Kafka 的寫入,并且支持格式轉換可以被 CK、ES 等直接消費。對 CK 和 ES 的直接寫入支持,目前也在規劃中。
基于 eBPF 的無侵入采集
下面介紹 eBPF 的接入和可觀測性采集辦法。對于端上的 Trace 和 Metric 數據接入,通常來說需要用 SDK 在應用中進行埋點。雖然也有無埋點數據采集,如使用 Java Agent,但受限于特定語言。有沒有辦法將無侵入采集推廣到其他語言?eBPF 技術提供了這樣的可能性。
在 ilogtail 的實現中 eBPF 的采集原理分為用戶態和內核態。內核態主要是通過 Kprobe 模塊用一定規則去抓取系統調用的數據,對它進行解包并關聯下發配置、進行過濾,把過濾后的解析數據發送到用戶態。
用戶態拿到的數據通常只有一些id信息,并不完整,ilogtail 使用一些插件來采集端上的 Process、容器等元信息,將這些信息與內核態采集的數據進行關聯/聚合,得到完整的數據后再發送到后端。

端上的情況大概是這樣,完整的構建采集方案還需要結合服務端整體的能力。除了采集數據 DaemonSet 的 iLogtail,完整的方案還需要部署 Deployment 的 iLogtail 來拿到更詳細的集群和容器信息,有了這個數據已經可以構建完整的主機監控。進一步我們可以從云上拿到云資產信息,再進行一次 join 以得到更加完整的 K8s 鏈路拓撲。
對于這些數據,可以對它進行聚合和處理從而得到一些指標數據,可以用來制作儀表盤實現圖形化展示。如果結合黃金指標或者應用 SLS 智能巡檢服務,則可以得到告警事件。如果對這些事件進行處理,我們就能得到完整的運維閉環。

五、開源與未來展望
iLogtail 現在已經開源,大家可以共同參與討論和開發,后續計劃會分成四塊共建:
- 生態拓展:Kafka Flusher 已經支持到2.0,OTLP有1.0的初步支持,ClickHouse Flusher 和 GRPC Input/Output 都在規劃中。
- 框架增強:iLogtail 從日志發展過來,整個數據模型偏向于日志,對時序數據或 Trace 數據,都是通過私有協議和日志服務的 SLS 綁定。對于開源來說,更希望是開放的,有更好的架構支持。
- eBPF:對于四層協議做了比較完整的解析,可以進行流量觀察。對于七層協議,支持 Http/Redis/數據庫類型協議,對于常見的 RPC 框架,有待社區共建。
- 全局管控:配置方案的管控能力,日志服務有商業版的支持,我們也希望把這個能力帶到開源上來。目前管控協議和管控服務已經有個初步的版本,后續希望把前端構建好,并且把如 K8s Operator 能力/iLogtail自身的可觀測性數據也都能集成進來。
Github:https://github.com/alibaba/ilogtail






























