• Русский
  • Установка Alauda Distributed Tracing с Elasticsearch

    Установка платформы Alauda Distributed Tracing включает следующие шаги:

    1. Установка Alauda Build of OpenTelemetry v2 Operator
    2. Развертывание Alauda Build of Jaeger v2
    3. Развертывание OpenTelemetry Collector для пересылки трассировок в Jaeger

    Установка Alauda Build of OpenTelemetry v2 Operator

    Alauda Build of OpenTelemetry v2 Operator управляет жизненным циклом экземпляров Jaeger v2 и OpenTelemetry Collector. Перед развертыванием любых компонентов трассировки необходимо установить этот Operator.

    Установка через веб-консоль

    Следуйте инструкциям в разделе Installing via the web console документации Alauda Build of OpenTelemetry v2.

    Установка через CLI

    Следуйте инструкциям в разделе Installing via the CLI документации Alauda Build of OpenTelemetry v2.

    Развертывание Alauda Build of Jaeger v2

    Jaeger v2 развертывается как пользовательский ресурс OpenTelemetryCollector, управляемый Alauda Build of OpenTelemetry v2 Operator. Он использует backend storage и интегрируется с системой аутентификации Alauda Container Platform через sidecar OAuth2 Proxy.

    Предварительные требования

    • Установлен Alauda Build of OpenTelemetry v2 Operator.
    • Доступен экземпляр Elasticsearch 8.x, и у вас есть URL его endpoint, имя пользователя и пароль.
    • Активная сессия ACP CLI (kubectl) от администратора кластера с ролью cluster-admin.
    • Установлена командная строка jq.

    Процедура

    1. Задайте переменные среды, настраиваемые пользователем, для подключения к Elasticsearch:

      export ES_ENDPOINT='<Elasticsearch endpoint URL>'
      export ES_USER='<Elasticsearch username>'
      export ES_PASS='<Elasticsearch password>'

      Замените значения-заполнители на фактические учетные данные Elasticsearch.

    2. Получите конфигурацию платформы и образы контейнеров, связанные с Jaeger, из кластера:

      export PLATFORM_URL=$(kubectl -nkube-public get configmap global-info -o jsonpath='{.data.platformURL}')
      export CLUSTER_NAME=$(kubectl -nkube-public get configmap global-info -o jsonpath='{.data.clusterName}')
      export ALB_CLASS_NAME=$(kubectl -nkube-public get configmap global-info -o jsonpath='{.data.systemAlbIngressClassName}')
      
      export OIDC_ISSUER=$(kubectl -nkube-public get configmap global-info -o jsonpath='{.data.oidcIssuer}')
      OIDC_CLIENT_SECRET_REF=$(kubectl -nkube-public get configmap global-info -o jsonpath='{.data.oidcClientSecretRef}')
      if [ -n "$OIDC_CLIENT_SECRET_REF" ]; then
        SYSTEM_NAMESPACE=$(kubectl -nkube-public get configmap global-info -o jsonpath='{.data.systemNamespace}')
        export OIDC_CLIENT_ID=$(kubectl -n"$SYSTEM_NAMESPACE" get secret "$OIDC_CLIENT_SECRET_REF" -o go-template='{{index .data "client-id"}}' | base64 -d)
        export OIDC_CLIENT_SECRET=$(kubectl -n"$SYSTEM_NAMESPACE" get secret "$OIDC_CLIENT_SECRET_REF" -o go-template='{{index .data "client-secret"}}' | base64 -d)
      else
        export OIDC_CLIENT_ID=$(kubectl -nkube-public get configmap global-info -o jsonpath='{.data.oidcClientID}')
        export OIDC_CLIENT_SECRET=$(kubectl -nkube-public get configmap global-info -o jsonpath='{.data.oidcClientSecret}')
      fi
      
      JAEGER_RELATED_IMAGES=$(kubectl get csv -n opentelemetry-operator2 \
        -l 'operators.coreos.com/opentelemetry-operator2.opentelemetry-operator2=' \
        -o jsonpath='{.items[0].spec.relatedImages}')
      export JAEGER_IMAGE=$(echo "$JAEGER_RELATED_IMAGES" | jq -r '.[] | select(.name=="component.jaeger") | .image')
      export JAEGER_ES_ROLLOVER_IMAGE=$(echo "$JAEGER_RELATED_IMAGES" | jq -r '.[] | select(.name=="component.jaeger-es-rollover") | .image')
      export JOAUTH2_PROXY_IMAGE=$(echo "$JAEGER_RELATED_IMAGES" | jq -r '.[] | select(.name=="component.oauth2-proxy") | .image')
      NOTE

      Убедитесь, что команды завершаются без ошибок.

    3. Задайте переменные среды по умолчанию. При необходимости вы можете изменить эти значения в соответствии с требованиями развертывания:

      # Namespace for the Jaeger instance
      export JAEGER_NS="jaeger-system"
      # Name of the Jaeger instance
      export JAEGER_INSTANCE_NAME="jaeger"
      # Elasticsearch index prefix for Jaeger data
      export JAEGER_ES_INDEX_PREFIX="acp-${CLUSTER_NAME}"
      # Base path for the Jaeger UI
      export JAEGER_BASEPATH="/clusters/${CLUSTER_NAME}/jaeger"
    4. Создайте namespace Jaeger и Secret с учетными данными Elasticsearch:

      kubectl get namespace ${JAEGER_NS} &> /dev/null || kubectl create namespace ${JAEGER_NS}
      
      kubectl create secret generic es-credentials \
        --namespace=${JAEGER_NS} \
        --from-literal=ES_USER=${ES_USER} \
        --from-literal=ES_PASS=${ES_PASS} \
        --dry-run=client -o yaml | kubectl apply -f -

      Проверьте, что Secret был создан:

      kubectl get secret es-credentials -n ${JAEGER_NS}
    5. Создайте ILM (Index Lifecycle Management) Policy в Elasticsearch. Jaeger использует ILM для управления rollover индексов и их хранением:

      curl -k -u "${ES_USER}:${ES_PASS}" -X PUT \
        "${ES_ENDPOINT}/_ilm/policy/jaeger-ilm-policy" \
        -H 'Content-Type: application/json' \
        --data-binary @- << 'EOF'
      {
        "policy": {
          "phases": {
            "hot": {
              "min_age": "0ms",
              "actions": {
                "rollover": {
                  "max_primary_shard_size": "50gb",
                  "max_age": "1d"
                },
                "set_priority": {
                  "priority": 100
                }
              }
            },
            "delete": {
              "min_age": "7d",
              "actions": {
                "delete": {}
              }
            }
          }
        }
      }
      EOF

      Ключевые поля:

      • policy.phases.hot.actions.rollover.max_primary_shard_size: Максимальный размер одного primary shard. Когда shard превышает этот размер, выполняется rollover и создается новый индекс. Значение по умолчанию: 50gb.
      • policy.phases.hot.actions.rollover.max_age: Максимальный возраст индекса перед выполнением rollover. Значение по умолчанию: 1d (1 день).
      • policy.phases.delete.min_age: Время ожидания после rollover перед удалением старого индекса. Значение по умолчанию: 7d (7 дней).

      Проверьте ILM Policy:

      curl -k -u "${ES_USER}:${ES_PASS}" "${ES_ENDPOINT}/_ilm/policy/jaeger-ilm-policy?pretty"

      В выводе должны отображаться сведения об ILM Policy, включая фазы hot и delete.

    6. Инициализируйте псевдонимы индексов и шаблоны с помощью инструмента jaeger-es-rollover. Это подготавливает Elasticsearch к хранению данных Jaeger:

      kubectl apply -n ${JAEGER_NS} -f - <<EOF
      apiVersion: batch/v1
      kind: Job
      metadata:
        name: jaeger-es-rollover-init
      spec:
        template:
          spec:
            containers:
            - name: es-rollover-init
              image: "${JAEGER_ES_ROLLOVER_IMAGE}"
              args:
                - init
                - "${ES_ENDPOINT}"
              env:
              - name: INDEX_PREFIX
                value: "${JAEGER_ES_INDEX_PREFIX}"
              - name: ES_USE_ILM
                value: "true"
              - name: ES_TLS_ENABLED
                value: "true"
              - name: ES_TLS_SKIP_HOST_VERIFY
                value: "true"
              - name: ES_USERNAME
                valueFrom:
                  secretKeyRef:
                    name: es-credentials
                    key: ES_USER
              - name: ES_PASSWORD
                valueFrom:
                  secretKeyRef:
                    name: es-credentials
                    key: ES_PASS
            restartPolicy: Never
        backoffLimit: 3
      EOF

      Дождитесь завершения Job, затем убедитесь, что шаблоны индексов и псевдонимы были созданы:

      kubectl wait --for=condition=complete job/jaeger-es-rollover-init \
        -n ${JAEGER_NS} --timeout=120s
      
      # Verify index templates
      curl -k -sS -u "${ES_USER}:${ES_PASS}" "${ES_ENDPOINT}/_index_template?pretty" \
        | grep ${JAEGER_ES_INDEX_PREFIX}-jaeger-
      
      # Verify index aliases
      curl -k -sS -u "${ES_USER}:${ES_PASS}" "${ES_ENDPOINT}/_alias?pretty" \
        | grep ${JAEGER_ES_INDEX_PREFIX}-jaeger-

      Ожидаемые результаты:

      • Статус Job равен Complete.
      • В Elasticsearch существуют шаблоны индексов, соответствующие ${JAEGER_ES_INDEX_PREFIX}-jaeger-*.
      • В Elasticsearch существуют псевдонимы индексов для ${JAEGER_ES_INDEX_PREFIX}-jaeger-*-read и ${JAEGER_ES_INDEX_PREFIX}-jaeger-*-write.
    7. Очистите initialization Job после его завершения:

      kubectl delete job jaeger-es-rollover-init -n ${JAEGER_NS}
    8. Создайте Secret для OAuth2 Proxy, который используется для интеграции Jaeger UI с системой аутентификации Alauda Container Platform:

      # Generate a cookie secret for the OAuth2 Proxy:
      OAUTH2_PROXY_COOKIE_SECRET=$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64 | tr -d -- '\n' | tr -- '+/' '-_')
      # Create the Secret:
      kubectl create secret generic ${JAEGER_INSTANCE_NAME}-oauth2-proxy \
        --namespace=${JAEGER_NS} \
        --from-literal=OAUTH2_PROXY_CLIENT_SECRET=${OIDC_CLIENT_SECRET} \
        --from-literal=OAUTH2_PROXY_COOKIE_SECRET=${OAUTH2_PROXY_COOKIE_SECRET} \
        --dry-run=client -o yaml | kubectl apply -f -
    9. Создайте файл с именем jaeger.yaml со следующим содержимым:

      jaeger.yaml
      apiVersion: opentelemetry.io/v1beta1
      kind: OpenTelemetryCollector
      metadata:
        labels:
          prometheus: kube-prometheus
        name: ${JAEGER_INSTANCE_NAME}
        namespace: ${JAEGER_NS}
      spec:
        image: "${JAEGER_IMAGE}"
        mode: deployment
        replicas: 1
      
        resources:
          requests:
            cpu: 100m
            memory: 256Mi
          limits:
            cpu: "2"
            memory: 2Gi
      
        ports:
          - name: oauth2-proxy
            port: 4180
          - name: jaeger-grpc
            port: 16685
      
        observability:
          metrics:
            enableMetrics: true
      
        volumes:
          - name: es-credentials
            secret:
              secretName: es-credentials
              items:
                - key: ES_PASS
                  path: pass
          - name: oauth2-proxy-secrets
            secret:
              secretName: ${JAEGER_INSTANCE_NAME}-oauth2-proxy
              items:
                - key: OAUTH2_PROXY_CLIENT_SECRET
                  path: client-secret
                - key: OAUTH2_PROXY_COOKIE_SECRET
                  path: cookie-secret
        volumeMounts:
          - name: es-credentials
            mountPath: /etc/jaeger/es-credentials
            readOnly: true
      
        config:
          receivers:
            otlp:
              protocols:
                grpc:
                  endpoint: "0.0.0.0:4317"
                http:
                  endpoint: "0.0.0.0:4318"
      
          processors:
            batch: {}
            memory_limiter:
              check_interval: 1s
              limit_percentage: 80
              spike_limit_percentage: 20
      
          exporters:
            debug: {}
            jaeger_storage_exporter:
              trace_storage: es_storage
      
          extensions:
            healthcheckv2:
              use_v2: true
              http:
                endpoint: "0.0.0.0:13133"
      
            jaeger_storage:
              backends:
                es_storage:
                  elasticsearch:
                    server_urls:
                      - "${ES_ENDPOINT}"
                    auth:
                      basic:
                        username: "${ES_USER}"
                        password_file: /etc/jaeger/es-credentials/pass
                    tls:
                      insecure_skip_verify: true
                    use_aliases: true
                    use_ilm: true
                    service_cache_ttl: 12h
                    create_mappings: false
                    indices:
                      index_prefix: "${JAEGER_ES_INDEX_PREFIX}"
                      spans:
                        shards: 5
                        replicas: 1
                      services:
                        shards: 5
                        replicas: 1
                      dependencies:
                        shards: 5
                        replicas: 1
                      sampling:
                        shards: 5
                        replicas: 1
      
            jaeger_query:
              storage:
                traces: es_storage
              ui:
                config_file: ""
              base_path: "${JAEGER_BASEPATH}"
              http:
                endpoint: 0.0.0.0:16686
      
          service:
            extensions: [healthcheckv2, jaeger_storage, jaeger_query]
            pipelines:
              traces:
                receivers: [otlp]
                processors: [memory_limiter, batch]
                exporters: [debug, jaeger_storage_exporter]
            telemetry:
              resource:
                service.name: jaeger
              metrics:
                level: detailed
                readers:
                  - pull:
                      exporter:
                        prometheus:
                          host: "0.0.0.0"
                          port: 8888
                          without_scope_info: true
                          without_type_suffix: true
                          without_units: true
              logs:
                level: info
      
        additionalContainers:
          - name: oauth2-proxy
            image: ${JOAUTH2_PROXY_IMAGE}
            args:
              - --http-address=0.0.0.0:4180
              - --upstream=http://127.0.0.1:16686
              - --proxy-prefix=${JAEGER_BASEPATH}/oauth2
              - --redirect-url=${PLATFORM_URL}${JAEGER_BASEPATH}/oauth2/callback
              - --provider=oidc
              - --oidc-issuer-url=${OIDC_ISSUER}
              - --scope=openid profile email groups ext
              - --email-domain=*
              - --code-challenge-method=S256
              - --insecure-oidc-allow-unverified-email=true
              - --cookie-secure=false
              - --skip-provider-button=true
              - --ssl-insecure-skip-verify=true
              - --skip-jwt-bearer-tokens=true
              - --client-id=${OIDC_CLIENT_ID}
              - --client-secret-file=/etc/oauth2-proxy/client-secret
              - --cookie-secret-file=/etc/oauth2-proxy/cookie-secret
            resources:
              requests:
                cpu: 50m
                memory: 64Mi
              limits:
                cpu: 500m
                memory: 256Mi
            volumeMounts:
              - name: oauth2-proxy-secrets
                mountPath: /etc/oauth2-proxy
                readOnly: true
            ports:
              - containerPort: 4180
                name: oauth2-proxy
                protocol: TCP
      1. Метка prometheus: kube-prometheus наследуется автоматически создаваемым ресурсом ServiceMonitor, что позволяет ACP Prometheus собирать метрики Jaeger.
      2. Образ контейнера Jaeger v2. Это не стандартный образ OpenTelemetry Collector; это пользовательский бинарный файл Jaeger, собранный на основе фреймворка OpenTelemetry Collector.
      3. Включает endpoint метрик Prometheus для экземпляра Jaeger.
      4. Запросы и лимиты ресурсов для контейнера Jaeger. Настройте их в зависимости от ожидаемого объема трассировок; для сред с более высокой пропускной способностью может потребоваться больше CPU и памяти.
      5. Расширение jaeger_storage настраивает Elasticsearch backend для хранения данных трассировки.
      6. service_cache_ttl определяет, как долго хранится кэш имен сервисов. Значение по умолчанию — 12h. Если интервал ILM от hot до delete короткий, уменьшите это значение, чтобы обеспечить своевременное обнаружение сервисов в Jaeger UI.
      7. При использовании режима ILM параметр create_mappings должен быть установлен в false, поскольку сопоставления индексов управляются инициализацией rollover.
      8. index_prefix должен совпадать с префиксом, использованным при инициализации jaeger-es-rollover на шаге 6. Дополнительные сведения о настройке shards и replicas см. в разделе Shards and Replicas.
      9. Расширение jaeger_query обслуживает Jaeger Query API и Jaeger UI.
      10. Раздел additionalContainers определяет sidecar OAuth2 Proxy, который выполняет аутентификацию для Jaeger UI, интегрируясь с поставщиком удостоверений Alauda Container Platform Dex.
      11. Запросы и лимиты ресурсов для sidecar OAuth2 Proxy. У этого контейнера низкие требования к ресурсам, поскольку он только проксирует запросы аутентификации.
    10. Сгенерируйте манифест с помощью envsubst и примените конфигурацию:

      envsubst < jaeger.yaml | kubectl apply -f -
    11. Дождитесь готовности Pod Jaeger:

      kubectl rollout status deployment/${JAEGER_INSTANCE_NAME}-collector \
        -n ${JAEGER_NS} --timeout=180s
    12. Присвойте namespace метку и создайте Ingress для публикации Jaeger UI:

      kubectl label namespace ${JAEGER_NS} cpaas.io/project=cpaas-system --overwrite
      kubectl apply -n ${JAEGER_NS} -f - <<EOF
      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        name: ${JAEGER_INSTANCE_NAME}
        annotations:
          nginx.ingress.kubernetes.io/enable-cors: "true"
      spec:
        ingressClassName: ${ALB_CLASS_NAME}
        rules:
          - http:
              paths:
                - path: ${JAEGER_BASEPATH}
                  pathType: ImplementationSpecific
                  backend:
                    service:
                      name: ${JAEGER_INSTANCE_NAME}-collector
                      port:
                        number: 4180
      EOF

      Дождитесь готовности Ingress:

      kubectl wait --for=jsonpath='{.status.loadBalancer.ingress}' ingress/${JAEGER_INSTANCE_NAME} \
        -n ${JAEGER_NS} --timeout=180s

    Проверка

    Откройте Jaeger UI по адресу <platform-url>/clusters/<cluster-name>/jaeger, где <platform-url> — это URL Alauda Container Platform, а <cluster-name> — имя вашего кластера.

    Выполните следующую команду, чтобы вывести URL Jaeger UI:

    echo "Jaeger UI: ${PLATFORM_URL}${JAEGER_BASEPATH}"

    Развертывание OpenTelemetry Collector

    После запуска Jaeger v2 разверните экземпляр OpenTelemetry Collector, чтобы принимать данные трассировок от инструментированных приложений и пересылать их в Jaeger.

    1. Создайте файл с именем otel-collector.yaml со следующим содержимым:

      otel-collector.yaml
      apiVersion: opentelemetry.io/v1beta1
      kind: OpenTelemetryCollector
      metadata:
        labels:
          prometheus: kube-prometheus
        name: otel
        namespace: ${JAEGER_NS}
      spec:
        mode: deployment
        replicas: 1
        resources:
          requests:
            cpu: 100m
            memory: 256Mi
          limits:
            cpu: "2"
            memory: 2Gi
        observability:
          metrics:
            enableMetrics: true
        config:
          receivers:
            otlp:
              protocols:
                grpc:
                  endpoint: 0.0.0.0:4317
                http:
                  endpoint: 0.0.0.0:4318
            zipkin: {}
          processors:
            batch: {}
            memory_limiter:
              check_interval: 1s
              limit_percentage: 80
              spike_limit_percentage: 20
          exporters:
            debug: {}
            otlp/traces:
              endpoint: "${JAEGER_INSTANCE_NAME}-collector.${JAEGER_NS}.svc.cluster.local:4317"
              tls:
                insecure: true
            prometheus:
              add_metric_suffixes: false # Jaeger expects standard OTel metric names without _total suffixes
              endpoint: "0.0.0.0:8889"
              resource_to_telemetry_conversion:
                enabled: true # by default resource attributes are dropped
          service:
            pipelines:
              traces:
                receivers: [otlp, zipkin]
                processors: [memory_limiter, batch]
                exporters: [debug, otlp/traces] 
              metrics:
                receivers: [otlp]
                processors: [memory_limiter, batch]
                exporters: [debug, prometheus]
            telemetry:
              metrics:
                readers:
                - pull:
                    exporter:
                      prometheus:
                        host: 0.0.0.0
                        port: 8888
                        without_scope_info: true
                        without_type_suffix: true
                        without_units: true
      1. Метка prometheus: kube-prometheus позволяет ACP Prometheus собирать метрики Collector через автоматически создаваемый ServiceMonitor.
      2. Запросы и лимиты ресурсов для контейнера Collector. Настройте их в зависимости от ожидаемой пропускной способности трассировок.
      3. Позволяет Operator автоматически создавать ресурсы ServiceMonitor для endpoint метрик Collector.
      4. Приемник OTLP принимает данные трассировки по gRPC (порт 4317) и HTTP (порт 4318) от инструментированных приложений.
      5. Экспортер otlp/traces пересылает полученные трассировки в сервис jaeger collector. Endpoint формируется на основе имени и namespace экземпляра Jaeger.
      6. Пайплайн трассировки получает данные через OTLP и Zipkin, обрабатывает их через memory_limiter и batch, а затем экспортирует как в экспортер debug (для логирования), так и в otlp/traces (для пересылки в Jaeger).
    2. Сгенерируйте манифест с помощью envsubst и примените конфигурацию:

      envsubst < otel-collector.yaml | kubectl apply -f -
    3. Дождитесь готовности pod Collector:

      kubectl rollout status deployment/otel-collector \
        -n ${JAEGER_NS} --timeout=180s

    Проверка

    После установки всех компонентов проверьте сквозной конвейер трассировки, сгенерировав тестовые данные трассировки.

    1. Разверните telemetrygen в качестве тестового клиента для генерации примеров трассировок:

      kubectl apply -f - <<EOF
      apiVersion: v1
      kind: Pod
      metadata:
        name: telemetrygen
        namespace: ${JAEGER_NS}
      spec:
        restartPolicy: Never
        containers:
          - name: telemetrygen
            image: ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:latest
            args:
              - traces
              - --otlp-endpoint=otel-collector.${JAEGER_NS}.svc.cluster.local:4317
              - --otlp-insecure
              - --duration=150s
              - --interval=5s
              - --child-spans=3
              - --rate=2
              - --service=telemetrygen
              - --workers=1
      EOF
      # Wait for telemetrygen to complete, then clean up the test Pod
      kubectl wait -n ${JAEGER_NS} --for=jsonpath='{.status.phase}'=Succeeded pod/telemetrygen --timeout=10m
      kubectl delete pod -n ${JAEGER_NS} telemetrygen
      NOTE

      Параметр --otlp-endpoint должен указывать на сервис OpenTelemetry Collector, развернутый на предыдущем шаге.

    2. Откройте Jaeger UI по адресу <platform-url>/clusters/<cluster-name>/jaeger.

      Выберите сервис telemetrygen в раскрывающемся списке Service и нажмите Find Traces, чтобы убедиться, что сгенерированные трассировки отображаются.

      Выполните следующую команду, чтобы вывести URL Jaeger UI:

      echo "Jaeger UI: ${PLATFORM_URL}${JAEGER_BASEPATH}"

    (Необязательно) Включение Service Performance Monitoring (SPM)

    Service Performance Monitoring (SPM) отображается в Jaeger UI как вкладка Monitor и агрегирует данные span для формирования метрик RED (Request, Error, Duration). Это позволяет выявлять проблемы производительности без предварительного знания имен сервисов или операций. Дополнительные сведения см. в разделе Service Performance Monitoring (SPM).

    Для включения SPM требуются два изменения: добавить SpanMetrics Connector в OpenTelemetry Collector и настроить совместимый с PromQL backend метрик в Jaeger.

    Предварительные требования

    • Развернуты Jaeger v2 и OpenTelemetry Collector (все предыдущие шаги выполнены).
    • В кластере доступен ACP monitoring.

    Процедура

    1. Получите endpoint мониторинга и учетные данные из кластера:

      export MONITORING_URL=$(kubectl get feature monitoring -o jsonpath='{.spec.accessInfo.database.address}')
      MONITORING_SECRET_NAME=$(kubectl get feature monitoring -o jsonpath='{.spec.accessInfo.database.basicAuth.secretName}')
      
      export MONITORING_USERNAME=$(kubectl -ncpaas-system get secret "$MONITORING_SECRET_NAME" -o jsonpath="{.data.username}" | base64 -d)
      export MONITORING_PASSWORD=$(kubectl -ncpaas-system get secret "$MONITORING_SECRET_NAME" -o jsonpath="{.data.password}" | base64 -d)
    2. Создайте Secret для учетных данных мониторинга:

      kubectl create secret generic monitoring-credentials \
        --namespace=${JAEGER_NS} \
        --from-literal=username=${MONITORING_USERNAME} \
        --from-literal=password=${MONITORING_PASSWORD} \
        --dry-run=client -o yaml | kubectl apply -f -
    3. Примените patch к OpenTelemetry Collector, чтобы включить SpanMetrics Connector. Это добавит connector spanmetrics, который генерирует метрики RED из span и экспортирует их через экспортер Prometheus:

      kubectl patch opentelemetrycollector otel -n ${JAEGER_NS} --type=merge -p '
      spec:
        config:
          connectors:
            spanmetrics: {}
          service:
            pipelines:
              traces:
                exporters: [debug, otlp/traces, spanmetrics]
              metrics/spanmetrics:
                receivers: [spanmetrics]
                exporters: [prometheus]
      '

      Дождитесь перезапуска Collector:

      kubectl rollout status deployment/otel-collector \
        -n ${JAEGER_NS} --timeout=180s
    4. Создайте файл с именем jaeger-spm-patch.yaml со следующим содержимым. Этот patch добавляет backend метрик PromQL в Jaeger и включает вкладку Monitor:

      jaeger-spm-patch.yaml
      spec:
        volumes:
          - name: es-credentials
            secret:
              secretName: es-credentials
              items:
                - key: ES_PASS
                  path: pass
          - name: oauth2-proxy-secrets
            secret:
              secretName: ${JAEGER_INSTANCE_NAME}-oauth2-proxy
              items:
                - key: OAUTH2_PROXY_CLIENT_SECRET
                  path: client-secret
                - key: OAUTH2_PROXY_COOKIE_SECRET
                  path: cookie-secret
          - name: monitoring-credentials
            secret:
              secretName: monitoring-credentials
              items:
                - key: username
                  path: user
                - key: password
                  path: pass
        volumeMounts:
          - name: es-credentials
            mountPath: /etc/jaeger/es-credentials
            readOnly: true
          - name: monitoring-credentials
            mountPath: /etc/jaeger/monitoring-credentials
            readOnly: true
        config:
          extensions:
            basicauth/monitoring:
              client_auth:
                username_file: /etc/jaeger/monitoring-credentials/user
                password_file: /etc/jaeger/monitoring-credentials/pass
            jaeger_storage:
              metric_backends:
                monitoring_metrics_storage:
                  prometheus:
                    endpoint: ${MONITORING_URL}
                    tls:
                      insecure_skip_verify: true
                    auth:
                      authenticator: basicauth/monitoring
            jaeger_query:
              storage:
                metrics: monitoring_metrics_storage
          service:
            extensions: [basicauth/monitoring, healthcheckv2, jaeger_storage, jaeger_query] 
      1. Том monitoring-credentials монтирует учетные данные basic-auth для мониторинга в контейнер Jaeger.
      2. volumeMount для monitoring-credentials делает учетные данные доступными по пути /etc/jaeger/monitoring-credentials/.
      3. Расширение basicauth/monitoring предоставляет basic authentication для endpoint метрик мониторинга.
      4. Раздел metric_backends настраивает совместимое с PromQL хранилище метрик, которое Jaeger запрашивает для данных SPM.
      5. Укажите store метрик в расширении jaeger_query.
      6. Расширение basicauth/monitoring должно быть добавлено в список service.extensions, чтобы оно было активным.
      WARNING

      Поля volumes, volumeMounts и service.extensions являются массивами. Merge patch полностью заменяет массивы, а не дополняет их. Приведенный выше файл patch включает все существующие элементы вместе с новыми, чтобы предотвратить потерю данных.

    5. Примените patch:

      kubectl patch opentelemetrycollector ${JAEGER_INSTANCE_NAME} -n ${JAEGER_NS} \
        --type=merge -p "$(envsubst < jaeger-spm-patch.yaml)"

      Дождитесь перезапуска Jaeger:

      kubectl rollout status deployment/${JAEGER_INSTANCE_NAME}-collector \
        -n ${JAEGER_NS} --timeout=180s

    Проверка

    После включения SPM вы можете проверить его, развернув тестовый клиент telemetrygen, как описано в разделе Проверка выше.

    После генерации трассировок перейдите на вкладку Monitor в Jaeger UI, чтобы просмотреть агрегированные метрики RED для сервиса telemetrygen.

    Удаление

    Чтобы удалить компоненты Alauda Distributed Tracing из кластера, следуйте инструкции Удаление Alauda Distributed Tracing.