Программа курса

Модуль 03 / Урок 14 из 27

Практикум: полный стенд docker-compose

Теория и практика

Собираем всё, что изучили: два сервиса → OTel Collector (с фильтрацией и батчингом) → Jaeger с Elasticsearch. Этот стенд — основа всех практикумов дальше.

docker-compose.yml

version: "3.8"
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.13.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - ES_JAVA_OPTS=-Xms512m -Xmx512m
    ports: ["9200:9200"]

  jaeger:
    image: jaegertracing/all-in-one:latest
    environment:
      - SPAN_STORAGE_TYPE=elasticsearch
      - ES_SERVER_URLS=http://elasticsearch:9200
    ports:
      - "16686:16686"   # UI
      - "14268:14268"   # legacy-приём
    depends_on: [elasticsearch]

  otel-collector:
    image: otel/opentelemetry-collector-contrib:latest
    command: ["--config=/etc/otel/config.yaml"]
    volumes:
      - ./otel-config.yaml:/etc/otel/config.yaml
    ports:
      - "4317:4317"     # OTLP gRPC — сюда шлют приложения
      - "4318:4318"     # OTLP HTTP
    depends_on: [jaeger]

otel-config.yaml

receivers:
  otlp:
    protocols:
      grpc: {}
      http: {}

processors:
  memory_limiter:
    check_interval: 1s
    limit_percentage: 75
    spike_limit_percentage: 15
  attributes/strip:
    actions:
      - key: db.statement
        action: delete          # PII-политика: не хранить SQL-тексты
  filter/noise:
    traces:
      span:
        - 'attributes["http.route"] == "/health"'
  batch:
    send_batch_size: 512
    timeout: 3s

exporters:
  otlp/jaeger:
    endpoint: jaeger:4317
    tls: { insecure: true }
  debug:
    verbosity: basic

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, attributes/strip, filter/noise, batch]
      exporters: [otlp/jaeger]

Приложения

Те же service-a/service-b из практикума 1.4, но теперь:

OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317   # в Collector, не в Jaeger!

Чек-лист проверки стенда

  1. docker compose up -d; ES поднялся (не экономьте: ему нужен 1+ ГБ heap);
  2. дёргайте curl localhost:8080/do и curl localhost:8081/health;
  3. UI: трейсы service-a есть, спанов /health нет — работает filter;
  4. откройте SQL-спан: db.statement отсутствует — работает attributes/strip;
  5. рестарт ES: docker compose restart elasticsearch — после подъёма трейсы снова пишутся (Collector пережил паузу очередью).

Задания

  1. Добавьте третий сервис service-c, вызываемый из B: убедитесь, что трейс стал трёхзвенным без изменения конфигов Collector.
  2. Вынесите processor resource: добавьте всем спанам deployment.environment=dev; проверьте в UI процесс-теги.
  3. Замерьте задержку появления трейса в UI (создали запрос → увидели в поиске) и объясните её слагаемые: batch timeout + запись ES + окно поиска UI.
  4. Нагрузочный тест: 100 RPS на /do в течение 5 минут; следите за памятью Collector и отставанием ES (почта ошибок экспорта в логах).
Мини-квиз

1. Почему приложения шлют в Collector, а не прямо в Jaeger? — Развязка: фильтры, PII, батчинг, смена бэкенда без правки приложений.

2. Что проверяют спаны /health? — Что filter-процессор действительно отсеивает шум до экспорта.

3. Почему трейсы появились после рестарта ES? — Collector буферизовал и с ретраями доставил после восстановления.