Grafana Agent e OpenTelemetry Operator
É interessante somente ler sobre isso depois que dominar o OpenTelemetry.
No kubernetes temos o Opetelemetry Operator que consegue injeta automaticamente uma instrumentação na aplicação usando um init container e sobe um collector já pré configurado como um sidecar igual o Istio.
Para configurar o collector temos custom resources específicos do opentelemetry. É uma proposta bem interesante.
Porém se falamos que o grafana agent pode funcionar como collector devíamos ter o sidecar? Podemos e não podemos, mas o grafana agent não tem a parte que injectar automaticamente a instrumentação.
O OpenTelemetry Operator e o Grafana Agent servem propósitos diferentes, mesmo que haja algumas sobreposições:
OpenTelemetry Operator:
- Faz a instrumentação automática das aplicações
- Configura sidecars automaticamente
- Gerencia o ciclo de vida da instrumentação
- Facilita a configuração via CRDs (Custom Resources)
Grafana Agent:
- Foco em coletar e enviar dados para Grafana Cloud
- Pode receber dados OTLP, mas não faz instrumentação
- Não tem capacidade de injetar instrumentação
Então, mesmo usando Grafana Agent, você ainda pode querer o OpenTelemetry Operator para:
- Instrumentação automática das aplicações
- Gerenciamento via Kubernetes native (CRDs)
- Configuração consistente entre aplicações
Uma arquitetura possível seria:
App + Auto-instrumentação (via Operator) --→ Grafana Agent --→ Grafana Cloud
O Operator cuida da instrumentação, enquanto o Agent cuida do envio para Grafana Cloud.
Por exemplo iriamos configurar aqui o nosso grafana agent para receber todos os tipos de dados.
apiVersion: monitoring.grafana.com/v1alpha1
kind: GrafanaAgent
metadata:
name: grafana-agent
spec:
flow:
# Recebedor OTLP para traces e logs
otelcol.receiver.otlp "default" {
grpc {
endpoint = "0.0.0.0:4317"
}
http {
endpoint = "0.0.0.0:4318"
}
}
# Configuração para Tempo (traces)
otelcol.exporter.otlp "tempo" {
client {
endpoint = "tempo-prod-XX.grafana.net:443"
auth {
basic {
username = "your-username"
password = "your-api-key"
}
}
}
}
# Configuração para Loki (logs)
loki.write "default" {
endpoint {
url = "https://logs-prod-XX.grafana.net/loki/api/v1/push"
basic_auth {
username = "your-username"
password = "your-api-key"
}
}
}
# Service Discovery Kubernetes
discovery.kubernetes "pods" {
role = "pod"
}
# Configuração para Prometheus (métricas)
prometheus.remote.write "default" {
endpoint {
url = "https://prometheus-prod-XX.grafana.net/api/prom/push"
basic_auth {
username = "your-username"
password = "your-api-key"
}
}
}
prometheus.scrape "default" {
targets = discovery.kubernetes.pods.targets
forward_to = [prometheus.remote.write.default.receiver]
clustering {
enabled = true
}
}
Então poderíamos simplemente configurar uma instrumentador do operator assim:
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: app-instrumentation
spec:
exporter:
endpoint: http://grafana-agent:4317 # Para traces e logs
metrics:
enable: true
prometheusExporter:
port: 8080 # Porta que expõe /metrics
propagators:
- tracecontext
- baggage
sampler:
type: parentbased_traceidratio
argument: "1"
Aplicação (instrumentada pelo Operator)
├──→ /metrics endpoint --→ Grafana Agent scrape --→ Prometheus Cloud
├──→ traces OTLP --------→ Grafana Agent --------→ Tempo Cloud
└──→ logs OTLP ----------→ Grafana Agent --------→ Loki Cloud
Configuramos o grafana agent para fazer o scrape de todas as aplicações do cluster.
Nada impede de não querer usar dessa maneira e colocar um collector também e configurar para enviar os dados para o seu grafana. O operator tem um custom resource só para configuração do collector como sidecar, mas sabendo que o grafana agent também funciona podemos diminuir muitos containers extras nos pods.
Isso só faz sentido se você estiver usando o Grafana, se sua stack for outra não se preocupe com isso.