Alura > Cursos de DevOps > Cursos de Confiabilidade > Conteúdos de Confiabilidade > Primeiras aulas do curso Observabilidade e métricas: instrumentação, dashboards e SLOs no Kubernetes

Observabilidade e métricas: instrumentação, dashboards e SLOs no Kubernetes

Fundamentos de Observabilidade Prática - Fundamentos e Instrumentação

Apresentando o curso e o instrutor

Olá! Bem-vindos ao curso de observabilidade na prática, do Zero ao Kubernetes com SLOs. Meu nome é Eric, e tenho mais de 18 anos de experiência na área, atuando como especialista em qualidade, SRE e observabilidade. Hoje, serei o instrutor nesta jornada de observabilidade.

Audiodescrição: Eric é um homem branco, com cabelo curto castanho e olhos castanhos. Ele veste uma camisa azul e está em um ambiente de escritório com uma parede clara ao fundo.

Introduzindo o cenário e os conceitos fundamentais

Neste curso, aprenderemos a instrumentar uma aplicação do zero, utilizando métricas e dashboards. Vamos migrar tudo isso para o Kubernetes, criando uma arquitetura em cloud com CICD automatizado e deploy automatizado. Além disso, dominaremos o SLA e o SLO em um cenário real.

O cenário que utilizaremos é o da empresa fictícia Fast Food Tech. Você acabou de ingressar na Fast Food Tech, no time de plataforma, e já enfrenta um desafio: o CEO está recebendo reclamações de que o aplicativo está lento, mas não temos dados para quantificar essa lentidão ou sua frequência. Nossa API é uma caixa preta, e nossa missão é transformá-la em um sistema observável. Vamos sair do escuro e tomar decisões baseadas em métricas e dados.

Explorando logs, métricas e traces

Antes de começarmos a prática, precisamos entender alguns conceitos fundamentais: logs, métricas e traces. Logs são como um diário de bordo detalhado, útil para identificar erros específicos. Eles registram tudo o que acontece na aplicação, sejam erros ou ações. No entanto, logs não são úteis para identificar tendências ou criar gráficos.

Para isso, utilizamos métricas, que funcionam como o painel de um carro, mostrando tendências numéricas e a saúde da aplicação. Focaremos bastante em métricas, pois elas são leves, baratas para armazenar e perfeitas para responder se o sistema está saudável.

Traces são o rastreamento de uma transação na aplicação, permitindo rastrear o caminho entre microserviços e o que acontece com uma determinada transação ou chamada.

Preparando o ambiente de desenvolvimento

Começaremos com métricas, pois elas respondem às nossas necessidades iniciais e são leves e baratas para armazenar. Agora, vamos colocar a mão na massa. No repositório da Fast Food Tech, há um README que explica como a aplicação foi construída, quais linguagens e tecnologias foram usadas. Inicialmente, trabalharemos localmente.

A API simples de pedidos do sistema Fast Food Tech foi construída em Node.js com Express e MySQL, rodando 100% localmente via Docker Compose. É importante conhecer a estrutura de pastas para saber onde está cada coisa. Vamos clonar o projeto e começar a trabalhar.

Configurando o Docker e clonando o projeto

Para isso, precisamos ter o Docker instalado. Uma alternativa ao Docker Desktop é o Rancher, uma ferramenta open source e gratuita. Ao rodar o comando docker --version, verificamos se o Docker está instalado.

docker --version

Voltando à aplicação, há endereços onde ela estará disponível para facilitar os testes. Vamos clonar o projeto, abrir a IDE de preferência e explorar a estrutura de pastas, como SRC, Controllers, e arquivos de configuração do Express.

git clone https://github.com/eamaral/fastfood-observability.git

Subindo a aplicação com Docker

Para subir a aplicação, utilizamos o Docker. O arquivo Dockerfile contém as etapas de execução, e o Docker Compose se comunica com ele. Detalhes como banco de dados, portas e API estão configurados lá.

Com o Docker instalado, rodamos o comando docker-compose up -d para colocar a aplicação no ar. Podemos usar o modo detached para continuar usando o terminal. Após subir a aplicação, verificamos nos endereços do README se ela está no ar.

docker-compose up -d

Testando a aplicação com Swagger

Acessamos o Swagger, uma documentação interativa que permite fazer requisições para as APIs sem usar o terminal ou ferramentas como Postman. Testamos a aplicação criando produtos, clientes e pedidos.

Ainda estamos no escuro, sem métricas para entender a aplicação, mas agora começaremos a instrumentá-la. Antes disso, precisamos garantir que o Node está instalado. No Mac, usamos brew install npm para instalar. Verificamos a instalação com node -v.

Instalando e configurando o Prometheus

Vamos instalar a biblioteca prom-client, que é o Prometheus. O Prometheus é um coletor que nos ajudará a coletar métricas. A página oficial das bibliotecas do Node mostra o que a biblioteca faz e como instalá-la.

Para instalar, utilizamos o comando npm install prom-client. Após a instalação, podemos verificar a presença da dependência no arquivo package.json. Em seguida, vamos criar um novo arquivo na pasta "src" para começar a codificar nossas métricas utilizando o prom-client.

Primeiro, importamos o prom-client com const client = require('prom-client').

const client = require('prom-client');

Coletando métricas padrão e personalizadas

Vamos começar coletando métricas padrão, como uso de CPU e memória, utilizando a função collectDefaultMetrics. Declaramos const collectDefaultMetrics = client.collectDefaultMetrics para coletar essas métricas do sistema.

const collectDefaultMetrics = client.collectDefaultMetrics;
collectDefaultMetrics();

Precisamos também contar os pedidos. Para isso, criamos uma constante const ordersTotal = new client.Counter com o nome fastfoodorders_total e um rótulo para o status do pedido. Isso nos permitirá filtrar as métricas posteriormente.

const ordersTotal = new client.Counter({
    name: 'orders_total',
    help: 'Total de pedidos',
    labelNames: ['status']
});

Outra métrica importante é o tempo de resposta da aplicação. Criamos um histograma para isso com const requestDuration = new client.Histogram, que nos ajudará a medir a performance da aplicação.

const httpRequestDuration = new client.Histogram({
    name: 'fastfood_http_request_duration_seconds',
    help: 'Tempo de duração das requisições HTTP',
    buckets: [0.1, 0.5, 1, 2, 5]
});

Integrando métricas ao servidor

Agora, vamos integrar essas métricas ao nosso servidor. No arquivo de servidor, importamos o register do prom-client e declaramos uma nova rota para expor as métricas. A rota /metrics será responsável por retornar as métricas coletadas.

app.get('/metrics', async (req, res) => {
    res.set('Content-Type', register.contentType);
    res.end(await register.metrics());
});

Para contar os pedidos, precisamos incrementar o contador ordersTotal após a criação de um pedido. Isso é feito com ordersTotal.inc({ status: 'CRIADO' }).

try {
    // ... (existing code)
    ordersTotal.inc({ status: 'CRIADO' });
    return res.status(201).json(pedidoCompleto);
} catch (error) {
    ordersTotal.inc({ status: 'ERRO' });
    return res.status(400).json({ error: error.message });
}

Concluindo a primeira aula

Por fim, discutimos a importância de evitar o uso de dados infinitos, como IDs, como rótulos nas métricas, pois isso pode causar uma explosão de cardinalidade e comprometer o desempenho do Prometheus.

Essa foi a nossa primeira aula. Nos encontramos na próxima aula. Até mais!

Fundamentos de Observabilidade Prática - Traduzindo métricas com Prometheus

Acessando a rota matrix e verificando a aplicação

Na nossa última aula, criamos a rota matrix, mas ainda não a acessamos. Precisamos fazer isso para verificar se o que implementamos está funcionando corretamente. Essa será a primeira ação que realizaremos agora.

Lembram-se da rota que criamos? Vamos prosseguir. Para que nossas alterações tenham efeito, precisamos executar o comando docker compose down e, em seguida, subir novamente o ambiente.

docker compose down

No entanto, não basta apenas subir novamente; é necessário executar docker compose up e reconstruir tudo. Vamos fazer isso e verificar o resultado.

docker compose up --build

O Swagger está disponível, o que indica que a aplicação subiu em algum lugar. Vamos verificar juntos. A aplicação está no ar, e vamos acessar a rota matrix. Temos aqui uma série de dados que mostram que o que fizemos funcionou. As métricas estão aparecendo de forma estática, ou seja, são exibidas ao vivo, mas permanecem nesse endereço. Precisamos de um sistema que colete essas informações periodicamente. É aí que entra o Prometheus.

Outro ponto a observar é que há uma grande quantidade de texto, o que dificulta a extração de informações visuais. Nossa aplicação está expondo os dados, mas precisamos de uma ferramenta, como o Prometheus, para coletá-los periodicamente.

Configurando o Prometheus para coleta de métricas

Vamos voltar ao código. Agora é o momento de pegar essas métricas, que estão sendo expostas de forma passiva, e fazer com que o Prometheus, de forma ativa, as colete. Isso é o que chamamos de pull e push, semelhante ao conceito do GitHub. O Prometheus segue o mesmo princípio.

No código, tudo está rodando. Precisamos criar o Prometheus para realizar essa tarefa. O que faremos primeiro? Vamos criar uma pasta chamada "Prometheus". Dentro dela, criaremos o arquivo prometheus.yaml.

Dentro desse arquivo, configuraremos o Prometheus. Na configuração global, a sugestão inicial é de 15 em 15 segundos, mas queremos que seja de 5 em 5 segundos.

global:
  scrape_interval: 15s

Vamos ajustar o intervalo de coleta para 5 segundos.

scrape_interval: 5s

Definiremos o scrap e o local onde ele será feito. Precisamos ajustar o endereço também. O MatrixPath está definido, então ele buscará em Matrix StaticConfig. O target não será o padrão; faremos a alteração necessária.

scrape_configs:
  - job_name: 'fastfood-observability'
    static_configs:
      - targets: ['localhost:3000']

Ajustando configurações do Docker Compose para o Prometheus

Essa é a primeira configuração do nosso Prometheus, mas ainda não está completa. Precisamos também informar ao Docker Compose o que deve ser feito. Já temos uma sugestão de configuração que precisa ser incluída.

Vamos criar o Prometheus. Ele já está sugerindo algumas configurações. Vamos verificar se estão corretas: FastFood, Observability, Prometheus. A porta que vamos utilizar é a 9090. No entanto, vou trocar essa informação, pois não gosto de subir nessa porta. Às vezes, ela já está em uso. Vou utilizar outra porta que normalmente está livre e garanto que funcionará. A 9090 também é uma opção, se preferirem, não há problema. É uma escolha pessoal.

prometheus:
    image: prom/prometheus:latest
    container_name: fastfood-observability-prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
    restart: unless-stopped

Vamos alterar a porta para evitar conflitos.

ports:
    - "9099:9090"

O volume deve ser exatamente como está escrito aqui. Há mais uma coisa que não está presente, que precisamos adicionar: o command. Ele sugeriu o config, mas não utilizo isso. Vamos usar aspas simples aqui também. Este é o command.

command: ['--config.file=/etc/prometheus/prometheus.yml']

Precisamos adicionar o depends_on também, que é o depends_on API.

depends_on:
    - api

Pronto, agora a configuração do nosso Prometheus está pronta dentro do nosso arquivo YAML do Docker Compose.

Reiniciando o ambiente e verificando o Prometheus

O que precisamos fazer novamente? A mesma coisa: se dermos um "Ctrl+C" aqui, ele interrompe os containers. Para mim também, mas é sempre bom executar um docker-compose down e um docker-compose up novamente. Vou fazer isso. Vamos lá, docker-compose up novamente. Ele vai iniciar novamente e então acessaremos o Prometheus na porta que configuramos.

docker-compose down
docker-compose up --build

Está no ar. Ele está indicando que a métrica também está ativa. Vamos acessar o Prometheus. Vamos acessar o localhost na porta 9099. Funcionou! Nosso Prometheus está no ar. O que podemos fazer aqui dentro? Que expressões podemos colocar? Uma das expressões que temos no nosso código está no arquivo metrics que criamos com esses nomes. Isso pode ser passado como expressão.

Por exemplo, ao digitar fastfood, ele já aparece, nem preciso digitar tudo. Ele já traz a métrica que criei. Vamos executar para ver o que acontece. Ele trouxe algo, mas ainda não há dados, pois não me lembro de ter criado nenhum pedido para ele contar. Mas o importante é que está funcionando, mesmo que ainda não seja o que queremos.

fastfood_orders_total

Por exemplo, se colocarmos app, conseguimos ver que a aplicação está no ar. Isso retorna um gráfico que mostra que está no ar. Podemos adicionar um track e outras coisas. Está configurado para uma hora, mas podemos ajustar para um minuto atrás. Ele indicará que está no ar, pois acabamos de subir.

up

Temos um gráfico, o Prometheus está ativo. Se fizermos um pedido no OrdersTotal, ele começará a aparecer na expressão do FastFoodOrdersTotal. Conseguiremos ver no gráfico. Precisamos aprender a debugar e veremos um handbook para isso na próxima aula. Primeira coisa, já conseguimos. Depois, veremos como debugar e criar um handbook.

Depuração e verificação de API - Runbook de Debug

Introduzindo a importância da depuração

Antes de continuarmos com a criação de gráficos, é importante saber como depurar quando um erro ocorre. Quais são as primeiras ações que devemos tomar? Qual a ordem que podemos seguir para resolver um problema?

Se o gráfico estiver vazio e não conseguirmos visualizar nada, devemos seguir um roteiro. Primeiramente, é necessário testar se a API está respondendo. Podemos testar a própria rota metrics, além de outra rota que será apresentada. Um erro comum que pode ocorrer está relacionado ao horário do servidor.

Verificando a atividade da API

Para verificar se a API está ativa, podemos usar o seguinte comando:

# 1. A API está viva?
curl http://localhost:3000/metrics

Vamos examinar o código e acessar a primeira rota. Temos uma rota health e o nosso swagger. O primeiro passo é iniciar a depuração por lá. Vamos acessar a documentação da API para verificar se ela está ativa. A API está no ar e respondeu com o código 200.

Podemos verificar a saúde da API com o seguinte comando:

curl -X 'GET' \
  'http://localhost:3000/health' \
  -H 'accept: */*'

Explorando a funcionalidade dos targets

O segundo passo, caso as métricas não estejam aparecendo, é acessar o endereço correspondente para verificar se o que foi feito até o momento está funcionando corretamente. Além disso, existe outro caminho que podemos verificar, que é o targets. O que o targets faz? Ele nos permite saber se o Prometheus consegue acessar a API. No exemplo apresentado, o Prometheus não está conseguindo encontrar a API.

Para verificar se o target está ativo, podemos acessar:

# Verifique em: http://localhost:9090/targets

Por que não está encontrando? Primeiro, porque não é essa porta. Lembramos que definimos 9099. O Prometheus, como mencionado anteriormente, é um coletor. Ele acessa a rota metrics e coleta dados a cada 5 segundos. Definimos isso em nosso código. A cada 5 segundos, ele realiza o scrap, que é o intervalo para coletar as métricas nesse caminho. Assim, sabemos que ele está conseguindo acessar e coletar os dados corretamente. Esse é o tipo de detalhe que devemos observar.

Configurando o Prometheus e verificando o horário

Aqui está a configuração do Prometheus para coletar as métricas:

global:
  scrape_interval: 5s

scrape_configs:
  - job_name: 'fastfood-observability'
    metrics_path: '/metrics'
    static_configs:
      - targets: ['api:3000']

Em relação ao horário no servidor, utilizamos frequentemente as configurações globais, como use local time, e também o horário do navegador. Como estamos em localhost, ele está utilizando o horário local, o que é compatível. Portanto, esse problema não ocorrerá aqui, mas é uma causa comum de gráficos pararem de aparecer. É importante estar atento a isso.

Para verificar se a hora está correta, podemos usar o comando:

# 3. A hora está certa?
date

Preparando para a visualização com o Grafana

Tudo está funcionando corretamente, e estamos prontos para avançar para a próxima etapa. A próxima etapa será a visualização com o Grafana, onde conectaremos o Prometheus a uma ferramenta ainda melhor. O Grafana permitirá que essas métricas sejam exibidas em gráficos, possibilitando um controle ainda mais eficaz. Nos vemos na próxima etapa.

Sobre o curso Observabilidade e métricas: instrumentação, dashboards e SLOs no Kubernetes

O curso Observabilidade e métricas: instrumentação, dashboards e SLOs no Kubernetes possui 222 minutos de vídeos, em um total de 69 atividades. Gostou? Conheça nossos outros cursos de Confiabilidade em DevOps, ou leia nossos artigos de DevOps.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Confiabilidade acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas