OTel

OpenTelemetry(OTel)是一个开源项目,旨在为分布式系统(例如微服务架构)中的遥测数据收集、处理和导出提供与供应商无关的标准。它可以帮助开发人员更轻松地分析软件的性能和行为,从而促进应用问题的诊断和解决。

术语

术语说明
Trace提交到 OTel Server 的数据,是一组相关事件或操作,用于跟踪分布式系统中的请求流;每个 Trace 由多个 Span 组成。
SpanTrace 中的独立操作或事件,包括开始时间、持续时间和其他相关信息。
OTel Server能够接收和存储 Trace 数据的 OTel 服务器,例如 Jaeger、Prometheus 等。
Jaeger一个开源分布式追踪系统,用于监控和排查微服务架构,支持与 OpenTelemetry 集成。
Attributes附加到 Trace 或 Span 的键值对,用于提供额外的上下文信息。这包括 Resource Attributes 和 Span Attributes;详情请参阅 Attributes。
Sampler用于确定是否对 Trace 进行采样和报告的策略组件。可以配置不同的采样策略,例如全量采样、按比例采样等。
ALB (Another Load Balancer)一种在集群中的可用节点之间分配网络请求的软件或硬件设备;平台使用的负载均衡器(ALB)是一个第 7 层软件负载均衡器,可以配置为使用 OTel 监控流量。ALB 支持将 Trace 提交到指定的 Collector,并允许使用不同的采样策略;同时还支持配置是否在 Ingress 层级提交 Trace。
FT (Frontend)ALB 的端口配置,用于指定端口级别的配置。
Rule端口(FT)上的路由规则,用于匹配特定路由。
HotROD (Rides on Demand)Jaeger 提供的示例应用,用于演示分布式追踪的使用;详情请参阅 Hot R.O.D. - Rides on Demand。
hotrod-with-proxy通过环境变量指定 HotROD 内部微服务的地址;详情请参阅 hotrod-with-proxy。

前提条件

  • 确保存在可正常运行的 ALB:创建或使用现有的 ALB。以下示例使用 <otel-alb> 作为 ALB 名称。有关创建 ALB 的操作步骤,请参阅 配置 ALB。

  • 确保存在 OTel 数据报告服务器地址:下文将该地址称为 <jaeger-server>。

操作步骤

更新 ALB 配置

  1. 在集群的控制平面节点上,使用 CLI 工具执行以下命令编辑 ALB 配置。

    kubectl edit alb2 -n cpaas-system <otel-alb> # Replace <otel-alb> with the actual ALB name
  2. 在 spec.config 部分下添加以下字段。

    otel:
      enable: true
      exporter:
        collector:
          address: '<jaeger-server>' # Replace <jaeger-server> with the actual OTel data reporting server address
          request_timeout: 1000

    完成后的配置示例:

    spec:
      address: 192.168.1.1
      config:
        otel:
         enable: true
         exporter:
           collector:
             address: "http://jaeger.default.svc.cluster.local:4318"
             request_timeout: 1000
        antiAffinityKey: system
        defaultSSLCert: cpaas-system/cpaas-system
        defaultSSLStrategy: Both
        gateway:
        ...
    type: nginx
  3. 执行以下命令保存更新。更新后,ALB 默认启用 OpenTelemetry,并将所有请求的 Trace 信息报告到 Jaeger Server。

    :wq

相关操作

在 Ingress 中配置 OTel

  • 在 Ingress 上启用或禁用 OTel

    通过配置是否在 Ingress 上启用 OTel,您可以更好地监控和调试应用的请求流,并通过跟踪请求在不同服务之间的传播来识别性能瓶颈或错误。

    操作步骤

    在 Ingress 的 metadata.annotations 字段下添加以下配置:

    nginx.ingress.kubernetes.io/enable-opentelemetry: "true"

    参数说明:

    • nginx.ingress.kubernetes.io/enable-opentelemetry:设置为 true 时,表示 Ingress controller 在处理通过该 Ingress 的请求时启用 OpenTelemetry 功能,即收集并报告请求的 Trace 信息。设置为 false 或移除此 annotation 时,表示不收集或报告请求的 Trace 信息。
  • 在 Ingress 上启用或禁用 OTel 信任

    OTel 信任用于确定 Ingress 是否信任并使用传入请求中的 Trace 信息(例如 trace ID)。

    操作步骤

    在 Ingress 的 metadata.annotations 字段下添加以下配置:

    nginx.ingress.kubernetes.io/opentelemetry-trust-incoming-span: "true"

    参数说明:

    • nginx.ingress.kubernetes.io/opentelemetry-trust-incoming-span:设置为 true 时,Ingress 会继续使用已有的 Trace 信息,有助于保持跨服务追踪的一致性,使整个请求链能够在分布式追踪系统中得到完整追踪和分析。设置为 false 时,将为请求生成新的追踪信息,这可能导致请求进入 Ingress 后被视为新追踪链的一部分,从而中断跨服务 Trace 的连续性。
  • 在 Ingress 上添加不同的 OTel 配置

    此配置允许您为不同的 Ingress 资源自定义 OTel 的行为和数据导出方式,从而对每个服务的追踪策略或目标进行精细控制。

    操作步骤

    在 Ingress 的 metadata.annotations 字段下添加以下配置:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      annotations:
        alb.ingress.cpaas.io/otel: >
          {
             "enable": true,
             "exporter": {
                 "collector": {
                     "address": "<jaeger-server>", # Replace <jaeger-server> with the actual OTel data reporting server address, e.g., "address": "http://128.0.0.1:4318"
                     "request_timeout": 1000
                 }
             }
          }

    参数说明:

    • exporter:指定如何将收集的 Trace 数据发送到 OTel Collector(OTel 数据报告服务器)。
    • address:指定 OTel Collector 的地址。
    • request_timeout:指定请求超时时间。

在应用中使用 OTel

以下配置显示了完整的 OTel 配置结构,可用于定义如何在应用中启用和使用 OTel 功能。

在集群的控制平面节点上,使用 CLI 工具执行以下命令,以获取完整的 OTel 配置结构。

kubectl get crd alaudaloadbalancer2.crd.alauda.io -o json|jq ".spec.versions[2].schema.openAPIV3Schema.properties.spec.properties.config.properties.otel"

回显结果:

{
    "otel": {
        "enable": true
    }
    "exporter": {
        "collector": {
            "address": ""
          },
    },
    "flags": {
        "hide_upstream_attrs": false
        "notrust_incoming_span": false
        "report_http_request_header": false
        "report_http_response_header": false
    },
    "sampler": {
        "name": "",
        "options": {
            "fraction": ""
            "parent_name": ""
          },
      },
 }

参数说明:

参数说明
otel.enable是否启用 OTel 功能。
exporter.collector.addressOTel 数据报告服务器的地址,支持 http/https 协议和域名。
flags.hide_upstream_attrs是否报告上游规则的信息。
flag.notrust_incoming_span是否信任并使用传入请求中的 OTel Trace 信息(例如 trace ID)。
flags.report_http_request_header是否报告请求标头。
flags.report_http_response_header是否报告响应标头。
sampler.name采样策略名称;有关详细信息,请参阅 采样策略。
sampler.options.fraction采样率。
sampler.options.parent_nameparent_base 采样策略的父策略。

继承

默认情况下,如果 ALB 配置了某些 OTel 参数,而 FT 未进行配置,则 FT 将从 ALB 继承这些参数作为自身配置;也就是说,FT 继承 ALB 配置,而 Rule 可以同时从 ALB 和 FT 继承配置。

  • ALB:ALB 上的配置通常是全局配置和默认配置。您可以在此配置 Collector 地址等全局参数,这些参数将由下层的 FT 和 Rule 继承。

  • FT:FT 可以从 ALB 继承配置,即 FT 上未配置的某些 OTel 参数将使用 ALB 中的配置。但是,您也可以进一步细化 FT 的配置;例如,可以选择在 FT 上启用或禁用 OTel,而不影响其他 FT 或 ALB 的全局设置。

  • Rule:Rule 可以同时从 ALB 和 FT 继承配置。但是,您也可以进一步细化 Rule 的配置;例如,特定 Rule 可以选择不信任传入的 OTel Trace 信息,或调整采样策略。

操作步骤

通过在 ALB、FT 和 Rule 的 YAML 文件中配置 spec.config.otel 字段,可以添加 OTel 相关配置。

附加说明

采样策略

参数说明
always on始终报告所有追踪数据。
always off从不报告追踪数据。
traceid-ratio根据 traceid 决定是否报告。traceparent 的格式为 xx-traceid-xx-flag,其中 traceid 的前 16 个字符表示一个 32 位十六进制整数。如果该整数小于 fraction 乘以 4294967295(即 (2^32-1)),则会报告。
parent-base根据请求中 traceparent 的标志部分决定是否报告。当标志为 01 时,将会报告;例如:curl -v "http://$ALB_IP/" -H 'traceparent: 00-xx-xx-01';当标志为 02 时,不会报告;例如:curl -v "http://$ALB_IP/" -H 'traceparent: 00-xx-xx-02'。

属性

  • 资源属性

    默认报告这些属性。

    参数描述
    hostnameALB Pod 的主机名
    service.nameALB 的名称
    service.namespaceALB 所在的命名空间
    service.type默认为 ALB
    service.instance.idALB Pod 的名称
  • Span 属性

    • 默认报告的属性:

      参数描述
      http.status_code状态码
      http.request.resend_count重试次数
      alb.rule.rule_name此请求匹配的 Rule 名称
      alb.rule.source_type此请求匹配的 Rule 类型,目前仅支持 Ingress
      alb.rule.source_nameIngress 的名称
      alb.rule.source_nsIngress 所在的命名空间
    • 默认报告的属性,但可以通过修改 flag.hide_upstream_attrs 字段将其排除:

      参数描述
      alb.upstream.svc_name流量转发到的 Service(内部路由)的名称
      alb.upstream.svc_ns被转发到的 Service(内部路由)所在的命名空间
      alb.upstream.peer被转发到的 Pod 的 IP 地址和端口
    • 默认不报告的属性,但可以通过修改 flag.report_http_request_header 字段进行报告:

      参数描述
      **http.request.header.<header>**请求标头
    • 默认不报告的属性,但可以通过修改 flag.report_http_response_header 字段进行报告:

      参数描述
      **http.response.header.<header>**响应标头

配置示例

以下 YAML 配置会部署一个 ALB,并使用 Jaeger 作为 OTel server,以 Hotrod-proxy 作为演示后端。通过配置 Ingress 规则,当客户端请求 ALB 时,流量将转发到 HotROD。此外,HotROD 内部微服务之间的通信也会通过 ALB 进行路由。

  1. 将以下 YAML 保存为名为 all.yaml 的文件。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hotrod
    spec:
      replicas: 1
      selector:
        matchLabels:
          service.cpaas.io/name: hotrod
          service_name: hotrod
      template:
        metadata:
          labels:
            service.cpaas.io/name: hotrod
            service_name: hotrod
        spec:
          containers:
            - name: hotrod
              env:
                - name: PROXY_PORT
                  value: '80'
                - name: PROXY_ADDR
                  value: 'otel-alb.default.svc.cluster.local:'
                - name: OTEL_EXPORTER_OTLP_ENDPOINT
                  value: 'http://jaeger.default.svc.cluster.local:4318'
              image: theseedoaa/hotrod-with-proxy:latest
              imagePullPolicy: IfNotPresent
              command: ['/bin/hotrod', 'all', '-v']
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: hotrod-frontend
    spec:
      ingressClassName: otel-alb
      rules:
        - http:
            paths:
              - backend:
                  service:
                    name: hotrod
                    port:
                      number: 8080
                path: /dispatch
                pathType: ImplementationSpecific
              - backend:
                  service:
                    name: hotrod
                    port:
                      number: 8080
                path: /frontend
                pathType: ImplementationSpecific
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: hotrod-customer
    spec:
      ingressClassName: otel-alb
      rules:
        - http:
            paths:
              - backend:
                  service:
                    name: hotrod
                    port:
                      number: 8081
                path: /customer
                pathType: ImplementationSpecific
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: hotrod-route
    spec:
      ingressClassName: otel-alb
      rules:
        - http:
            paths:
              - backend:
                  service:
                    name: hotrod
                    port:
                      number: 8083
                path: /route
                pathType: ImplementationSpecific
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: hotrod
    spec:
      internalTrafficPolicy: Cluster
      ipFamilies:
        - IPv4
      ipFamilyPolicy: SingleStack
      ports:
        - name: frontend
          port: 8080
          protocol: TCP
          targetPort: 8080
        - name: customer
          port: 8081
          protocol: TCP
          targetPort: 8081
        - name: router
          port: 8083
          protocol: TCP
          targetPort: 8083
      selector:
        service_name: hotrod
      sessionAffinity: None
      type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: jaeger
    spec:
      replicas: 1
      selector:
        matchLabels:
          service.cpaas.io/name: jaeger
          service_name: jaeger
      template:
        metadata:
          labels:
            service.cpaas.io/name: jaeger
            service_name: jaeger
        spec:
          containers:
            - name: jaeger
              env:
                - name: LOG_LEVEL
                  value: debug
              image: jaegertracing/all-in-one:1.58.1
              imagePullPolicy: IfNotPresent
          hostNetwork: true
          tolerations:
            - operator: Exists
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: jaeger
    spec:
      internalTrafficPolicy: Cluster
      ipFamilies:
        - IPv4
      ipFamilyPolicy: SingleStack
      ports:
        - name: http
          port: 4318
          protocol: TCP
          targetPort: 4318
      selector:
        service_name: jaeger
      sessionAffinity: None
      type: ClusterIP
    ---
    apiVersion: crd.alauda.io/v2
    kind: ALB2
    metadata:
      name: otel-alb
    spec:
      config:
        loadbalancerName: otel-alb
        otel:
          enable: true
          exporter:
            collector:
              address: 'http://jaeger.default.svc.cluster.local:4318'
              request_timeout: 1000
        projects:
          - ALL_ALL
        replicas: 1
        resources:
          alb:
            limits:
              cpu: 200m
              memory: 2Gi
            requests:
              cpu: 50m
              memory: 128Mi
          limits:
            cpu: '1'
            memory: 1Gi
          requests:
            cpu: 50m
            memory: 128Mi
      type: nginx
  2. 在 CLI 工具中执行以下命令,部署 Jaeger、ALB、HotROD 以及测试所需的所有 CR。

    kubectl apply ./all.yaml
  3. 执行以下命令获取 Jaeger 的访问地址。

    export JAEGER_IP=$(kubectl get po -A -o wide |grep jaeger | awk '{print $7}');echo "http://$JAEGER_IP:16686"
  4. 执行以下命令获取 otel-alb 的访问地址。

    export ALB_IP=$(kubectl get po -A -o wide|grep otel-alb | awk '{print $7}');echo $ALB_IP
  5. 执行以下命令通过 ALB 向 HotROD 发送请求。此时,ALB 将 Trace 报告到 Jaeger。

    curl -v "http://<$ALB_IP>:80/dispatch?customer=567&nonse=" # Replace <$ALB_IP> in the command with the access address of otel-alb obtained in the previous procedure
  6. 打开在步骤 3中获取的 Jaeger 访问地址,查看结果。

商标声明

NGINX® 是 F5, Inc. 在美国及其他国家/地区的注册商标。

Alauda 是独立供应商。本产品与 F5, Inc. 不存在关联,也未获得其认可或赞助。所有商标均归其各自所有者所有,此处仅用于标识目的。