OTel

OpenTelemetry (OTel) — это проект с открытым исходным кодом, направленный на предоставление независимого от поставщика стандарта для сбора, обработки и экспорта телеметрических данных в распределённых системах, таких как архитектуры микросервисов. Он помогает разработчикам проще анализировать производительность и поведение программного обеспечения, что облегчает диагностику и устранение проблем в приложениях.

Содержание

Терминология

ТерминОбъяснение
TraceДанные, отправляемые на OTel Server, представляющие собой набор связанных событий или операций, используемых для отслеживания потока запросов в распределённых системах; каждый Trace состоит из нескольких Spans.
SpanНезависимая операция или событие внутри Trace, включающая время начала, продолжительность и другую релевантную информацию.
OTel ServerСервер OTel, способный принимать и хранить данные Trace, например Jaeger, Prometheus и др.
JaegerСистема распределённого трассирования с открытым исходным кодом, используемая для мониторинга и отладки архитектур микросервисов, поддерживающая интеграцию с OpenTelemetry.
AttributesПары ключ-значение, прикреплённые к Trace или Span для предоставления дополнительной контекстной информации. Включают Resource Attributes и Span Attributes; см. Attributes для подробностей.
SamplerКомпонент стратегии, определяющий, следует ли сэмплировать и отправлять Trace. Можно настроить различные стратегии сэмплирования, например полное сэмплирование, пропорциональное и др.
ALB (Another Load Balancer)Программное или аппаратное устройство, распределяющее сетевые запросы между доступными узлами в кластере; балансировщик нагрузки (ALB), используемый на платформе, является программным балансировщиком уровня 7, который можно настроить для мониторинга трафика с помощью OTel. ALB поддерживает отправку Trace на указанный Collector и позволяет использовать различные стратегии сэмплирования; также поддерживает настройку отправки Trace на уровне Ingress.
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 см. в разделе Creating Load Balancer.

  • Убедитесь, что имеется адрес сервера отчётов данных OTel: Этот адрес далее будет называться <jaeger-server>.

Процедура

Обновление конфигурации ALB

  1. На Master-узле кластера с помощью CLI выполните команду для редактирования конфигурации ALB.

    kubectl edit alb2 -n cpaas-system <otel-alb> # Замените <otel-alb> на фактическое имя ALB
  2. Добавьте следующие поля в раздел spec.config.

    otel:
      enable: true
      exporter:
        collector:
          address: "<jaeger-server>" # Замените <jaeger-server> на фактический адрес сервера отчётов OTel
          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

Связанные операции

Настройка OTel в Ingress

  • Включение или отключение OTel на Ingress

    Настройка включения или отключения OTel на Ingress позволяет лучше контролировать и отлаживать поток запросов приложений, выявляя узкие места производительности или ошибки, отслеживая запросы при их прохождении между различными сервисами.

    Процедура

    Добавьте следующую конфигурацию в поле metadata.annotations Ingress:

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

    Объяснение параметра:

    • nginx.ingress.kubernetes.io/enable-opentelemetry: При значении true контроллер Ingress включает функциональность OpenTelemetry при обработке запросов через этот Ingress, то есть информация о Trace запросов будет собираться и отправляться. При значении false или отсутствии этой аннотации сбор и отправка Trace не выполняются.
  • Включение или отключение доверия OTel на Ingress

    OTel Trust определяет, доверяет ли Ingress и использует ли Trace информацию (например, trace ID) из входящих запросов.

    Процедура

    Добавьте следующую конфигурацию в поле metadata.annotations Ingress:

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

    Объяснение параметра:

    • nginx.ingress.kubernetes.io/opentelemetry-trust-incoming-span: При значении true Ingress продолжает использовать уже существующую Trace информацию, что помогает сохранять согласованность в межсервисном трассировании, позволяя полностью отслеживать и анализировать всю цепочку запросов в системе распределённого трассирования. При значении false для запроса генерируется новая информация трассировки, что может привести к тому, что запрос будет рассматриваться как часть новой цепочки трассировки после прохождения через Ingress, прерывая непрерывность межсервисного трассирования.
  • Добавление различных конфигураций OTel на Ingress

    Эта настройка позволяет кастомизировать поведение OTel и метод экспорта данных для разных ресурсов Ingress, обеспечивая тонкий контроль над стратегией трассирования или целями каждого сервиса.

    Процедура

    Добавьте следующую конфигурацию в поле metadata.annotations Ingress:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      annotations:
        alb.ingress.cpaas.io/otel: >
          {
             "enable": true,
             "exporter": {
                 "collector": {
                     "address": "<jaeger-server>", # Замените <jaeger-server> на фактический адрес сервера отчётов OTel, например "address": "http://128.0.0.1:4318"
                     "request_timeout": 1000
                 }
             }
          }

    Объяснение параметров:

    • exporter: Определяет, как собранные данные Trace отправляются в OTel Collector (сервер отчётов OTel).
    • address: Адрес OTel Collector.
    • request_timeout: Таймаут запроса.

Использование OTel в приложениях

Ниже приведена полная структура конфигурации OTel, которая может использоваться для определения включения и использования функций OTel в приложениях.

На Master-узле кластера с помощью 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.addressАдрес сервера отчётов OTel, поддерживает протоколы http/https и доменные имена.
flags.hide_upstream_attrsОтчёт об информации о правилах upstream.
flag.notrust_incoming_spanДоверие и использование Trace информации OTel (например, trace ID) из входящих запросов.
flags.report_http_request_headerОтчёт заголовков HTTP-запроса.
flags.report_http_response_headerОтчёт заголовков HTTP-ответа.
sampler.nameНазвание стратегии сэмплирования; подробности см. в разделе Sampling Strategies.
sampler.options.fractionДоля сэмплирования.
sampler.options.parent_nameРодительская стратегия для стратегий parent_base.

Наследование

По умолчанию, если в ALB настроены определённые параметры OTel, а FT не настроен, FT наследует параметры от ALB как собственные; то есть FT наследует конфигурацию ALB, а Rule может наследовать конфигурации как от ALB, так и от FT.

  • ALB: Конфигурация на уровне ALB обычно глобальная и по умолчанию. Здесь можно настроить глобальные параметры, например адреса Collector, которые будут унаследованы нижележащими FT и Rule.

  • FT: FT может наследовать конфигурации от ALB, то есть параметры OTel, не настроенные на FT, будут использоваться из ALB. При этом FT можно детализировать, например, выборочно включать или отключать OTel на FT без влияния на другие FT или глобальные настройки ALB.

  • Rule: Rule может наследовать конфигурации как от ALB, так и от FT. При этом Rule также можно детализировать, например, конкретное правило может не доверять входящей Trace информации OTel или изменять стратегии сэмплирования.

Процедура

Настройте поле spec.config.otel в YAML-файлах ALB, FT и Rule для добавления конфигураций, связанных с OTel.

Дополнительные сведения

Стратегии сэмплирования

ПараметрОбъяснение
always onВсегда отправлять все данные трассировки.
always offНикогда не отправлять данные трассировки.
traceid-ratioРешение об отправке принимается на основе traceid. Формат traceparentxx-traceid-xx-flag, где первые 16 символов traceid представляют 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'.

Атрибуты

  • Resource Attributes

    Эти атрибуты отправляются по умолчанию.

    ПараметрОписание
    hostnameИмя хоста Pod ALB
    service.nameИмя ALB
    service.namespaceПространство имён, где расположен ALB
    service.typeПо умолчанию ALB
    service.instance.idИмя Pod ALB
  • Span Attributes

    • Атрибуты, отправляемые по умолчанию:

      ПараметрОписание
      http.status_codeКод состояния
      http.request.resend_countКоличество повторных попыток
      alb.rule.rule_nameИмя правила, с которым совпал этот запрос
      alb.rule.source_typeТип правила, с которым совпал запрос, в настоящее время только Ingress
      alb.rule.source_nameИмя Ingress
      alb.rule.source_nsПространство имён, где расположен Ingress
    • Атрибуты, отправляемые по умолчанию, но которые можно исключить, изменяя поле flag.hide_upstream_attrs:

      ПараметрОписание
      alb.upstream.svc_nameИмя Service (внутреннего маршрута), на который перенаправляется трафик
      alb.upstream.svc_nsПространство имён Service (внутреннего маршрута), на который перенаправляется трафик
      alb.upstream.peerIP-адрес и порт Pod, на который перенаправляется трафик
    • Атрибуты, не отправляемые по умолчанию, но которые можно включить, изменяя поле flag.report_http_request_header:

      ПараметрОписание
      **http.request.header.<header>**Заголовок запроса
    • Атрибуты, не отправляемые по умолчанию, но которые можно включить, изменяя поле flag.report_http_response_header:

      ПараметрОписание
      **http.response.header.<header>**Заголовок ответа

Пример конфигурации

Ниже приведена YAML-конфигурация, которая разворачивает ALB и использует Jaeger в качестве сервера OTel, с 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. Выполните команду для отправки запроса к HotROD через ALB. ALB при этом отправит Trace в Jaeger.

    curl -v "http://<$ALB_IP>:80/dispatch?customer=567&nonse=" # Замените <$ALB_IP> в команде на адрес доступа otel-alb, полученный на предыдущем шаге
  6. Откройте адрес доступа Jaeger, полученный в Шаге 3, чтобы просмотреть результаты.