當您使用 OpenTelemetry Collector 計劃您的可觀測性管道時,您應該考慮隨著遙測收集的增加而擴展管道的方法。
以下部分將指導您完成計劃階段,討論要擴展哪些組件,如何確定何時進行擴展,以及如何執行計劃。
雖然 OpenTelemetry Collector 二進制文件可能對於所有遙測信號類型只有一個,但事實上,每種類型可能都有不同的擴展需求,可能需要不同的擴展策略。首先觀察您的工作負載,確定哪種信號類型預計將佔用最大的負載份額,以及 Collector 預計將接收哪些格式。例如,擴展一個抓取集群與擴展日誌接收器有很大的不同。還要考慮工作負載的彈性:您是否在一天中的特定時間有高峰,或者 24 小時的負載都相似?一旦您收集到這些信息,您就會明白需要擴展什麼。
例如,假設您有數百個 Prometheus 端點需要抓取,每分鐘都有來自 fluentd 實例的一兆字節的日誌,以及一些來自您最新的微服務的應用程序指標和跟踪,它們以 OTLP 格式到達。在這種情境下,您會希望有一個能夠單獨擴展每個信號的架構:擴展 Prometheus 接收器需要在抓取器之間進行協調,決定哪個抓取器轉到哪個端點。相反,我們可以根據需求水平擴展無狀態的日誌接收器。將用於指標和跟踪的 OTLP 接收器放在第三個 Collector 集群中,使我們能夠隔離故障,更快地迭代,而不用擔心重啟繁忙的管道。考慮到 OTLP 接收器使得所有遙測類型的摄取都成為可能,我們可以將應用程序指標和跟踪保持在同一個實例上,根據需要進行水平擴展。
再次強調,我們應該了解我們的工作負載以決定何時擴展或縮減。但是 Collector 發出的一些指標可以提供何時採取行動的好建議。
Collector 可以給你的一個有用提示是指標 otelcol_processor_refused_spans
,當 memory_limiter處理器是管道的一部分時。此處理器允許您限制 Collector 可以使用的記憶體量。雖然 Collector 可能會消耗比這個處理器中配置的最大量稍多的記憶體,但新數據最終將被
memory_limiter``` 阻止通過管道,並在此指標中記錄這一事實。所有其他遙測數據類型都有相同的指標。如果數據太頻繁地被拒絕進入管道,您可能會希望擴展您的 Collector 集群。當節點間的記憶體消耗明顯低於此處理器設定的限制時,您可以縮減擴展。
需要密切關注的另一組指標是與導出器的隊列大小相關的指標:otelcol_exporter_queue_size
和 otelcol_exporter_queue_capacity
。Collector 將在等待工作人員可以發送數據時將數據放入記憶體隊列中。如果沒有足夠的工作人員或後端太慢,數據開始在隊列中堆積,直到容量大小時它會拒絕數據 (otelcol_exporter_enqueue_failed_spans
)。增加更多的工作人員通常會使 Collector 導出更多數據,但這可能不一定是您想要的(參見何時不應該擴展)。
還值得熟悉您打算使用的組件,因為不同的組件可能產生其他指標。例如,負載平衡導出器將記錄導出操作的時間資訊,並將其作為直方圖 otelcol_loadbalancer_backend_latency
的一部分暴露。您可以提取這些資訊以確定所有後端處理請求所需的時間是否相似:單個後端速度過慢可能表示 Collector 之外的問題。
對於進行抓取的接收器,例如 Prometheus 接收器,應當抓取時間經常接近抓取間隔時,進行擴展或分片抓取。當那種情況發生時,是時候添加更多的抓取器,通常是 Collector 的新實例。
知道何時擴展和了解哪些跡象表明擴展操作不會帶來任何好處同樣重要。一個例子是當遙測數據庫無法跟上負載時:在不擴展數據庫的情況下,將 Collector 添加到集群中是無濟於事的。同樣地,當 Collector 和後端之間的網絡連接飽和時,添加更多的 Collector 可能會產生有害的副作用。
再次,捕捉這種情況的一種方法是查看指標 otelcol_exporter_queue_size
和 otelcol_exporter_queue_capacity
。如果您的隊列大小一直接近隊列容量,這是一個跡象,表明導出數據比接收數據慢。您可以嘗試增加隊列大小,這將導致 Collector 消耗更多的記憶體,但它也將給後端一些呼吸的空間,而不會永久地丟棄遙測數據。但如果您持續增加隊列容量,且隊列大小以相同的比例持續上升,這表明您可能想要查看 Collector 之外的情況。還需要注意的是,這裡增加更多的工作人員將不會有所幫助:您只會對一個已經過載的系統施加更大的壓力。
後端可能出現問題的另一個跡象是 otelcol_exporter_send_failed_spans
指標的增加:這表明永久性地將數據發送到後端失敗了。當這種情況持續發生時,擴展 Collector 很可能只會使情況惡化。
此時,我們知道哪部分的流程需要擴展。關於擴展,我們有三種類型的組件:無狀態、掃描器和有狀態。
大多數 Collector 組件都是無狀態的。即使它們在記憶體中保持某些狀態,但出於擴展目的,這不是很重要。
像 Prometheus 接收器這樣的掃描器被配置為從外部位置獲取遙測數據。然後接收器將逐目標進行掃描,將數據放入流程中。
像 tail sampling 處理器這樣的組件不能容易地進行擴展,因為它們在記憶體中保留了一些與其業務相關的狀態。這些組件在擴展之前需要一些仔細的考慮。
好消息是,大多數情況下,擴展 Collector 很容易,因為它只是添加新的副本並使用現成的負載均衡器的問題。當使用 gRPC 接收數據時,我們建議使用理解 gRPC 的負載均衡器。否則,客戶端將始終擊中相同的後端 Collector。
您仍然應該考慮用可靠性為考慮點來分割您的收集流水線。例如,當您的工作負載在 Kubernetes 上運行時,您可能希望使用DaemonSets
在與您的工作負載相同的物理節點上有一個 Collector,以及一個遠程中央 Collector,負責在將數據發送到存儲之前對數據進行預處理。當節點數量少且 pod 數量多時,Sidecars
可能更有意義,因為您將在不需要 gRPC 專用負載均衡器的情況下獲得更好的 gRPC 連接之間的負載均衡。當一個 DaemonSet
pod 失敗時,使用 Sidecar
也可以避免關閉節點中所有 pod 的關鍵組件。
Sidecar 模式包括將容器添加到工作負載 pod 中。OpenTelemetry 操作員可以自動為您添加。為此,您需要一個 OpenTelemetry Collector CR,並且您需要註解您的 PodSpec
或 Pod
,告訴操作員注入 sidecar:
---
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
name: sidecar-for-my-workload
spec:
mode: sidecar
config: |
receivers:
otlp:
protocols:
grpc:
processors:
exporters:
logging:
service:
pipelines:
traces:
receivers: [otlp]
processors: []
exporters: [logging]
---
apiVersion: v1
kind: Pod
metadata:
name: my-microservice
annotations:
sidecar.opentelemetry.io/inject: "true"
spec:
containers:
- name: my-microservice
image: my-org/my-microservice:v0.0.0
ports:
- containerPort: 8080
protocol: TCP
如果您更喜歡繞過操作員並手動添加 sidecar,這裡有一個示例:
apiVersion: v1
kind: Pod
metadata:
name: my-microservice
spec:
containers:
- name: my-microservice
image: my-org/my-microservice:v0.0.0
ports:
- containerPort: 8080
protocol: TCP
- name: sidecar
image: ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector:0.69.0
ports:
- containerPort: 8888
name: metrics
protocol: TCP
- containerPort: 4317
name: otlp-grpc
protocol: TCP
args:
- --config=/conf/collector.yaml
volumeMounts:
- mountPath: /conf
name: sidecar-conf
volumes:
- name: sidecar-conf
configMap:
name: sidecar-for-my-workload
items:
- key: collector.yaml
path: collector.yaml
有些接收器正在主動獲取遙測數據以放入流水線中,例如 hostmetrics
和 prometheus
接收器。儘管獲取主機指標不是我們通常需要擴展的東西,但我們可能需要分割為 Prometheus 接收器抓取數千個端點的工作。我們不能僅僅添加更多具有相同配置的實例,因為每個 Collector 都會嘗試抓取與群集中的每個其他 Collector 相同的端點,導致出現更多的問題,例如順序錯亂的樣本。
解決方案是按 Collector 實例將端點分片,這樣如果我們添加另一個 Collector 的副本,每個副本都會對不同的端點組執行操作。
做到這一點的一種方法是為每個 Collector 擁有一個配置文件,這樣每個 Collector 都只會發現與該 Collector 相關的端點。例如,每個 Collector 都可以負責一個 Kubernetes 命名空間或工作負載上的特定標籤。
擴展 Prometheus 接收器的另一種方法是使用目標分配器:它是一個額外的二進制文件,可以作為 OpenTelemetry 操作員的一部分部署,並將給定配置的 Prometheus 工作的份額分配到使用一致的哈希算法的 Collector 群集。您可以使用以下 Custom Resource (CR) 來使用 Target Allocator:
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
name: collector-with-ta
spec:
mode: statefulset
targetAllocator:
enabled: true
config: |
receivers:
prometheus:
config:
scrape_configs:
- job_name: 'otel-collector'
scrape_interval: 10s
static_configs:
- targets: [ '0.0.0.0:8888' ]
exporters:
logging:
service:
pipelines:
traces:
receivers: [prometheus]
processors: []
exporters: [logging]
在調和後,OpenTelemetry 操作員將 Collector 的配置轉換為以下內容:
exporters:
logging: null
receivers:
prometheus:
config:
global:
scrape_interval: 1m
scrape_timeout: 10s
evaluation_interval: 1m
scrape_configs:
- job_name: otel-collector
honor_timestamps: true
scrape_interval: 10s
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
follow_redirects: true
http_sd_configs:
- follow_redirects: false
url: http://collector-with-ta-targetallocator:80/jobs/otel-collector/targets?collector_id=$POD_NAME
service:
pipelines:
traces:
exporters:
- logging
processors: []
receivers:
- prometheus
請注意,操作員如何添加了一個global
部分和一個新的 http_sd_configs
到 otel-collector
抓取配置,指向它提供的 Target Allocator 實例。現在,要擴展 collectors,請更改 CR 的 “replicas” 屬性,Target Allocator 將通過為每個 collector 實例 (節點) 提供自定義的 http_sd_config
來相應地分配負載。
某些組件可能會在內存中保持數據,當擴展時會產生不同的結果。這是尾部採樣導出器的情況,它在內存中保持一段時間的跨度,只有當跟踪被認為是完整的時候才評估採樣決策。通過添加更多的副本來擴展 Collector 集群意味著不同的 collectors 會接收到給定跟踪的跨度,導致每個 collector 評估該跟踪是否應該被採樣,可能得到不同的答案。這種行為導致跟踪丟失跨度,錯誤地代表了該事務中發生的事情。
與生成服務指標的跨度到指標處理器相似的情況發生。當不同的 collectors 接收到與同一服務相關的數據時,基於服務名稱的聚合將是不准確的。
為了克服這一點,您可以在執行尾部採樣或跨度到指標處理的 Collector 前部署一層包含負載均衡導出器的 Collector。負載均衡導出器將一致地對跟踪 ID 或服務名稱進行哈希,並確定哪個 collector 後端應該接收該跟踪的跨度。您可以配置負載均衡導出器使用給定 DNS A 條目背後的主機列表,例如 Kubernetes 無頭服務。當支持該服務的部署放大或縮小時,負載均衡導出器最終會看到更新的主機列表。或者,您可以指定負載均衡導出器使用的靜態主機列表。您可以通過增加副本數量來擴展配置有負載均衡導出器的 Collector 層。請注意,每個 Collector 可能會在不同的時間運行 DNS 查詢,導致集群視圖在短時間內有所不同。我們建議在高彈性環境中降低間隔值interval
,以便集群視圖只在短時間內有所不同。
以下是使用 DNS A 記錄(Kubernetes 服務 otelcol
在observability
命名空間上)作為後端信息輸入的示例配置:
receivers:
otlp:
protocols:
grpc:
processors:
exporters:
loadbalancing:
protocol:
otlp:
resolver:
dns:
hostname: otelcol.observability.svc.cluster.local
service:
pipelines:
traces:
receivers:
- otlp
processors: []
exporters:
- loadbalancing
OpenTelemetry Collector提供了一個強大的方式來收集、處理和導出遙測數據。當面對不同的工作負載和需要時,知道何時、如何以及不擴展是至關重要的。根據遙測數據類型和收集器組件,您需要密切關注特定的指標以判定是否需要擴展。大多數情況下,擴展Collector相對簡單,只需增加新的副本和使用現成的負載均衡器。但是,對於某些有狀態的組件,擴展需要更多的策略和考慮,以確保數據的準確性和完整性。