Opentelemetry collector用法

charlieroro發表於2024-08-12

Opentelemetry collector用法

目錄
  • Opentelemetry collector用法
    • Service
      • Extensions
      • healthcheckextension
      • Pipelines
    • receiver
      • OTLP Receiver
      • prometheus receiver
      • filelog receiver
    • Processor
      • 資料歸屬
      • Important
      • memory limiter processor
      • batch processor
      • attributes processor && Resource Processor
      • filter processor
      • k8s attributes processor
      • Tail Sampling Processor
      • transform processor
      • routing processor
    • Exporter
      • debug exporter
      • otlp exporter
      • otlp http exporter
      • prometheus exporter
      • prometheus remote write exporter
      • loadbalancing exporter
    • Connector
      • roundrobin connector
      • span metrics connector
    • troubleshooting
    • 擴容
      • 何時擴容
      • 如何擴容
        • stateful

image

Opentelemetry collector包含如下幾個元件

  • receiver
  • processor
  • exporter
  • connector
  • Service

注意這裡只是定義了各個元件,若要真正生效,則需要將其新增到service中.

官方的opentelemetry-collectoropentelemetry-collector-contrib兩個庫給出了大量Collector元件實現。前者是opentelemetry-collector的核心配置,用於提供vendor無關的collector配置,後者則由不同的vendor提供,如aws、aure、kafka等。在使用時可以透過結合二者功能來滿足業務需求。另外值得注意的是,兩個倉庫的各個元件目錄中都提供了README.md幫助文件,如otlpreceiverprometheusremotewriteexporter等。

Service

service欄位用於組織啟用receivers, processors, exporters和 extensions 元件。一個service包含如下子欄位:

  • Extensions
  • Pipelines
  • Telemetry:支援配置metriclog
    • 預設情況下,opentelemetry會在http://127.0.0.1:8888/metrics下暴露metrics,可以透過telemetry.metrics.address指定暴露metrics的地址。可以使用level欄位控制暴露的metrics數(這裡給出了各個level下的metrics):

      • none: 不採集遙測資料
      • basic: 採集基本的遙測資料
      • normal: 預設級別,在basic之上增加標準的遙測資料
      • detailed: 最詳細的級別,包括dimensions 和 views.
    • log的預設級別為INFO,支援DEBUGWARNERROR

Extensions

可以使用extensions實現Collector的認證、健康監控、服務發現或資料轉發等。大部分extensions都有預設配置。

service:
  extensions: [health_check, pprof, zpages]
  telemetry:
    metrics:
      address: 0.0.0.0:8888
      level: normal

healthcheckextension

可以為pod的probe提供健康檢查:

    extensions:
      health_check:
        endpoint: ${env:MY_POD_IP}:13133

Pipelines

一個pipeline包含receivers、processors和exporters集,相同的receivers、processors和exporters可以放到多個pipeline中。

配置pipeline,型別為:

  • traces: 採集和處理trace資料
  • metrics:採集和處理metric資料
  • logs:採集和處理log資料

注意processors的位置順序決定了其處理順序。

service:
  pipelines:
    metrics:
      receivers: [opencensus, prometheus]
      processors: [batch]
      exporters: [opencensus, prometheus]
    traces:
      receivers: [opencensus, jaeger]
      processors: [batch, memory_limiter]
      exporters: [opencensus, zipkin]

下面主要介紹幾種常見的元件配置。

receiver

用於接收遙測資料。

可以透過<receiver type>/<name>為一類receiver配置多個receivers,確保receiver的名稱唯一性。collector中至少需要配置一個receiver。

receivers:
  # Receiver 1.
  # <receiver type>:
  examplereceiver:
    # <setting one>: <value one>
    endpoint: 1.2.3.4:8080
    # ...
  # Receiver 2.
  # <receiver type>/<name>:
  examplereceiver/settings:
    # <setting two>: <value two>
    endpoint: 0.0.0.0:9211

OTLP Receiver

使用OTLP格式接收gRPC或HTTP流量,這種為push模式,即需要client將遙測資料push到opentelemetry:

receivers:
  otlp:
    protocols:
      grpc:
      http:

k8s下可以使用如下方式定義otlp receiver:

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: ${env:MY_POD_IP}:4317 #定義接收grpc資料格式的server
      http:
        endpoint: ${env:MY_POD_IP}:4318 #定義接收http資料格式的server

Receiver本身支援push和pull模式,如haproxyreceiver就是pull模式:

receivers:
  haproxy:
    endpoint: http://127.0.0.1:8080/stats
    collection_interval: 1m
    metrics:
      haproxy.connection_rate:
        enabled: false
      haproxy.requests:
        enabled: true

prometheus receiver

prometheusreceiver支援使用prometheus 的方式pull metrics資料,但需要注意的是,該方式目前處於開發階段官方給出了注意事項不支援的特性

receivers:
    prometheus:
      config:
        scrape_configs:
          - job_name: 'otel-collector'
            scrape_interval: 5s
            static_configs:
              - targets: ['0.0.0.0:8888']
          - job_name: k8s
            kubernetes_sd_configs:
            - role: pod
            relabel_configs:
            - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
              regex: "true"
              action: keep
            metric_relabel_configs:
            - source_labels: [__name__]
              regex: "(request_duration_seconds.*|response_duration_seconds.*)"
              action: keep

filelog receiver

filelog-receiver用於從檔案中採集日誌。

Processor

根據各個processor定義的規則或配置來修改或轉換receiver採集的資料,如過濾、丟棄、重新命名等操作。Processors的執行順序取決於service.pipelines中定義的Processors順序。推薦的processors如下:

  • memory_limiter
  • sampling processors 或初始的filtering processors
  • 依賴Context傳送源的processor,如k8sattributes
  • batch
  • 其他processors

資料歸屬

image

由於一個receiver可能會附加到多個pipelines上,因此可能存在多個processors同時處理來自同一個receiver的資料,這裡涉及到資料歸屬權的問題。從pipelines的角度看有兩種資料歸屬模式:

  • 獨佔資料:這種模式下,pipeline會複製從receiver接收到的資料,各個pipeline之間不會相互影響。
  • 共享資料:這種模式下,pipeline不會複製從receiver接收到的資料,多個pipeline共享同一份資料,且資料是只讀的,無法修改。可以透過設定MutatesData=false來避免獨佔模式下的資料複製。

注意:在官方的文件中有如下警告,即當多個pipelines引用了同一個receiver時,只能保證各個pipeline的資料是獨立的,但由於整個流程使用的是同步呼叫方式,因此如果一個pipeline阻塞,則會導致其他使用使用相同receiver的pipelines也被阻塞

Important

When the same receiver is referenced in more than one pipeline, the Collector creates only one receiver instance at runtime that sends the data to a fan-out consumer. The fan-out consumer in turn sends the data to the first processor of each pipeline. The data propagation from receiver to the fan-out consumer and then to processors is completed using a synchronous function call. This means that if one processor blocks the call, the other pipelines attached to this receiver are blocked from receiving the same data, and the receiver itself stops processing and forwarding newly received data.

memory limiter processor

用於防止collector OOM。該processor會週期性地檢查記憶體情況,如果使用的記憶體大於設定的閾值,則執行一次runtime.GC()memorylimiterprocessor有兩個閾值:soft limithard limit。當記憶體用量超過soft limit時,processor將拒絕接收資料並返回錯誤(因此要求能夠重試發生資料,否則會有資料丟失),直到記憶體用量低於soft limit;如果記憶體用量超過hard limit,則會強制執行一次GC。

推薦將memorylimiterprocessor設定為第一個processor。設定引數如下:

  • check_interval (預設 0s): 記憶體檢查週期,推薦值為1s。如果Collector記憶體有尖刺,則可以降低check_interval或增加spike_limit_mib,以避免記憶體超過hard limit
  • limit_mib (預設 0): 定義hard limit,程序堆申請的最大記憶體值,單位MiB。注意,通常總記憶體會高於該值約50MiB。
  • spike_limit_mib (預設為20%的 limit_mib): 測量記憶體使用之間預期的最大峰值,必須小於 limit_mib.。soft limit 等於 (limit_mib - spike_limit_mib),spike_limit_mib的推薦值為20% limit_mib
  • limit_percentage (預設 0): 透過百分比來定義程序堆申請的最大記憶體,其優先順序低於limit_mib
  • spike_limit_percentage (預設 0): 透過百分比來測量記憶體使用之間預期的最大峰值,只能和limit_percentage配合使用。

使用方式如下:

processors:
  memory_limiter:
    check_interval: 1s
    limit_mib: 4000
    spike_limit_mib: 800
processors:
  memory_limiter:
    check_interval: 1s
    limit_percentage: 50
    spike_limit_percentage: 30

batch processor

batch processor可以接收spans, metrics,或logs,透過壓縮資料來降低資料傳輸所需的連線。

推薦在每個Collector上都配置batch processor,並將其放到memory_limiter和sampling processors之後。有根據大小和間隔時間兩種batch傳送模式。

配置引數如下:

  • send_batch_size (預設 8192): 定義傳送batch的(spans, metric data points或 log records的)數目,超過該數值後會傳送一個batch。
  • timeout (預設 200ms): 定義傳送batch的超時時間,超過該時間會傳送一個batch。如果設定為0,則會忽略send_batch_size並只根據 send_batch_max_size來傳送資料。
  • send_batch_max_size (預設 0): batch的大小上限,必須大於或等於send_batch_size0表示沒有上限。
  • metadata_keys (預設為空): 如果設定了該值,則processor會為每個不同組合的client.Metadata值建立一個batcher例項。注意使用後設資料執行batch會增加batch所需要的記憶體。
  • metadata_cardinality_limit (預設1000): 當 metadata_keys 非空,該值限制了需要處理的metadata key的組合數目。

下面定義了一個預設的batch processor和一個自定義的batch processor。注意這裡只是宣告,若要生效還需在service中引用。

processors:
  batch:
  batch/2:
    send_batch_size: 10000
    timeout: 10s

attributes processor && Resource Processor

Resource Processor可以看作是attributes processor的子集,用於修改資源( span、log、metric)屬性。

attributes processor有兩個主要功能:修改資源屬性,以及資料過濾。通常用於修改資源屬性,資料過濾可以考慮使用filterprocessor

下面是常見的修改資源屬性的方式,類似prometheus修改label。更多參見官方例子

processors:
  attributes/example:
    actions:
      - key: db.table
        action: delete
      - key: redacted_span
        value: true
        action: upsert
      - key: copy_key
        from_attribute: key_original
        action: update
      - key: account_id
        value: 2245
        action: insert
      - key: account_password
        action: delete
      - key: account_email
        action: hash
      - key: http.status_code
        action: convert
        converted_type: int

filter processor

用於丟棄Collector採集的spans、span events、metrics、datapoints和logs。filterprocessor會使用OTTL語法來建立是否需要丟棄遙測資料的conditions,如果匹配任意condition,則丟棄。

traces.span Span
traces.spanevent SpanEvent
metrics.metric Metric
metrics.datapoint DataPoint
logs.log_record Log

如下面丟棄所有HTTP spans:

processors:
  filter:
    error_mode: ignore
    traces:
      span:
        - attributes["http.request.method"] == nil

此外filter processor還支援OTTL Converter functions。如

# Drops metrics containing the 'bad.metric' attribute key
filter/keep_good_metrics:
  error_mode: ignore
  metrics:
    metric:
      - 'HasAttrKeyOnDatapoint("bad.metric")'

k8s attributes processor

該processor可以自動發現k8s資源,然後將所需的metadata資訊注入span、metrics和log中,作為resources屬性。

k8sattributesprocessor在接收到資料(log, trace or metric)時,會嘗試將資料和pod進行匹配,如果匹配成功,則將相關的pod metadata注入該資料。預設情況下,k8sattributesprocessor使用入站的連線IP 和Pod IP進行關聯,但也可以透過resource_attribute自定義關聯方式:

每條規則包含一對from(表示規則型別)和name(如果fromresource_attribute,則表示屬性名稱)。

from有兩種型別:

  • connection:使用連線上下午中的IP屬性匹配資料。使用此型別時,該processor必須位於任何batching或tail sampling之前
  • resource_attribute:從接收的資源中指定用於匹配資料的屬性。只能使用metadata的屬性。
pod_association:
  # below association takes a look at the datapoint's k8s.pod.ip resource attribute and tries to match it with
  # the pod having the same attribute.
  - sources:
      - from: resource_attribute
        name: k8s.pod.ip
  # below association matches for pair `k8s.pod.name` and `k8s.namespace.name`
  - sources:
      - from: resource_attribute
        name: k8s.pod.name
      - from: resource_attribute
        name: k8s.namespace.name

預設情況下會提取並新增如下屬性,可以透過metadata修改預設值:

  • k8s.namespace.name
  • k8s.pod.name
  • k8s.pod.uid
  • k8s.pod.start_time
  • k8s.deployment.name
  • k8s.node.name

k8sattributesprocessor支援從pods、namespaces和nodes的labelsannotations上提取(extract)資源屬性。

extract:
  annotations:
    - tag_name: a1 # extracts value of annotation from pods with key `annotation-one` and inserts it as a tag with key `a1`
      key: annotation-one
      from: pod
    - tag_name: a2 # extracts value of annotation from namespaces with key `annotation-two` with regexp and inserts it as a tag with key `a2`
      key: annotation-two
      regex: field=(?P<value>.+)
      from: namespace
    - tag_name: a3 # extracts value of annotation from nodes with key `annotation-three` with regexp and inserts it as a tag with key `a3`
      key: annotation-three
      regex: field=(?P<value>.+)
      from: node
  labels:
    - tag_name: l1 # extracts value of label from namespaces with key `label1` and inserts it as a tag with key `l1`
      key: label1
      from: namespace
    - tag_name: l2 # extracts value of label from pods with key `label2` with regexp and inserts it as a tag with key `l2`
      key: label2
      regex: field=(?P<value>.+)
      from: pod
    - tag_name: l3 # extracts value of label from nodes with key `label3` and inserts it as a tag with key `l3`
      key: label3
      from: node

完整例子如下,由於k8sattributesprocessor本身也是一個k8s Controller,因此需要透過filter指定listwatch的範圍:

k8sattributes:
k8sattributes/2:
  auth_type: "serviceAccount"
  passthrough: false
  filter:
    node_from_env_var: KUBE_NODE_NAME
  extract:
    metadata:
      - k8s.pod.name
      - k8s.pod.uid
      - k8s.deployment.name
      - k8s.namespace.name
      - k8s.node.name
      - k8s.pod.start_time
   labels:
     - tag_name: app.label.component
       key: app.kubernetes.io/component
       from: pod
  pod_association:
    - sources:
        - from: resource_attribute
          name: k8s.pod.ip
    - sources:
        - from: resource_attribute
          name: k8s.pod.uid
    - sources:
        - from: connection

Tail Sampling Processor

基於預定義的策略來取樣traces。注意,為了有效執行取樣策略,必須在相同的Collector例項中處理一個trace下的所有spans必須將該processor放到依賴context的processors(如k8sattributes)之後,否則重組會導致丟失原始的context。在執行取樣之前,會根據trace_id對spans進行分組,因此無需groupbytraceprocessor就可以直接使用tail sampling processor。

tailsamplingprocessorand是一個比較特別的策略,它會使用AND邏輯串聯多條策略。例如下面例子中的and串聯了多條策略,用於:

  1. 過濾出service.name[service-1, service-2, service-3]的資料
  2. 然後從上述3個服務的資料中過濾出http.route[/live, /ready]的資料
  3. 最後將來自[service-1, service-2, service-3]服務的[/live, /ready]的資料的取樣率設定為0.1
        and:
          {
            and_sub_policy: # and邏輯的策略集
              [
                {
                  # filter by service name
                  name: service-name-policy,
                  type: string_attribute,
                  string_attribute:
                    {
                      key: service.name,
                      values: [service-1, service-2, service-3],
                    },
                },
                {
                  # filter by route
                  name: route-live-ready-policy,
                  type: string_attribute,
                  string_attribute:
                    {
                      key: http.route,
                      values: [/live, /ready],
                      enabled_regex_matching: true, #啟用正規表示式
                    },
                },
                {
                  # apply probabilistic sampling
                  name: probabilistic-policy,
                  type: probabilistic,
                  probabilistic: { sampling_percentage: 0.1 },
                },
              ],
          },

更多參見官方例子

transform processor

該processor包含一系列與Context 型別相關的conditions和statements,並按照配置順序,對接收的遙測資料執行conditions和statements。它使用了一種名為OpenTelemetry Transformation Language的類SQL語法。

transform processor可以trace、metrics和logs配置多個context statements,context指定了statements使用的OTTL Context

Telemetry OTTL Context
Resource Resource
Instrumentation Scope Instrumentation Scope
Span Span
Span Event SpanEvent
Metric Metric
Datapoint DataPoint
Log Log

trace、metric和log支援的Context如下:

Signal Context Values
trace_statements resource, scope, span, and spanevent
metric_statements resource, scope, metric, and datapoint
log_statements resource, scope, and log

每個statement可以包含一個Where子語句來校驗是否執行statement。

transform processor 還支援一個可選欄位,error_mode,用於確定processor如何應對statement產生的錯誤。

error_mode description
ignore processor忽略錯誤,記錄日誌,並繼續執行下一個statement,推薦模式。
silent processor忽略錯誤,不記錄日誌,並繼續執行下一個statement。
propagate processor向pipeline返回錯誤,導致Collector丟棄payload。預設選項。

此外transform processor還支援OTTL函式可以新增、刪除、修改遙測資料。

如下面例子中,如果attribute test不存在,則將attribute test設定為pass

transform:
  error_mode: ignore
  trace_statements:
    - context: span
      statements:
        # accessing a map with a key that does not exist will return nil. 
        - set(attributes["test"], "pass") where attributes["test"] == nil

debug

透過在Collector啟用debug日誌來進行定位:

receivers:
  filelog:
    start_at: beginning
    include: [ test.log ]

processors:
  transform:
    error_mode: ignore
    log_statements:
      - context: log
        statements:
          - set(resource.attributes["test"], "pass")
          - set(instrumentation_scope.attributes["test"], ["pass"])
          - set(attributes["test"], true)

exporters:
  debug:

service:
  telemetry:
    logs:
      level: debug
  pipelines:
    logs:
      receivers:
        - filelog
      processors:
        - transform
      exporters:
        - debug

routing processor

將logs, metrics 或 traces路由到指定的exporter。此processor需要根據入站的HTTP請求(gRPC)首部或資源屬性值來將trace資訊路由到特定的exporters。

注意:

  • 該processor會終結pipeline的後續processors,如果在該processor之後定義了其他processors,則會發出告警。
  • 如果在pipeline中新增了一個exporter,則需要將其也新增到該processor中,否則不會生效。
  • 由於該processor依賴HTTP首部或資源屬性,因此需要謹慎在pipeline中使用aggregation processors(batchgroupbytrace)

配置的必須引數如下:

  • from_attribute: HTTP header名稱或資源屬性名稱,用於獲取路由值。
  • table: processor的路由表
  • table.value: FromAttribute欄位的可能值
  • table.exporters: 如果FromAttribute欄位值匹配table.value,則使用此處定義的exporters。

可選欄位如下:

  • attribute_source: 定義from_attribute的屬性來源:
    • context (預設) - 查詢 context(包含HTTP headers)。預設的from_attribute的資料來源,可以手動注入,或由第三方服務(如閘道器)注入。
    • resource - 查詢資源屬性
  • drop_resource_routing_attribute - 是否移除路由所用的資源屬性。
  • default_exporters:無法匹配路由表的資料的exporters。

舉例如下:

processors:
  routing:
    from_attribute: X-Tenant
    default_exporters:
    - jaeger
    table:
    - value: acme
      exporters: [jaeger/acme]
exporters:
  jaeger:
    endpoint: localhost:14250
  jaeger/acme:
    endpoint: localhost:24250

Exporter

注意opentelemetry的Exporter大部分是push模式,需要傳送到後端。

debug exporter

除錯使用,可以將遙測資料輸出到終端,配置引數如下:

  • verbosity:(預設basic),可選值為basic(輸出摘要資訊)、normal(輸出實際資料)、detailed(輸出詳細資訊)
  • sampling_initial:(預設2),一開始每秒內輸出的訊息數
  • sampling_thereafter:(預設1),在sampling_initial之後的取樣率,1表示禁用該功能。每秒內輸出前sampling_initial個訊息,然後再輸出第sampling_thereafter個訊息,丟棄其餘訊息。
exporters:
  debug:
    verbosity: detailed
    sampling_initial: 5
    sampling_thereafter: 200

otlp exporter

使用OTLP 格式,透過gRPC傳送資料,注意這是push模式,預設需要TLS。可以選擇設定retry和queue

exporters:
  otlp:
    endpoint: otelcol2:4317
    tls:
      cert_file: file.cert
      key_file: file.key
  otlp/2:
    endpoint: otelcol2:4317
    tls:
      insecure: true

otlp http exporter

透過HTTP傳送OTLP 格式的資料

endpoint: "https://1.2.3.4:1234"
tls:
  ca_file: /var/lib/mycert.pem
  cert_file: certfile
  key_file: keyfile
  insecure: true
timeout: 10s
read_buffer_size: 123
write_buffer_size: 345
sending_queue:
  enabled: true
  num_consumers: 2
  queue_size: 10
retry_on_failure:
  enabled: true
  initial_interval: 10s
  randomization_factor: 0.7
  multiplier: 1.3
  max_interval: 60s
  max_elapsed_time: 10m
headers:
  "can you have a . here?": "F0000000-0000-0000-0000-000000000000"
  header1: "234"
  another: "somevalue"
compression: gzip

prometheus exporter

使用 Prometheus 格式暴露metrics,pull模式

  • endpoint:暴露metrics的地址,路徑為/metrics
  • const_labels: 為每個metrics追加的key/values
  • namespace: 如果設定,則指標暴露為<namespace>_<metrics>
  • send_timestamps: 預設false,是否在響應中傳送metrics的採集時間
  • metric_expiration:預設5m,定義暴露的metrics無需更新的時長
  • resource_to_telemetry_conversion:預設false,如果啟用,則會將所有resource attributes轉變為metric labels
  • enable_open_metrics:預設false,如果啟用,則會使用OpenMetrics格式暴露metrics,可以支援Exemplars功能。
  • add_metric_suffixes:預設true,如果false,則不會啟用type和unit字尾。
exporters:
  prometheus:
    endpoint: "1.2.3.4:1234" # 暴露地址為:https://1.2.3.4:1234/metrics
    tls:
      ca_file: "/path/to/ca.pem"
      cert_file: "/path/to/cert.pem"
      key_file: "/path/to/key.pem"
    namespace: test-space
    const_labels:
      label1: value1
      "another label": spaced value
    send_timestamps: true
    metric_expiration: 180m
    enable_open_metrics: true
    add_metric_suffixes: false
    resource_to_telemetry_conversion:
      enabled: true

推薦使用transform processor來將最常見的resource attribute設定為metric labels。

processor:
  transform:
    metric_statements:
      - context: datapoint
        statements:
        - set(attributes["namespace"], resource.attributes["k8s.namespace.name"])
        - set(attributes["container"], resource.attributes["k8s.container.name"])
        - set(attributes["pod"], resource.attributes["k8s.pod.name"])

prometheus remote write exporter

支援HTTP 設定Retry 和 timeout 設定

用於將opentelemetry metrics傳送到相容prometheus remote wirte的後端,如Cortex、Mimir和thanos等。

配置引數如下:

  • endpoint:remote write URL
  • tls:預設必須配置TLS
    • insecure:預設false。如需啟動TLS,則需要配置cert_filekey_file
  • external_labels:為每個metric新增額外的label name和value
  • headers:為每個HTTP 請求新增額外的header。
  • add_metric_suffixes:預設true,如果false,則不會啟用type和unit字尾。
  • send_metadata:預設false,如果true,則會生成併傳送prometheus metadata
  • remote_write_queue:配置remote write的佇列和傳送引數
    • enabled: 啟動傳送佇列,預設true
    • queue_size: 入佇列的OTLP指標數,預設10000
    • num_consumers: 傳送請求的最小workers數,預設5
  • resource_to_telemetry_conversion:預設false,如果true,則會將所有的resource attribute轉變為metric labels。
  • target_info:預設false,如果true,則會為每個resource指標生成一個target_info指標
  • max_batch_size_bytes:預設 3000000 -> ~2.861 mb。傳送給遠端的batch取樣數。如果一個batch大於該值,則會給切分為多個batches。
exporters:
  prometheusremotewrite:
    endpoint: "https://my-cortex:7900/api/v1/push"
    external_labels:
      label_name1: label_value1
      label_name2: label_value2
    resource_to_telemetry_conversion:
      enabled: true # Convert resource attributes to metric labels

推薦使用transform processor來將最常見的resource attribute設定為metric labels。

processor:
  transform:
    metric_statements:
      - context: datapoint
        statements:
        - set(attributes["namespace"], resource.attributes["k8s.namespace.name"])
        - set(attributes["container"], resource.attributes["k8s.container.name"])
        - set(attributes["pod"], resource.attributes["k8s.pod.name"])

loadbalancing exporter

基於routing_key實現spans, metrics 和 logs的負載均衡。如果不配置routing_key,則traces的預設值為traceID,metrics的預設值為service,即相同traceID(或service.name(當service作為routing_key))的spans會被髮送到相同的後端。特別適用於tail-based samplers或red-metrics-collectors這種需要基於完整trace的後端。

需要注意的是負載均衡僅基於Trace ID或Service名稱,且不會考慮實際後端的負載,也不會執行輪詢負載均衡。

routing_key 的可選值為:

routing_key can be used for
service logs, spans, metrics
traceID logs, spans
resource metrics
metric metrics
streamID metrics

可以透過靜態DNS的方式配置後端。當更新後端時,會根據R/N(路由總數/後端總數)重新路由。如果後端經常變動,可以考慮使用groupbytrace processor。

需要注意的是,如果後端出現異常,此時loadbalancingexporter並不會嘗試重新傳送資料,存在資料丟失的可能,因此要求在exporter上配置queue和retry機制

  • 當resolver為static時,如果一個後端不可用,則會所有後端的資料負載均衡失敗,直到該後端恢復正常或從static列表中移除。dns resolver也遵循相同的原則。
  • 當使用k8sdns時,拓撲變更會最終反映到loadbalancingexporter上。

主要配置引數如下:

  • otlp:用於配置OTLP exporter。注意此處無需配置endpoint,該欄位會被resolver的後端覆蓋。
  • resolver:可以配置一個static ,一個 dns,以及一個 k8saws_cloud_map,但不能同時指定4個resolvers。
    • dns中的hostname用於獲取IP地址列表,port指用於匯入traces的埠,預設為4317;interval指定解析間隔,如5s, 1d, 30m,預設5stimeout指定解析超時時間,如5s, 1d, 30m,預設1s
    • k8s中的service指kubernetes的service域名,如lb-svc.lb-nsport指用於匯入traces的埠,預設為4317,如果指定了多個埠,則會在loadbalancer中新增對應的backend,就像不同的pods一樣;timeout指定解析超時時間,如5s, 1d, 30m,預設1s
  • routing_key:用於資料(spans或metrics)路由。目前僅支援tracemetrics 型別。支援如下引數:
    • service:基於service 名稱進行路由。非常適用於span metrics,這樣每個服務的所有spans都會被髮送到一致的metrics Collector中。否則相同服務的metrics可能會被髮送到不同的Collectors上,造成聚合不精確。
    • traceID:根據traceID路由spans。metrics無效。
    • metric:根據metric名稱路由metrics。spans無效。
    • streamID:根據資料的streamID路由metrics。streamID為對attributes和resource、scope和metrics資料雜湊產生的唯一值。

在下面例子中可以確保相同traceID的spans傳送到相同的後端(Pod)上, :

    receivers:
      otlp/external:
        protocols:
          grpc:
            endpoint: ${env:MY_POD_IP}:4317
          http:
            endpoint: ${env:MY_POD_IP}:4318
      otlp/internal:
        protocols:
          grpc:
            endpoint: ${env:MY_POD_IP}:14317
          http:
            endpoint: ${env:MY_POD_IP}:14318
            
    exporters:
      loadbalancing/internal:
        protocol:
          otlp:
            sending_queue:
              queue_size: 50000
            timeout: 1s
            tls:
              insecure: true
        resolver:
          k8s:
            ports:
            - 14317
            service: infrastructure-opentelemetry-tracingcollector.infrastructure-opentelemetry
            timeout: 10s
      otlphttp/tempo:
        endpoint: http://infrastructure-tracing-tempo.net:14252/otlp
        sending_queue:
          queue_size: 50000
        tls:
          insecure: true

    service:
      pipelines:
        traces:
          exporters:
          - loadbalancing/internal
          processors:
          - memory_limiter
          - resource/metadata
          receivers:
          - otlp/external
        traces/loadbalancing:
          exporters:
          - otlphttp/tempo
          processors:
          - memory_limiter
          - resource/metadata
          - tail_sampling
          receivers:
          - otlp/internal
image

Connector

Connector可以將兩個pipelines連線起來,使其中一個pipeline作為exporter,另一個作為receiver。connector可以看作一個exporter,從一個pipeline的尾部消費資料,從將資料傳送到另一個pipeline開始處的receiver上。可以使用connector消費、複製或路由資料。

下面表示將traces的資料匯入metrics中:

receivers:
  foo/traces:
  foo/metrics:
exporters:
  bar:
connectors:
  count:
service:
  pipelines:
    traces:
      receivers: [foo/traces]
      exporters: [count]
    metrics:
      receivers: [foo/metrics, count]
      exporters: [bar]

roundrobin connector

用於使用輪詢方式實現負載均衡,適用於可擴充套件性不是很好的exporter,如prometheusremotewrite,下面用於將接收到的資料(metrics)以輪詢方式分發到不同的prometheusremotewrite(metrics/1metrics/2):

receivers:
  otlp:
processors:
  resourcedetection:
  batch:
exporters:
  prometheusremotewrite/1:
  prometheusremotewrite/2:
connectors:
  roundrobin:
service:
  pipelines:
    metrics:
      receivers: [otlp]
      processors: [resourcedetection, batch]
      exporters: [roundrobin]
    metrics/1:
      receivers: [roundrobin]
      exporters: [prometheusremotewrite/1]
    metrics/2:
      receivers: [roundrobin]
      exporters: [prometheusremotewrite/2]

span metrics connector

用於從span資料中聚合Request、Error和Duration(R.E.D) metrics。

  • Request:

    calls{service.name="shipping",span.name="get_shipping/{shippingId}",span.kind="SERVER",status.code="Ok"}
    
  • Error:

    calls{service.name="shipping",span.name="get_shipping/{shippingId},span.kind="SERVER",status.code="Error"}
    
  • Duration:

    duration{service.name="shipping",span.name="get_shipping/{shippingId}",span.kind="SERVER",status.code="Ok"}
    

每條metric至少包含如下dimension(所有span都存在這些dimensions):

  • service.name
  • span.name
  • span.kind
  • status.code

常見引數如下:

  • histogram:預設explicit,用於配置histogram,只能選擇explicitexponential
    • disable:預設false,禁用所有histogram metrics
    • unit:預設ms,可以選擇mss
    • explicit:指定histogram的time bucket Duration。預設[2ms, 4ms, 6ms, 8ms, 10ms, 50ms, 100ms, 200ms, 400ms, 800ms, 1s, 1400ms, 2s, 5s, 10s, 15s]
    • exponential:正負數範圍內的最大bucket數
  • dimensions:除預設的dimensions之外還需新增的dimensions。每個dimension必須定一個name欄位來從span的attributes集合或resource attribute中進行查詢,如iphost.nameregion。如果沒有在span中找到name屬性,則查詢default中定義的屬性,如果沒有定義default,則忽略此dimension
  • exclude_dimensions:從default dimensions中排除的dimensions列表。用於從metrics排除掉不需要的資料。
  • dimensions_cache_size:儲存Dimensions的快取大小,預設1000
  • metrics_flush_interval:flush 生成的metrics的間隔,預設60s。
  • metrics_expiration:如果在該時間內沒有接收到任何新的spans,則不會再export metrics。預設0,表示不會超時。
  • metric_timestamp_cache_size:,預設1000
  • events:配置events metrics。
    • enable:預設false
    • dimensions:如果enable,則該欄位必須存在。event metric的額外的Dimension
  • resource_metrics_key_attributes:過濾用於生成resource metrics key雜湊值的resource attributes,可以防止resource attributes變動影響到Counter metrics。
receivers:
  nop:

exporters:
  nop:

connectors:
  spanmetrics:
    histogram:
      explicit:
        buckets: [100us, 1ms, 2ms, 6ms, 10ms, 100ms, 250ms]
    dimensions:
      - name: http.method
        default: GET
      - name: http.status_code
    exemplars:
      enabled: true
    exclude_dimensions: ['status.code']
    dimensions_cache_size: 1000
    aggregation_temporality: "AGGREGATION_TEMPORALITY_CUMULATIVE"    
    metrics_flush_interval: 15s
    metrics_expiration: 5m
    events:
      enabled: true
      dimensions:
        - name: exception.type
        - name: exception.message
    resource_metrics_key_attributes:
      - service.name
      - telemetry.sdk.language
      - telemetry.sdk.name

service:
  pipelines:
    traces:
      receivers: [nop]
      exporters: [spanmetrics]
    metrics:
      receivers: [spanmetrics]
      exporters: [nop]

troubleshooting

  • 使用 debug exporter
  • 使用 pprof extension,暴露埠為1777,採集pprof資料
  • 使用 zPages extension, 暴露埠為55679,地址為/debug/tracez可以定位如下問題:
    • 延遲問題
    • 死鎖和工具問題
    • 錯誤

擴容

何時擴容

  • 當使用memory_limiter processor時,可以透過otelcol_processor_refused_spans來檢查記憶體是否充足
  • Collector會使用queue來儲存需要傳送的資料,如果otelcol_exporter_queue_size > otelcol_exporter_queue_capacity則會拒絕資料(otelcol_exporter_enqueue_failed_spans)
  • 此外特定元件也會暴露相關metrics,如otelcol_loadbalancer_backend_latency

如何擴容

對於擴容,可以將元件分為三類:stateless、scrapers 和 stateful。對於stateless來說只需要增加副本數即可。

scrapers

對於hostmetricsreceiverprometheusreceiver這樣的receivers,不能簡單地增加例項數,否則會導致每個Collector都scrape系統的endpoints。可以透過Target Allocator來對endpoints進行分片。

stateful

對於某些將資料存放在記憶體中的元件來說,擴容可能會導致不同的結果。如tail-sampling processor,它會在記憶體中儲存一定時間的spans資料,並在認為trace結束時評估取樣決策。如果透過增加副本數來對此類Collector進行擴容,就會導致不同的Collectors接收到相同trace的spans,導致每個Collector都會評估是否應該對該trace進行取樣,從而可能得到不同的結果(trace丟失spans)。

類似的還有span-to-metrics processor,當不同的Collectors接收到相同服務的資料時,基於service name聚合就會變得不精確。

為了避免該問題,可以在執行tail-sampling 或 span-to-metrics 前面加上 load-balancing exporter, load-balancing exporter會根據trace ID 或service name獲取雜湊值,保證後端的Collector接收到一致的資料。

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317

processors:

exporters:
  loadbalancing:
    protocol:
      otlp:
    resolver:
      dns:
        hostname: otelcol.observability.svc.cluster.local

service:
  pipelines:
    traces:
      receivers:
        - otlp
      processors: []
      exporters:
        - loadbalancing

相關文章