Azure Managed Grafana + Prometheus no AKS: observabilidade moderna com stack open-source gerenciado - Parte 1
Se você acompanha esta série, já vimos como implementar observabilidade em contêineres com Azure Monitor e AKS, como configurar Azure Workbooks para visualização avançada e até como montar observabilidade avançada para GPU e inferência. Mas há uma realidade que muitos times enfrentam: a equipe já conhece Prometheus e Grafana. Já tem dashboards construídos, alertas configurados em PromQL e runbooks baseados nesse stack. Migrar para um modelo 100% proprietário do Azure Monitor significa jogar fora esse investimento e reaprender tudo.
É por isso que a Microsoft criou o Azure Managed Grafana e o Azure Monitor managed service for Prometheus, versões totalmente gerenciadas das ferramentas open-source mais populares do ecossistema de observabilidade. Você mantém a mesma linguagem de queries (PromQL), os mesmos dashboards (JSON nativo do Grafana), as mesmas regras de alerta, mas sem a dor operacional de gerenciar clusters Prometheus, lidar com retenção de dados, scaling de storage e upgrades do Grafana.
Neste artigo, vamos implementar do zero uma stack de observabilidade moderna no AKS usando Managed Grafana e Prometheus: desde o provisionamento da infraestrutura até dashboards avançados, alertas em PromQL, métricas customizadas de aplicações, cenários multi-cluster e as armadilhas que fazem times perderem dias debugando por que métricas simplesmente não aparecem.
Por que Prometheus e Grafana no Azure?
Antes de entrar na implementação, é fundamental entender por que a Microsoft investiu em oferecer versões gerenciadas de ferramentas open-source em vez de simplesmente empurrar Azure Monitor para todo mundo.
O ecossistema Prometheus é o padrão de fato
Prometheus se tornou o padrão de métricas para workloads cloud-native. Não é questão de opinião, é fato:
- É o segundo projeto graduado pela CNCF (depois do Kubernetes)
- Mais de 90% dos clusters Kubernetes em produção usam Prometheus ou derivados
- O formato de métricas do Prometheus (OpenMetrics) é o padrão da indústria
- Ferramentas como Istio, NGINX, Redis, PostgreSQL e centenas de exporters expõem métricas nativamente no formato Prometheus
O problema do Prometheus self-hosted
Rodar Prometheus em produção é simples para um cluster pequeno. Para operações reais, vira pesadelo:
| Desafio | Impacto |
|---|---|
| Storage | Prometheus usa armazenamento local; se o pod morre, você perde métricas |
| Escalabilidade | Um único Prometheus não aguenta clusters grandes (>500 nodes) |
| Alta disponibilidade | Precisa de Thanos ou Cortex para replicação e long-term storage |
| Multi-cluster | Federar métricas entre clusters é complexo e frágil |
| Upgrades | Cada versão pode quebrar compatibilidade de PromQL ou storage format |
| Retenção | Balancear custo de storage vs. histórico necessário é operacionalmente caro |
| Segurança | Controle de acesso nativo do Prometheus é praticamente inexistente |
A proposta do Azure: open-source sem a dor operacional
O Azure resolve isso com dois serviços complementares:
| Serviço | O que é | O que substitui |
|---|---|---|
| Azure Monitor managed service for Prometheus | Backend de ingestão e armazenamento de métricas Prometheus, totalmente gerenciado | Prometheus server + Thanos/Cortex para long-term storage |
| Azure Managed Grafana | Instância Grafana totalmente gerenciada, com autenticação via Entra ID e plugins pré-configurados | Grafana self-hosted + gerenciamento de usuários/plugins |
A combinação oferece:
- Zero operação de infraestrutura: sem pods, sem PVCs, sem upgrades manuais
- Retenção de 18 meses incluída, com billing baseado em ingestão
- Multi-cluster nativo: um único Azure Monitor workspace recebe métricas de N clusters
- RBAC via Entra ID: controle de acesso granular integrado com identidade corporativa
- Compatibilidade total com PromQL: suas queries existentes funcionam sem alteração
- Dashboards da comunidade: importe dashboards do Grafana.com direto
Arquitetura de referência
Antes de provisionar qualquer recurso, vamos entender como os componentes se conectam:
Fluxo de dados:
- O AKS roda um agente de coleta (ama-metrics, baseado no Prometheus agent) como DaemonSet
- O agente faz scrape das métricas de pods, nodes e serviços no formato Prometheus
- As métricas são enviadas via remote write para o Azure Monitor workspace
- O Managed Grafana consulta o workspace usando PromQL como data source
- Dashboards, alertas e explorações usam PromQL padrão
Provisionamento da infraestrutura
Vamos provisionar tudo via CLI, começando pelos pré-requisitos e avançando até a stack completa funcionando.
Pré-requisitos
# Variáveis de ambiente
export RESOURCE_GROUP="rg-observability-prod"
export LOCATION="eastus2"
export AKS_CLUSTER="aks-prod-east"
export MONITOR_WORKSPACE="amw-prometheus-prod"
export GRAFANA_NAME="grafana-prod-east"
# Criar resource group
az group create \
--name $RESOURCE_GROUP \
--location $LOCATION
Passo 1: Criar o Azure Monitor workspace
O Azure Monitor workspace é o backend que armazena as métricas Prometheus. Pense nele como o "Prometheus server" gerenciado.
# Criar o workspace
az monitor account create \
--name $MONITOR_WORKSPACE \
--resource-group $RESOURCE_GROUP \
--location $LOCATION
# Obter o ID do workspace (vamos precisar)
MONITOR_WORKSPACE_ID=$(az monitor account show \
--name $MONITOR_WORKSPACE \
--resource-group $RESOURCE_GROUP \
--query id -o tsv)
echo "Workspace ID: $MONITOR_WORKSPACE_ID"
Passo 2: Criar o Azure Managed Grafana
# Criar instância Managed Grafana
az grafana create \
--name $GRAFANA_NAME \
--resource-group $RESOURCE_GROUP \
--sku Standard \
--zone-redundancy Enabled \
--public-network-access Enabled
# Obter o ID do Grafana
GRAFANA_ID=$(az grafana show \
--name $GRAFANA_NAME \
--resource-group $RESOURCE_GROUP \
--query id -o tsv)
echo "Grafana ID: $GRAFANA_ID"
SKUs disponíveis:
| SKU | Características | Cenário |
|---|---|---|
| Essential | Sem SLA, sem zone redundancy, 1 instância | Dev/test, exploração |
| Standard | SLA 99.9%, zone redundancy, alerting nativo | Produção |
Dica: Sempre use Standard para produção. A diferença de custo é pequena comparada ao valor de ter observabilidade disponível durante um incidente.
Passo 3: Criar o cluster AKS com monitoramento habilitado
Se você já tem um cluster AKS, pode habilitar o monitoramento Prometheus sem recriá-lo. Aqui mostramos ambos os caminhos.
Novo cluster com Prometheus habilitado:
az aks create \
--name $AKS_CLUSTER \
--resource-group $RESOURCE_GROUP \
--location $LOCATION \
--node-count 3 \
--node-vm-size Standard_D4s_v5 \
--network-plugin azure \
--network-plugin-mode overlay \
--enable-azure-monitor-metrics \
--azure-monitor-workspace-resource-id $MONITOR_WORKSPACE_ID \
--grafana-resource-id $GRAFANA_ID \
--generate-ssh-keys
Cluster existente, habilitar Prometheus:
az aks update \
--name $AKS_CLUSTER \
--resource-group $RESOURCE_GROUP \
--enable-azure-monitor-metrics \
--azure-monitor-workspace-resource-id $MONITOR_WORKSPACE_ID \
--grafana-resource-id $GRAFANA_ID
O parâmetro --grafana-resource-id configura automaticamente o Managed Grafana como data source conectado ao workspace Prometheus. Sem ele, você teria que configurar manualmente.
O que acontece por baixo dos panos
Quando você habilita --enable-azure-monitor-metrics, o Azure instala automaticamente no seu cluster:
| Componente | Tipo | Função |
|---|---|---|
| ama-metrics | DaemonSet | Agente de coleta no formato Prometheus (baseado no Prometheus agent mode) |
| ama-metrics-node | DaemonSet | Coleta métricas de nível de node (kubelet, cAdvisor) |
| ama-metrics-ksm | Deployment | Kube State Metrics — métricas de estado do Kubernetes (pods, deployments, etc.) |
Você pode verificar que tudo está rodando:
kubectl get pods -n kube-system | grep ama-metrics
Saída esperada:
ama-metrics-5d8b7c8f9d-x2j4k 2/2 Running 0 5m
ama-metrics-ksm-6f9c8d7b5-m3n7p 1/1 Running 0 5m
ama-metrics-node-abc12 2/2 Running 0 5m
ama-metrics-node-def34 2/2 Running 0 5m
ama-metrics-node-ghi56 2/2 Running 0 5m
Métricas coletadas por padrão
O Azure Managed Prometheus coleta um conjunto padrão de métricas que cobre os cenários mais comuns. Entender o que é coletado por padrão (e o que não é) evita horas de debugging.
Métricas habilitadas por padrão
| Categoria | Exemplos de métricas | Fonte |
|---|---|---|
| Node | node_cpu_seconds_total, node_memory_MemTotal_bytes, node_disk_io_time_seconds_total | Node exporter (via kubelet) |
| Kubelet | kubelet_running_pods, kubelet_volume_stats_used_bytes | Kubelet |
| cAdvisor | container_cpu_usage_seconds_total, container_memory_working_set_bytes | cAdvisor |
| Kube State Metrics | kube_pod_status_phase, kube_deployment_status_replicas, kube_node_status_condition | KSM |
| API Server | apiserver_request_total, apiserver_request_duration_seconds | API Server |
| CoreDNS | coredns_dns_requests_total, coredns_dns_responses_total | CoreDNS |
Métricas NÃO coletadas por padrão
Este é o ponto onde muita gente trava. Métricas de aplicações customizadas (seus pods, seus exporters) não são coletadas automaticamente. Você precisa configurar scraping customizado.
Configurando scrape de métricas customizadas
A coleta de métricas das suas aplicações requer configuração adicional via ConfigMap ou PodMonitor/ServiceMonitor.
Opção 1: Pod annotations (mais simples)
A forma mais rápida é usar annotations nos pods da sua aplicação:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-pedidos
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: api-pedidos
template:
metadata:
labels:
app: api-pedidos
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
prometheus.io/path: "/metrics"
spec:
containers:
- name: api
image: myregistry.azurecr.io/api-pedidos:v2.3.1
ports:
- containerPort: 8080
Para que essas annotations sejam respeitadas, você precisa criar um ConfigMap que configure o agente ama-metrics para reconhecê-las:
# ama-metrics-settings-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ama-metrics-settings-configmap
namespace: kube-system
data:
schema-version: v1
config-version: ver1
prometheus-collector-settings: |
[prometheus-collector-settings]
cluster_alias = "aks-prod-east"
default-scrape-settings: |
[default-scrape-settings]
merge_annotations = true
pod-annotation-based-scraping: |
[pod-annotation-based-scraping]
podannotationnamespaceregex = "production|staging"
kubectl apply -f ama-metrics-settings-configmap.yaml
Opção 2: Custom scrape config (controle total)
Para cenários onde você precisa de controle fino sobre quais endpoints são scraped, use uma configuração Prometheus customizada:
# ama-metrics-prometheus-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ama-metrics-prometheus-config
namespace: kube-system
data:
prometheus-config: |
scrape_configs:
- job_name: 'api-pedidos'
scrape_interval: 15s
kubernetes_sd_configs:
- role: pod
namespaces:
names:
- production
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_app]
regex: api-pedidos
action: keep
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: (.+)
replacement: $1:8080
- job_name: 'redis-exporter'
scrape_interval: 30s
kubernetes_sd_configs:
- role: pod
namespaces:
names:
- production
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_app]
regex: redis-exporter
action: keep
- job_name: 'nginx-ingress'
scrape_interval: 10s
kubernetes_sd_configs:
- role: pod
namespaces:
names:
- ingress-nginx
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_app.kubernetes.io/name]
regex: ingress-nginx
action: keep
kubectl apply -f ama-metrics-prometheus-config.yaml
# Reiniciar o agente para aplicar a configuração
kubectl rollout restart deployment ama-metrics -n kube-system
Construindo dashboards no Managed Grafana
Com métricas fluindo para o Azure Monitor workspace, é hora de construir dashboards que entreguem valor real para o time.
Acessando o Grafana
# Obter a URL do Grafana
az grafana show \
--name $GRAFANA_NAME \
--resource-group $RESOURCE_GROUP \
--query properties.endpoint -o tsv
O acesso usa autenticação via Microsoft Entra ID. Os roles disponíveis:
| Role | Permissões |
|---|---|
| Grafana Viewer | Visualizar dashboards e explorar métricas |
| Grafana Editor | Criar e editar dashboards, alertas e data sources |
| Grafana Admin | Tudo acima + gerenciar usuários, plugins e configurações |
# Atribuir role de Editor para um usuário
az role assignment create \
--assignee "usuario@empresa.com" \
--role "Grafana Editor" \
--scope $GRAFANA_ID
# Atribuir role de Viewer para um grupo de Entra ID
az role assignment create \
--assignee "grupo-sre-id" \
--role "Grafana Viewer" \
--scope $GRAFANA_ID
Dashboard: Visão geral do cluster AKS
Abaixo, as queries PromQL essenciais para um dashboard de visão geral do cluster. Cada query pode ser adicionada como um painel no Grafana.
Uso de CPU por node (%):
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
Uso de memória por node (%):
100 * (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes))
Pods em estado não-Running:
sum by (namespace, phase) (kube_pod_status_phase{phase!="Running", phase!="Succeeded"})
Taxa de requisições ao API Server (por código de resposta):
sum by (code) (rate(apiserver_request_total[5m]))
Pods com restart recente (últimas 2 horas):
sum by (namespace, pod) (
increase(kube_pod_container_status_restarts_total[2h])
) > 0
Consumo de CPU por namespace:
sum by (namespace) (
rate(container_cpu_usage_seconds_total{container!="", container!="POD"}[5m])
)
Uso de disco dos PVCs (%):
100 * (
kubelet_volume_stats_used_bytes
/ kubelet_volume_stats_capacity_bytes
)
Dashboard: Métricas de aplicação
Para aplicações que expõem métricas no formato Prometheus (via bibliotecas como prometheus-client para Python, prom-client para Node.js ou Micrometer para Java), as queries de negócio ficam poderosas:
Latência P99 da API (histograma):
histogram_quantile(0.99,
sum by (le, endpoint) (
rate(http_request_duration_seconds_bucket{app="api-pedidos"}[5m])
)
)
Taxa de erros HTTP (5xx):
sum(rate(http_requests_total{app="api-pedidos", status=~"5.."}[5m]))
/
sum(rate(http_requests_total{app="api-pedidos"}[5m]))
* 100
Requisições por segundo por endpoint:
sum by (endpoint, method) (
rate(http_requests_total{app="api-pedidos"}[5m])
)
Fila de processamento — itens pendentes:
sum(queue_pending_messages{service="worker-pedidos"})
Importando dashboards da comunidade
Uma das maiores vantagens do Grafana é o ecossistema de dashboards prontos. No Managed Grafana, você pode importar dashboards do Grafana.com diretamente:
# Importar dashboard de Kubernetes via CLI
az grafana dashboard import \
--name $GRAFANA_NAME \
--resource-group $RESOURCE_GROUP \
--definition 15760
# Dashboards populares para AKS:
# 15760 - Kubernetes / Views / Global (by dotdc)
# 15757 - Kubernetes / Views / Namespaces (by dotdc)
# 15758 - Kubernetes / Views / Nodes (by dotdc)
# 15759 - Kubernetes / Views / Pods (by dotdc)
# 13770 - Kube State Metrics v2
# 1860 - Node Exporter Full
Conclusão da Parte 1
Nesta primeira parte, provisionamos toda a infraestrutura de observabilidade no AKS — Azure Monitor workspace, Managed Grafana e a integração com Prometheus — além de configurar scrape de métricas customizadas e construir dashboards avançados com PromQL para monitoramento de cluster e aplicações.
Com a base sólida em funcionamento, já temos visibilidade completa sobre recursos de infraestrutura e métricas de negócio no Grafana. Na Parte 2, vamos configurar Recording Rules, Alerting Rules, monitoramento multi-cluster, dashboards como código e troubleshooting.