Depurando microsserviços no Kubernetes com Istio, OpenTelemetry e Tempo — Parte 2

Na parte 1 expliquei como:

  • Instale o Grafana Tempo como back-end para armazenar dados de telemetria
  • Instalar e configurar o Operador OpenTelemetry
  • Configurar o Istio para rastreamento usando o provedor de extensão opentelemetry
  • Configurar o controlador de entrada Nginx para OpenTelemetry

Nesta segunda parte, vou explicar como:

  • Configurar fontes de dados para Tempo e Loki no Grafana
  • Configurar instrumentação automatizada para propagação de contexto

Fontes de dados do Grafana

Agora o Istio e os controladores de entrada Nginx estão configurados para enviar dados de telemetria para o OpenTelemetry Collector, e o Collector está configurado para exportar dados para o Tempo, a próxima coisa que queremos é ver rastreamentos.

Como estou usando o Otomi, o Loki já está instalado e configurado em uma configuração multilocatário permitindo que o Teams veja os logs de seus aplicativos. O log de acesso padrão do Envoy é configurado para mostrar a ID de Rastreamento nos logs e o Teams pode ver esses logs no Loki. Agora eu quero que um usuário seja capaz de abrir o rastreamento completo (consultado fron Tempo) com base em um ID de rastreamento nos logs de Loki. Para isso vou configurar 2 fontes de dados. Um para Tempo e outro para Tempo.

Vamos começar com a fonte de dados para Tempo. Use os seguintes valores para configurar uma fonte de dados Grafana adicional para Tempo:

grafana:
    additionalDataSources:
      - name: Tempo
        type: tempo
        uid: tempo
        access: proxy
        url: http://tempo-query-frontend.tempo:3100
        jsonData:
          nodeGraph:
            enabled: true

E então a fonte de dados adicional para Loki:

grafana:
    additionalDataSources:
      - name: Loki
        editable: false
        type: loki
        uid: loki
        access: proxy
        url: http://loki-query-frontend-headless.monitoring:3101
        jsonData:
          derivedFields:
            - datasourceName: Tempo
              matcherRegex: "traceID=00-([^\\-]+)-"
              name: traceID
              url: "$${__value.raw}"
              datasourceUid: tempo

Como estou usando o provedor de extensão opentelemetry no Istio, os logs de acesso do Envoy mostrarão o cabeçalho TRACEPARENT. Este cabeçalho tem a seguinte aparência:

00-3724a0faa7a5c20783702c91a9082ae2-4526b089c53276b7-01

A ID de rastreamento, no entanto, está entre o primeiro e o segundo (traço). É por isso que estou usando o matcherRegex “traceID=00-([^\\-]+)-“. Isso agora adicionará a opção de vincular diretamente ao rastreamento no Tempo:

Quando você clicar no link para Tempo, Tempo será consultado com base no ID de rastreamento:

E ao clicar no gráfico Nó, você verá o fluxo completo:

Agora você pode notar que o Tempo está mostrando o rastreamento completo do controlador Nginx para o Istio Ingress Gateway, para o Ingress da equipe e, em seguida, vários vãos dentro do aplicativo petclinic. Na primeira parte expliquei que o Istio não é capaz disso e você precisará instrumentar o aplicativo.

Na parte 1 também mostrei como instalar o Tempo Metrics Generator. Este é um requisito para usar gráficos de serviço no Grafana. Os gráficos de serviço podem ajudá-lo a entender a estrutura de um sistema distribuído. Não vou me aprofundar em todas as possibilidades de relacionar logs, métricas e rastreamentos. Você pode ler sobre todas as opções de configuração da fonte de dados aqui. Vamos lá e instrumentalizar um aplicativo.

Configuração automatizada de instrumentação

A instrumentação automática é um recurso do OpenTelemetry Operator para fornecer uma maneira de instrumentar seu aplicativo sem tocar no código-fonte.

Antes de implantarmos o aplicativo petclinic, primeiro precisaremos criar um recurso:OpenTelemetryCollector

apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
  name: sidecar
spec:
  mode: sidecar
  config: |
    receivers:
      otlp:
        protocols:
          grpc:
          http:
    exporters:
      otlp:
        endpoint: otel-collector-collector.otel.svc.cluster.local:4317
        tls:
          insecure: true
    service:
      pipelines:
        traces:
          receivers:
          - otlp
          exporters:
          - otlp    

Este coletor funcionará como um sidecar no Pod petclinic e enviará todos os dados de telemetria para o coletor central (que criamos na Parte 1).

Em seguida, precisaremos criar um recurso:Instrumentation


apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: java-instrumentation
spec:
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: always_on
  java:
    env:
      - name: OTEL_EXPORTER_OTLP_ENDPOINT
        value: http://otel-collector-collector.otel.svc.cluster.local:4317

Observe que um Propagator é usado para propagar o contexto de rastreamento.

Agora implante a imagem da petclinic:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: petclinic
  labels:
    app: petclinic
spec:
  replicas: 1
  selector:
    matchLabels:
      app: petclinic
  template:
    metadata:
      labels:
        app: petclinic
      annotations:
        instrumentation.opentelemetry.io/inject-java: 'true'
        sidecar.opentelemetry.io/inject: 'sidecar'
    spec:
      containers:
      - name: petclinic
        image: springcommunity/spring-framework-petclinic
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: petclinic
spec:
  selector:
    app: petclinic
  ports:
    - port: 80
      targetPort: 8080

Como você pode ver, eu só criei um serviço. Como uso o Otomi, só preciso configurar o serviço para exposição.ClusterIP

Agora que o aplicativo PetClinic está implantado e a Instrumentação configurada, agora podemos ver o rastreamento completo e ver o que deu errado:

Usando Jaeger como back-end

Ao usar o OpenTelemetry Collector, você pode usar facilmente um back-end diferente. Se você quiser usar o Jaeger, basta adicionar o Jaeger como exportador à configuração do coletor:

exporters:
  logging:
    loglevel: info
  otlp:
    endpoint: tempo-distributor.tempo.svc.cluster.local:4317
    sending_queue:
      enabled: true
      num_consumers: 100
      queue_size: 10000
    retry_on_failure:
      enabled: true
    tls:
      insecure: true
  jaeger:
    endpoint: jaeger-operator-jaeger-collector.jaeger.svc:14250
    tls:
      insecure: true
service:
  pipelines:
    traces:
      receivers:
      - otlp
      processors:
      - memory_limiter
      - batch
      exporters:
      - logging
      - otlp
      - jaeger

Em seguida, instale o Jaeger e você verá os mesmos traços:

Recapitular

Na primeira parte desta minissérie, vimos como configurar o rastreamento no Kubernetes usando Istio, OpenTelemetry e Grafana Tempo. Eu realmente não me aprofundei na teoria por trás do rastreamento, mas apenas me concentrei na implementação. Mas esteja ciente do fato de que eu não cobri todos os tópicos como multilocação, ajuste de desempenho, personalização de registro do Envoy. Talvez isso fique para outra época.

A configuração que expliquei aqui será a base para o rastreamento no Otomi. Ao usar o Otomi, você poderá ativar o Tempo e o OpenTelemetry e, em seguida, o Istio e todas as fontes de dados do Grafana serão configuradas automaticamente.

Tempo e OpenTelemetry em Otomi

Seja o primeiro a experimentá-lo e siga o Otomi no GitHub.


Artigo Original