
Fala dev! Neste BoraPraticar, vamos colocar de pé uma stack de observabilidade completa e leve usando o quarteto Prometheus, Loki, Promtail e Grafana. Tudo isso em um cluster local criado com o K3d, com uma aplicação Spring Boot que emite logs e métricas no estilo profissional. 💻✨
⚠️ Este conteúdo é parte da série de artigos sobre Kubernetes no blog.setedevs.com.br. Se você caiu direto aqui, recomendamos ver os artigos anteriores para montar o ambiente com K3d e subir sua aplicação Spring Boot com PostgreSQL antes de prosseguir.
✅ Pré-requisitos
✅ Docker (o K3d roda tudo como container!)
✅ K3d (nosso Kubernetes local)
✅ kubectl (para conversar com o cluster)
✅ Java 17 ou superior (para rodar o Spring Boot)
✅ Maven ou Gradle (o que você estiver utilizando no projeto Spring Boot)
Antes de partir para a prática, garanta que você tem essas ferramentas instaladas:
Com isso no esquema, bora criar o cluster e ativar a observabilidade!
🧱 Criando o cluster com K3d
Antes de qualquer coisa, precisamos levantar nosso cluster local com o K3d, que é uma forma rápida e leve de rodar Kubernetes usando containers Docker. Bora rodar o seguinte comando:
k3d cluster create mycluster
Pronto! Isso já sobe um cluster K3s dentro de containers, perfeito para testes e estudos.
🧠 Antes de mais nada: o que é cada coisa?
📄 Prometheus
O Prometheus coleta e armazena métricas das suas aplicações, como uso de CPU, quantidade de requisições, tempo de resposta etc. Ele é quem faz o “pinga-pinga” nas APIs Spring Boot e guarda os números bonitinhos.
📜 Loki
O Loki é o parceiro do Prometheus, mas para logs. Em vez de você precisar instalar um ELK pesado, o Loki armazena os logs de forma eficiente e simples, integrando nativamente com o Grafana. Ah, e ele não precisa de indexação pesada!
🐾 Promtail
O Promtail é o agente responsável por ler os logs dos pods do Kubernetes e enviá-los para o Loki. Ele é feito sob medida para trabalhar com o Loki. Ao instalar o loki-stack
com o Helm, o Promtail já vem junto e começa automaticamente a monitorar os logs dos pods no cluster.
Sem ele, o Loki não tem como receber os logs da aplicação — então, apesar dele parecer um coadjuvante, o Promtail é essencial para fechar o ciclo da observabilidade baseada em logs. 😉
📈 Grafana
O Grafana é o visualizador oficial da zoeira! É nele que você cria dashboards maneiros para visualizar os dados que o Prometheus e o Loki coletam. Pode ser métricas, logs, alertas, tudo junto num só painel.
⚙️ Mágica com Helm
O Helm é um gerenciador de pacotes para Kubernetes. Ele funciona como um apt ou yum, mas para aplicações rodando em clusters. No nosso caso, vamos usar Helm para instalar toda a stack de observabilidade com um só comando. Mas antes, precisamos adicionar o repositório:
helm repo add grafana https://grafana.github.io/helm-charts helm repo update
Agora sim, podemos rodar o comando mágico:
helm upgrade --install loki grafana/loki-stack \ --namespace monitoring \ --create-namespace \ --set grafana.enabled=true \ --set grafana.persistence.enabled=true \ --set grafana.persistence.storageClassName=local-path \ --set grafana.persistence.size=2Gi \ --set loki.persistence.enabled=true \ --set loki.persistence.storageClassName=local-path \ --set loki.persistence.size=2Gi \ --set prometheus.enabled=true \ --set prometheus.alertmanager.persistentVolume.enabled=true \ --set prometheus.alertmanager.persistentVolume.storageClassName=local-path \ --set prometheus.server.persistentVolume.enabled=true \ --set prometheus.server.persistentVolume.storageClassName=local-path \ --set prometheus.server.persistentVolume.size=2Gi
Esse comando que não é magica, mas é tecnologia:
- Cria um namespace
monitoring
- Sobe o Loki, Promtail, o Prometheus e o Grafana
- Já configura o Grafana com persistência de dados
Depois que tudo subir, execute o seguinte comando para verificar se tudo está rodando direitinho:
kubectl get pods -n monitoring
Você deve ver os pods Loki
, Promtail
, Prometheus
, Grafana
e seus auxiliares com status Running
ou Completed
. Se algum estiver como CrashLoopBackOff
, para investigar rode o comando:
kubectl describe pod <nome-do-pod> -n monitoring
Agora, para acessar o Grafana:
kubectl port-forward -n monitoring service/loki-grafana 3000:80
Abra o navegador em http://localhost:3000
O usuario padrão criado:
Username: admin
Para obter o password rode o comando:👇
kubectl get secret loki-grafana -n monitoring -o jsonpath='{.data.admin-password}' | base64 --decode; echo
🚀 Configurando a aplicação Spring Boot
Crie uma aplicação Spring Boot ou utilize uma de sua preferencia
Para criar, você pode utilizar o Spring Initializr
Para este Borapraticar, crie o seguinte controller TestController, ele apenas gera nomes aleatórios e então poderemos simular as requisições e monitorar as mesmas:
import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.UUID; @Log4j2 @RequiredArgsConstructor @RestController @RequestMapping("/test") public class TestController { @GetMapping public String test() { UUID id = UUID.randomUUID(); String name = getRandomName(); String message = "Id: " + id + " | Username: " + name; log.info(message); return message; } private static final String[] NAMES = { "Jesus", "Moses", "Abraham", "David", "Noah", "Joseph", "Peter", "Paul", "John", "Mary", "Isaac", "Jacob", "Solomon", "Samuel", "Elijah", "Esther", "Ruth", "Joshua", "Daniel", "Deborah" }; private String getRandomName() { int idx = (int) (Math.random() * NAMES.length); return NAMES[idx]; } }
📦 Adicionando dependências no pom.xml
<!-- Exibe métricas no endpoint /actuator/prometheus --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- Exporta as métricas no formato do Prometheus --> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency> <!-- Formata os logs em JSON para o Loki entender --> <dependency> <groupId>net.logstash.logback</groupId> <artifactId>logstash-logback-encoder</artifactId> <version>7.3</version> </dependency>
📦 Adicionando o Plugin no pom.xml
Para gerar a imagem Docker da aplicação sem precisar criar um Dockerfile
manualmente, podemos usar o plugin jib-maven-plugin
.
Esse passo é opcional, claro. Se você já possui outra forma de gerar sua imagem, como um Dockerfile por exemplo, fique à vontade para seguir como preferir.
<plugin> <groupId>com.google.cloud.tools</groupId> <artifactId>jib-maven-plugin</artifactId> <version>3.4.0</version> <configuration> <from> <image>eclipse-temurin:21-jdk</image> </from> </configuration> </plugin>
📄 Configurando o logback-spring.xml
Para gerar logs estruturados em JSON, que facilita a integração com ferramentas como Grafana + Loki
🗂️ Crie o arquivo na pasta src/main/resources
O nome do arquivo deve ser exatamente logback-spring.xml
🧩 Conteúdo do arquivo:
<configuration> <include resource="org/springframework/boot/logging/logback/base.xml"/> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="net.logstash.logback.encoder.LogstashEncoder" /> </appender> <root level="INFO"> <appender-ref ref="CONSOLE" /> </root> </configuration>
🔍 Explicando rapidamente:
LogstashEncoder
: converte os logs para o formato JSON, que o Loki entende muito bem.ConsoleAppender
: envia os logs para o console, o que é essencial quando usamos o Loki para coletar logs dos containers.root level="INFO"
: define que apenas logs a partir do nível INFO serão exibidos. Em ambientes de desenvolvimento, você pode ajustar paraDEBUG
se quiser mais detalhes.
✅ Não esqueça da dependência do
logstash-logback-encoder
que já foi adicionada nopom.xml
anteriormente, sem ela a configuração dologback-spring.xml
não funciona.
⚙️ Configuração no application.yml
Para habilitar a coleta de métricas pela aplicação Spring Boot, basta configurar corretamente o arquivo application.yml
. Veja abaixo um exemplo:
management: endpoints: web: exposure: include: health,info,prometheus endpoint: health: show-details: always metrics: tags: application: minha-app
O que essa configuração faz?
exposure.include
: expõe os endpointshealth
,info
eprometheus
via HTTP. Isso é essencial para que o Prometheus consiga coletar as métricas da aplicação.health.show-details: always
: exibe detalhes dos checks de saúde da aplicação, que é fundamental para observabilidade.metrics.tags.application
: adiciona uma tag personalizada chamadaapplication
em todas as métricas. Isso facilita na hora de filtrar ou agrupar os dados no Grafana, principalmente quando você tem várias aplicações exportando métricas.
💡 Troque
minha-app
pelo nome real da sua aplicação.
Certifique-se de que sua aplicação esteja expondo o endpoint /actuator/prometheus
, como configurado no application.yml
.
🔗 Para testar localmente, com a aplicação em execução, acesse no navegador ou via curl
:
http://localhost:8080/actuator/prometheus
Você deverá ver várias métricas em formato de texto, como jvm_memory_used_bytes
, http_server_requests_seconds_count
, entre outras.
🚀 Preparando tudo para o deploy
Agora que a aplicação está configurada e pronta para monitoramento, vamos empacotá-la em uma imagem container e disponibilizar para o cluster.
🛠️ Gerando a imagem container com o Jib
Utilizaremos o plugin Jib (já configurado no pom.xml
) para gerar a imagem sem precisar criar um Dockerfile:
./mvnw compile jib:dockerBuild -Dimage=minha-app:latest
✅ Isso criará a imagem minha-app:latest
diretamente no seu ambiente local.
📦 Enviando a imagem para o cluster
Se você estiver usando K3d (como no nosso exemplo):
Importe a imagem diretamente para o cluster com o seguinte comando:
k3d image import minha-app:latest -c mycluster
🔁 Esse processo torna a imagem acessível dentro do ambiente K3d, sem precisar de um registry.
🛰️ Se estiver usando outros ambientes (como Kind, on-premise ou um cluster real na nuvem):
Você deve publicar a imagem em um registry acessível pelo cluster, como:
- Docker Hub
- GitHub Container Registry
- Google Artifact Registry
- Amazon ECR
- Seu próprio registry privado
📌 Para isso, você pode ajustar o comando do Jib para enviar diretamente para o seu registry, por exemplo:
./mvnw compile jib:build -Dimage=meu-registry.io/minha-app:latest
🔐 Lembre-se de configurar corretamente as credenciais do seu registry, se for privado.
☁️ Anotando o Deployment para Prometheus
Para que o Prometheus consiga descobrir e coletar as métricas expostas pela sua aplicação Spring Boot (via /actuator/prometheus
), precisamos adicionar labels e annotations no seu Deployment
.
metadata: labels: app: minha-app annotations: prometheus.io/scrape: "true" prometheus.io/path: "/actuator/prometheus" prometheus.io/port: "8080"
🧩 Onde exatamente adicionar?
As labels e annotations devem ser adicionadas na seção metadata
do pod template, e não no metadata do Deployment
em si.
✅ Exemplo completo e correto:
apiVersion: apps/v1 kind: Deployment metadata: name: minha-app spec: replicas: 1 selector: matchLabels: app: minha-app template: metadata: labels: app: minha-app annotations: prometheus.io/scrape: "true" prometheus.io/path: "/actuator/prometheus" prometheus.io/port: "8080" spec: containers: - name: minha-app image: minha-app:latest imagePullPolicy: Never ports: - containerPort: 8080 resources: requests: memory: "512Mi" cpu: "100m" limits: memory: "1024Mi" cpu: "1024m" --- apiVersion: v1 kind: Service metadata: name: minha-app spec: selector: app: minha-app ports: - port: 8080 targetPort: 8080 type: ClusterIP
🚨 Importante:
- As annotations devem estar no
.spec.template.metadata.annotations
e isso que garante que o Prometheus descubra o Pod.
🚀 Realizando o Deploy da Aplicação
Fizemos alterações importantes na nossa aplicação Spring Boot e também no manifesto do Deployment, então agora é hora de aplicar tudo no cluster! 🛠️
Execute o comando abaixo para fazer o deploy:
kubectl apply -f deployment.yaml
🔍 Verificando se está tudo certo
Depois de aplicar o deploy, é importante conferir se tudo foi criado corretamente. Use os comandos abaixo:
kubectl get pods kubectl get svc kubectl get all
📈 Dashboards no Grafana: visualizando métricas e logs em tempo real
Agora que todas as configurações foram feitas e o deploy está pronto, é hora de colher os frutos!
Depois de acessar o Grafana, siga os passos abaixo para visualizar as métricas da sua aplicação e os logs em tempo real:
🔌 1. Verifique as conexões com as fontes de dados
Acesse o menu lateral e vá em Connections > Data Sources
✅ Certifique-se de que as seguintes fontes estão configuradas corretamente:
- Prometheus (para métricas)
- Loki (para logs)
📊 2. Importe os dashboards oficiais
- Vá em Dashboards → New → Import
- Insira o ID
17175
e clique em Load - Selecione o Data Source correto para Prometheus (métricas) e Loki (logs)
- Importe e curta o painel já pronto para uso!
Exemplo de dashboards muito utilizando pela comunidade e que estão no GrafanaLab:
Dashboard | ID | O que mostra |
---|---|---|
📄 Loki Logging Dashboard | 13639 | Logs em tempo real filtrados por aplicação, nível e mensagem |
📄 Loki Kubernetes Logs | 15141 | Logs coletados do Kubernetes e salvo no Loki |
🚀 Spring Boot 3.x Statistics | 19004 | Inclui gráficos de JVM, throughput, erros, tempos de resposta e muito mais |
🚀 Spring Boot Observability | 17175 | Métricas, logs e tracing |
🚀 Spring Boot & Endpoint Metrics 2.0 | 17053 | Quantidade de request de sucesso, erro, warning, spring data, entity, resilience retry, CPU e memória |
🚀🛢️ Spring Boot JDBC & HikariCP | 20729 | Métricas do pool: conexões ativas, espera, tempos de resposta, ótimo para diagnosticar gargalos de BD |
✅ Resultado
Com isso, você terá:
- 📈 Gráficos de requisições por segundo
- 🔥 Monitoramento de uso de memória e garbage collection
- 🧵 Informações de threads, status da aplicação, tempo de uptime
- 📄 Logs estruturados em tempo real com possibilidade de filtro e busca
🧑💻 Dica extra: Você pode customizar seus dashboards ou criar alertas diretamente no Grafana para ficar de olho na saúde da aplicação.
✅ Bora testar!
Agora vamos dar acesso a nossa aplicação através do port forward:
kubectl port-forward svc/minha-app 8090:8080 &
Gere carga na app com curl
:
for i in {1..30}; do curl http://localhost:8090/test; sleep 1; done
Veja os dados fluindo nos dashboards importados no Grafana:
http://localhost:3000
→ Painéis com métricas e logshttp://localhost:3000/explore
→ Navegue pelos logs com queries tipo:
📊 Criando gráficos personalizados no Grafana
Além dos dashboards prontos, você também pode montar visualizações personalizadas com base nas suas métricas expostas via Prometheus! Aqui vão dois exemplos úteis usando a URI /test
.
📈 Requisições por hora para /test
Essa métrica mostra quantas requisições com status 200 foram feitas para a rota /test
, por hora, ao longo do tempo:
increase(http_server_requests_seconds_count{ application="minha-app", uri="/test", status="200" }[1h])
💡 Dica: No painel do Grafana, defina o intervalo de tempo para as últimas 12h e ajuste a resolução para 1h para uma visualização mais clara da distribuição.
📊 Média de tempo das requisições para /test
Essa métrica calcula a média de tempo gasto nas requisições para a rota /test
:
sum by(uri)( http_server_requests_seconds_sum{ application="minha-app", uri="/test" } ) / sum by(uri)( http_server_requests_seconds_count{ application="minha-app" } )
📌 Essa divisão é possível porque o Micrometer (usado no Spring Boot) separa os valores somados dos tempos de resposta e o número de requisições, permitindo calcular médias facilmente.
🏁 Finalizando o BoraPraticar!
🎉 Parabéns por chegar até aqui! Se você seguiu todos os passos, agora tem uma aplicação Spring Boot monitorada com Prometheus, Grafana, Loki e Promtail, tudo rodando em um cluster K3d de forma prática e realista. 🚀
💬 Esperamos que esse Borapraticar tenha sido útil pra você entender melhor o ecossistema de observabilidade no Kubernetes.
Mas não pare por aqui!
👉 Continue sua jornada com a gente:
- Leia os outros tutoriais que publicamos no blog blog.setedevs.com.br
- Se inscreva no nosso canal no YouTube BoraPraticar e confira os vídeos explicativos que complementam esse conteúdo.
- Compartilhe com seus amigos que estão nesta caminhada de evolução com Kubernetes! 💡
Muito obrigado por acompanhar até o fim.
Nos vemos nos próximos Borapraticar! 👋
☕ Me paga um café?
Se curtiu o conteúdo e quer me dar aquela moral, escaneia aí e me paga um cafezinho pra eu continuar compartilhando conhecimento de forma leve e prática com você 😄
Valeu demais pela força! 🙌