Alura > Cursos de DevOps > Cursos de Confiabilidade & SRE > Conteúdos de Confiabilidade & SRE > Primeiras aulas do curso Logs e Observabilidade: estratégias de coleta, análise e governança

Logs e Observabilidade: estratégias de coleta, análise e governança

Estratégias de coleta e gestão de logs - Apresentação

Apresentando o treinamento

Olá! Meu nome é Bruno, e vamos iniciar o treinamento sobre estratégias de coleta e gestão de logs (registros).

Neste treinamento, nós vamos abordar o que são os logs (registros) e sua estrutura, os níveis existentes, os tipos de logs (registros) — de servidor e de aplicação —, para que servem os logs (registros) e algumas ferramentas para coleta, centralização e análise ao longo do percurso.

Montando o laboratório e explorando observabilidade

Nesta aula, nós vamos apresentar as introduções, o conceito e a teoria, abordar os tipos de log level (níveis de log) e montar um ambiente de laboratório com VirtualBox. Vamos levantar uma máquina com Windows e outra com Linux atuando como servidores, e ambas irão enviar seus logs para um servidor de logs. Nesse servidor, implementaremos um cluster (agrupamento) do Elasticsearch, composto por Elasticsearch, Logstash e Kibana.

Também faremos testes com Fluent Bit no lugar do Logstash e montaremos um stack (pilha) com Grafana, Loki e Prometheus. Em seguida, veremos OpenTelemetry com Loki e Grafana, com OpenTelemetry substituindo o Prometheus, focando a parte de observabilidade e pensando na coleta de métricas e rastros no futuro. Além disso, analisaremos as três dimensões da observabilidade — métricas, rastros e logs — e como estruturamos essa arquitetura.

Abordando governança de dados e conteúdo extra

Exploraremos a anonimização e a governança de dados, com atenção à LGPD, discutindo como mascarar e anonimizar informações sensíveis dentro dos logs.

Como conteúdo extra ao final, vamos instrumentar logs para Splunk, Datadog, Dynatrace e New Relic. Faremos a exportação dos logs dos nossos servidores para essas ferramentas e analisaremos como cada uma delas interpreta esses registros.

Estratégias de coleta e gestão de logs - Introduzindo os fundamentos de logs

Apresentando o instrutor e iniciando o treinamento

Olá, pessoal. Tudo bem? Hoje vamos iniciar o treinamento de estratégias de coleta e gestão de logs. Veremos desde o Syslog, a origem dos logs e seus fundamentos — o que são e para que servem — até a parte mais sofisticada que complementa a observabilidade, tema bastante discutido no mundo de SRE (Engenharia de Confiabilidade de Sites) e DevOps (Desenvolvimento e Operações).

Eu vou começar me apresentando. Meu nome é Bruno Cavalcante. Tenho 34 anos, trabalho com TI desde os 16, em suporte naquela época. Hoje trabalho como arquiteto de infraestrutura. Nesse percurso, obtive algumas certificações: Architect Professional da AWS, CKA, Terraform Associate, LPI1 e CompTIA Linux+. Trabalho com nuvem, como SRE especificamente, desde 2020. Na tela estão meu LinkedIn e meu e-mail para contato. Podem enviar qualquer dúvida por lá e nós daremos a maior atenção possível.

A primeira aula será a introdução aos logs. Aqui falaremos sobre o que são, quais tipos existem e para que servem. Também veremos alguns exemplos de logs para começarmos a nos familiarizar com esse formato e entender o que podemos fazer com eles ao longo do curso.

Definindo logs e introduzindo a aula

Aula 1: Introdução aos logs

O que são logs e para que servem? Uma analogia útil é a caixa-preta de um avião. De forma literal, “logs de dados” referem-se ao registro de eventos de sistemas computacionais. São eventos registrados de forma cronológica, com a premissa de imutabilidade: a linha de log não deve ser modificada, assim como o arquivo de log não deve ser alterado. Eles existem para registrar momentos do comportamento do sistema, considerando o tempo e o evento. A caixa-preta do avião pode ser comparada ao Syslog do avião: ela guarda todo o log do sistema da aeronave, registrando tudo o que acontece, tanto no aspecto de segurança quanto em eventos de falha.

Vamos abordar alguns pilares da observabilidade e, em seguida, os tipos de logs: logs de sistema e logs de aplicação. São dois tipos diferentes, que trazem informações distintas em cada um. Também veremos exemplos visuais de logs tratados e não tratados.

Detalhando componentes de logs e tratando conformidade

Em uma linha de log, encontramos a data, o nível do log (se foi um erro, uma informação, um aviso ou uma criticidade) — isso aparece de forma explícita — e a mensagem de log em si. Na mensagem de log, há outras informações. Por exemplo, em um log de auditoria de um serviço SSH, teremos o endereço de origem que tentou se conectar, se a conexão foi bem-sucedida ou não, o usuário que tentou se conectar, o IP de destino, o IP de origem, o momento em que a sessão foi encerrada e, a partir do registro de entrada e de saída, conseguimos inferir por quanto tempo aquela pessoa ficou autenticada. Vamos observar isso e identificar informações relevantes para o dia a dia. Também falaremos sobre LGPD e sobre Governança/Compliance (conformidade).

Como mencionamos, a parte de rastreabilidade e auditoria responde a duas perguntas fundamentais: quem executou e quando executou. Isso é muito importante. É o que utilizam a Polícia Federal e a perícia forense, principalmente, mas todas as empresas se beneficiam desse tipo de ação. Por exemplo, a equipe de segurança, ao olhar um log de tentativa de intrusão, verifica quem tentou invadir, qual foi o IP de origem, em que momento ocorreu a tentativa e se a invasão foi bem-sucedida ou não.

Diagnóstico de erros e depuração também se baseiam em logs. Como dissemos, o log registra eventos do sistema. Podemos configurar o nível de detalhamento — mais ou menos detalhado — e, a partir dos logs, identificar se o sistema apresenta problemas, quais problemas são e, então, buscar uma solução objetiva com base no que foi registrado. A parte de observabilidade e monitoramento de desempenho também pode ser vista em logs. Por exemplo, no mercado temos servidores web como Nginx e Apache HTTP Server. Os logs dessas aplicações, por servirem sites e aplicações web, registram eventos de acordo com as solicitações dos clientes pelo protocolo HTTP (e TCP; falaremos disso depois). Assim, conseguimos identificar quanto tempo uma solicitação demorou para ser respondida, como está o throughput (vazão), quanto de dados foi transferido naquela solicitação, o tamanho dos arquivos baixados, como foi o acesso (se foi HTTP, se foi autenticado ou não) e outras informações.

Explorando exemplos de logs estruturados em json

Exemplo de logs estruturados: vamos observar uma tela e identificar informações-chave que ajudariam diferentes equipes. Pensando no time de segurança: ao olhar o log, vemos que, em 1º de abril de 2026, ocorreu um log de erro na aplicação com uma tentativa de autenticação que falhou. Alguém informou um e-mail e senha, mas a senha estava incorreta, conforme a mensagem de log na linha 4. Também aparece qual foi o usuário que tentou se autenticar: “admin master”. O time de segurança verificaria se esse usuário existe. Se existir, provavelmente alguém externo já tem acesso ao identificador desse usuário e está tentando um ataque de brute force (força bruta).

Para tangibilizar esse exemplo, veja um log estruturado em JSON que reflete exatamente o cenário descrito (com campos claros e pesquisáveis):

{
  "timestamp": "2024-04-01T13:20:15.123Z",
  "level": "ERROR",
  "event_type": "auth_failure",
  "message": "Login attempt failed: Invalid password",
  "user": {
    "username": "admin_master",
    "email_masked": "c***s.s***a@gmail.com",
    "id": 10592
  },
  "network": {
    "client_ip": "172.16.254.1",
    "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)..."
  },
  "metadata": {
    "attempt_count": 3,
    "service": "auth-manager",
    "trace_id": "req-999-0022"
  }
}

Esse JSON evidencia campos como timestamp, nível, mensagem, usuário (com e-mail mascarado), IP de origem e metadados (contagem de tentativas, serviço e trace_id), facilitando buscas por chave e valor.

A informação de e-mail mascarada é uma configuração que veremos mais adiante, na parte de Governança/Compliance (conformidade), olhando para segurança da informação com a LGPD. Podemos mascarar informações em logs como medida de conformidade para evitar que qualquer pessoa com acesso aos registros visualize dados sensíveis, muitas vezes de clientes. Nesse exemplo, temos o ID do log, a origem da solicitação, “client IP 172.16.254.1”. Trata-se do IP do cliente, e, por ser um IP privado, provavelmente foi uma tentativa de acesso interno. O time de segurança então avalia: esse usuário existe? O evento se repete? A pessoa pode apenas ter digitado a senha errada uma vez, mas, se houver uma anomalia — 100 ou 200 tentativas repetidas nesse formato — identificamos um possível ataque de intrusão. Existem parâmetros de segurança nos sistemas, como bloquear o acesso por 10 minutos após 4 falhas de senha ou bloquear o usuário, exigindo contato com a administração. Essas decisões derivam exatamente desse tipo de informação que chega ao sistema.

Abaixo, aparecem metadados mostrando como isso ocorreu: por exemplo, o evento aconteceu 3 vezes pelo AuthManager e ficou registrado um trace (rastreamento). O que é esse trace? Ele registrou o endereço de referência para esse tipo de log; com ele, conseguimos rastrear todas as referências daquela informação a partir do ID de trace (rastreamento) indicado na última linha. O erro ocorreu 3 vezes; se não voltar a acontecer, pode ser que a pessoa tenha errado a senha 3 vezes. Se continuar, é preciso avaliar o que está acontecendo. O ponto importante é que o registro está em formato de JSON (formato de dados estruturados), muito bem estruturado, e podemos fazer buscas por chave e valor com facilidade. O JSON trabalha com chave e valor de forma estruturada: tudo o que vem antes de “:” é uma chave; tudo o que vem depois é o valor dessa chave. Se filtrarmos pelo timestamp, obteremos o valor correspondente. Se filtrarmos pelo level do log, obteremos o nível correspondente. Isso será muito importante quando tratarmos esses dados mais adiante. Podemos aplicar esses filtros e extrair logs de forma muito otimizada.

Contrastando com logs não estruturados e parsing

Exemplos de logs não estruturados: aqui estamos olhando um log semelhante ao anterior — o mesmo usuário, o mesmo IP de origem, a senha inválida e o mesmo número de tentativas —, porém em formato não estruturado. O que isso significa? Que não conseguimos aplicar os mesmos filtros do exemplo anterior, pois não há delimitação explícita de chave e valor; é um bloco de texto puro, no qual não conseguimos filtrar com facilidade. Existem formas de tratar esse texto; veremos como aplicar filtros a partir de texto usando Grok mais adiante. O importante é notar que aparecem o datetime, o level do log (que foi “severe”), a falha na tentativa do usuário, a mensagem de erro, o usuário que tentou se autenticar, e o e-mail não está ofuscado. Nesse formato, alguém com acesso ao log veria o e-mail de quem tentou se autenticar, já que essa informação foi enviada no momento do login (autenticação). Aparecem a origem e o erro de senha inválida. Não há ID de trace (rastreamento) porque não estamos referenciando nem processando a mensagem; é um texto no estilo “.txt” com a linha do evento. O processamento em larga escala fica mais trabalhoso, embora ainda seja possível.

Para contrastar com o JSON anterior, segue um exemplo de log não estruturado (texto livre):

[2024-04-01 13:20:15] SEVERE: Falha na tentativa de login do usuário "admin_master" (email: carlos.silva@gmail.com) vindo do IP 172.16.254.1. Erro: senha inválida. Tentativa número 3. User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)...

Note que, por não haver chaves explícitas, a filtragem exige parsing adicional (por exemplo, Grok) para extrair campos como timestamp, nível, usuário e IP.

Reforçando conceitos e apresentando os pilares da observabilidade

Retomando: o que são logs e para que servem? Em computação, logs são eventos cronológicos de sistemas computacionais. Não importa se o nível é erro, info (informação), warning (aviso), critical (crítico) ou debug (depuração): todos são logs. Registramos os eventos de forma cronológica, tanto do sistema quanto das aplicações. A partir deles, trabalhamos conformidade, troubleshooting, segurança e observabilidade. Os exemplos visuais de logs estruturados e não estruturados mostram que podemos formatar o log conforme a nossa conveniência: tratar de forma não estruturada exige mais trabalho das ferramentas de logs, enquanto, com uma ferramenta de coleta como o Logstash, podemos processar o log antes de ele chegar ao servidor de logs.

Quais são os três pilares da observabilidade? Temos:

Ilustrando eventos suspeitos com contexto de segurança

Exemplo de um evento discreto com contexto detalhado: temos um evento com métrica e log. Entre as informações, há um IP de contexto mascarado (185.156.xx), indicando que a conexão veio da Rússia, e o dispositivo utilizado foi um Tor Browser (navegador Tor), priorizando anonimato. Trata-se de uma solicitação muito suspeita. Conseguimos captar essas informações a partir da estrutura do log e também levantar métricas: quantas vezes essa origem acessou o servidor, quantas vezes esse usuário iniciou sessão, quantos bloqueios ocorreram, quantas tentativas de autenticação foram realizadas. Esse é um evento tratado do qual extraímos diversas informações.

Para exemplificar esse “evento discreto” com contexto rico, veja este registro estruturado:

{
  "at": "2024-04-01T14:05:01Z",
  "event": "login_attempt",
  "status": "blocked",
  "user": "admin_01",
  "ctx": {
    "ip": "185.156.X.X",
    "geo": "RU",
    "device": "Tor Browser/Linux",
    "reason": "suspicious_location"
  }
}

Observe como os campos de contexto (geo, device, reason) permitem análises rápidas de risco e agregações métricas por origem, dispositivo e motivo de bloqueio.

Apresentando métricas http e uso de memória

Exemplo de métricas: já explicamos o que é uma métrica. Agora, vejamos um evento de métrica em coleta. Suponhamos que temos um campo (field) HTTP request total. O que está sendo somado? O método é POST (em HTTP temos métodos como OPTIONS, POST, PUT, GET), o endpoint é /login e o código de status é 200. Quantas solicitações devolveram 200 para /login? Foram 4.502 solicitações. Assim, vemos quantas solicitações foram bem-sucedidas. Também podemos observar quantas resultaram em “não autorizado” (código 401). Esses códigos são o padrão do protocolo HTTP: 401 (não autorizado), 404 (não encontrado), 403 (acesso negado), 502 (bad gateway), 504 (gateway timeout), 301 (redirecionamento permanente), 302 (redirecionamento temporário). Como sabemos que 200, 204 e, em geral, os 2xx indicam sucesso (sem redirecionamento e sem erro), contamos quantas solicitações deram certo e quantas não deram.

Aqui está um exemplo em formato de exposição do Prometheus com essas métricas, incluindo também uso de memória do sistema:

# HELP http_requests_total Contador total de requisições HTTP
# TYPE http_requests_total counter
http_requests_total{method="POST", endpoint="/login", status="200"} 4502
http_requests_total{method="POST", endpoint="/login", status="401"} 125

# HELP system_memory_usage_bytes Uso atual de memória RAM
# TYPE system_memory_usage_bytes gauge
system_memory_usage_bytes{server="server-prod-01"} 1073741824

Com esse formato, conseguimos calcular taxas, criar alertas por status code e acompanhar consumo de memória ao longo do tempo.

Aqui abaixo também temos um exemplo do System Memory Usage Bytes.

Métricas de memória e exemplo de rastreamento

Este é outro campo. Como citamos, podemos monitorar quanta memória está sendo consumida pelo sistema. Aqui temos o valor em bytes; para converter para megabytes, dividimos por 1024, e novamente por 1024 para chegar a gigabytes.

Vamos continuar.

Demonstrando rastreamento e correlação de spans entre serviços

Aqui temos um exemplo de trace (rastreamento). Vemos o trace ID (identificador de rastreamento), que estava no primeiro exemplo de log (registro) tratado. Por meio desse trace ID, correlacionamos as solicitações feitas a partir da primeira requisição. A ferramenta que coleta esse trace etiqueta tudo com o trace ID. Quando os dados chegam ao servidor de logs (registros) e de observabilidade, conseguimos vincular todo o rastreamento de solicitações a partir da primeira.

Para visualizar o encadeamento de serviços e o ponto de falha (o Redis, neste caso), considere o trace abaixo:

{
  "trace_id": "tr-8821",
  "spans": [
    {"service": "api", "op": "get_profile", "status": "ok"},
    {"service": "redis", "op": "get_cache", "status": "error", "msg": "timeout"},
    {"service": "postgres", "op": "select_user", "status": "ok"}
  ]
}

O trace mostra a primeira chamada na API concluída com sucesso, um erro de timeout ao consultar o Redis e, em seguida, a aplicação indo ao Postgres para recuperar os dados com sucesso — exatamente o fluxo que utilizamos para diagnosticar a degradação no tempo de resposta.

No trace, temos um span (bloco), que é esse bloco de solicitações. Qual foi o serviço? Recebemos a primeira solicitação proveniente de uma API. A operação foi GetProfile, e o status resultou em OK. Essa solicitação foi concluída como esperado.

Essa API provavelmente precisou do Redis. A segunda solicitação foi ao Redis. A operação foi GetCached, para verificar se já havia algo em cache (cache) relacionado à seção superior do perfil, e o status foi um erro: ocorreu um timeout (tempo limite) no Redis. Ao receber esse erro do cache (cache), sem resposta do cache (cache), a aplicação (a API) foi diretamente ao banco de dados buscar a informação necessária. Então, acessou o serviço Postgres, executou a operação SelectUser do perfil, e o status resultou em OK.

Para a pessoa usuária, essa solicitação foi OK. Porém, para nós, que gerimos o sistema, ficou evidente que o Redis apresentou algum problema. Precisamos analisar por que houve problema no Redis, por que ocorreu timeout (tempo limite), por que não respondeu, e por que não possuía o dado. Esse timeout (tempo limite) afetou o tempo de resposta para a pessoa usuária final. Como havia um Redis no meio e ele gerou timeout (tempo limite), precisamos verificar qual é o tempo configurado de timeout (tempo limite) no Redis, pois esse tempo foi somado ao tempo total da solicitação até que a informação retornasse ao cliente.

Isso é um trace (rastreamento): conseguimos acompanhar todo o percurso da solicitação até encontrar o ponto de falha, que, neste caso, foi o Redis.

Classificando tipos de logs e discutindo desafios modernos

Tipos de logs e desafios modernos

Temos traces (rastreamentos), métricas e logs (registros), além do que chamamos de APM, isto é, Application Performance Monitoring (monitoramento de desempenho de aplicações). O APM funciona com todas essas informações de forma unificada. Coletamos tudo isso, relacionamos informações provenientes de lugares distintos — banco de dados, Redis, sistema — e chegamos a uma conclusão muito mais otimizada do que se observássemos apenas o log (registro). O log (registro) entrega muita informação, mas, quando o combinamos com outros sistemas, o resultado se torna muito mais valioso para quem está avaliando a situação.

Quais são os tipos de logs (registros) que temos?

Agora, vejamos os desafios modernos:

Listando ecossistemas e ferramentas de observabilidade

Ecossistemas e ferramentas que veremos

Veremos alguns ecossistemas:

Descrevendo o framework de logs e principais fontes

Trazemos informações sobre como funcionaria esse framework (estrutura) de logs (registros). Teremos logs (registros) do sistema, de processos, de auditoria, de contêiner, de aplicações, de rede e de segurança — tudo no mesmo lugar. Precisamos identificar cada tipo, entender seu conteúdo e as informações que trazem, como citamos:

Avaliando gestão de logs e critérios de escolha de plataformas

Gestão de logs: volume, efemeridade e formatos

Como já conversamos, o volume é extenso; lidar com grandes volumes de dados é crucial, tanto para receber quanto para armazenar. Há a efemeridade dos ambientes, então precisamos de ferramentas compatíveis com esse cenário. Quanto à variedade de formatos, precisamos padronizar, pelo menos para as aplicações que as equipes desenvolvem.

As ferramentas de monitoramento variam de enfoques específicos a plataformas integradas. O que isso significa? Precisamos decidir o que vamos usar em nosso ambiente e qual problema queremos resolver:

Planejando o laboratório prático e topologia do ambiente

Prática: Lab e topologia

Vamos falar da prática que faremos: o Lab (laboratório) e a topologia que vamos montar.

O que vamos montar neste Lab (laboratório)?

A topologia geral incluirá esses componentes. Primeiro, levantaremos o servidor de logs (registros) e iniciaremos um desses servidores para realizar o encaminhamento do log (registro) diretamente ao Graylog. Iniciaremos um deles e continuaremos com essa estrutura ao longo do treinamento, subindo as outras máquinas e configurando as demais comunicações.

Inicialmente, vamos observar os logs (registros): veremos o Syslog, acompanharemos a chegada das mensagens, entenderemos o que é auditoria e o que é sistema. Em seguida, enviaremos esses logs (registros) ao Graylog, verificaremos como chegam lá e, a partir disso, evoluiremos nossa estrutura.

[♪]

Estratégias de coleta e gestão de logs - Configurando o ambiente de virtualização

Iniciando a criação do ambiente

Vamos iniciar a criação do nosso ambiente. Nós o desenvolveremos conforme o avanço das aulas e, ao final, teremos todo o ambiente pronto. Não executaremos as duas ferramentas ao mesmo tempo. Primeiro, testaremos o Graylog para observar seu funcionamento. Em seguida, trabalharemos com a stack (pilha) ELK e, depois, com a stack (pilha) do Grafana, utilizando o Loki e o Alloy.

Uma informação importante: o Promtail foi descontinuado em 26 de março. O Promtail era a ferramenta responsável por enviar dados ao Loki. O Loki armazena esses logs e os exibe no painel do Grafana (dashboard — painel). Vamos conhecer a nova ferramenta que realiza esse envio ao Loki.

Primeiro, vamos criar o servidor LogServer. Quanto à rede, vamos ignorar a configuração visível agora, pois será utilizado outro endereço IP, o da nossa rede atual. Os recursos também serão ajustados para menos, já que se trata apenas de um laboratório: não será necessário utilizar 4 GB de RAM; utilizaremos menos memória.

Instalando o VirtualBox e baixando o Ubuntu

Agora, vamos baixar o Ubuntu 22 e realizar a instalação. Sairemos do slide para acessar a página do VirtualBox: virtualbox.org/wiki/Downloads. Também é possível pesquisar no Google por “download (baixar) VirtualBox” para chegar a essa página. Vamos baixar para Windows, pois estamos utilizando Windows no momento. Abriremos o instalador. Com o instalador aberto, avançaremos, aceitaremos os termos de licença e seguiremos sem alterar as opções padrão. Confirmaremos com “Yes”. Marcaremos a opção de adicionar ao Menu Iniciar. Não criaremos um ícone na Área de Trabalho, pois preferimos mantê-la sem ícones. Manteremos a opção de iniciar por padrão quando um arquivo .ovf for aberto, o que é interessante quando baixarmos uma imagem pronta no formato reconhecido pelo VirtualBox, pois a configuração da máquina virtual será iniciada automaticamente. No nosso caso, utilizaremos uma imagem .iso comum, então seguiremos com a instalação.

Enquanto a instalação ocorre, podemos já pesquisar no Google por “download (baixar) Ubuntu Server 22.04”. Essa será a versão que testaremos. É uma LTS com cinco anos de suporte, válida até 2027. Vamos baixar a 22.04. Em “Alternative Downloads” e “Previous Release”, é possível acessar a 22.04 LTS. Iniciaremos o download (baixa). O arquivo tem aproximadamente 2 GB, e o download (baixa) não deve demorar muito, cerca de 5 minutos.

Enquanto isso, voltaremos ao VirtualBox e concluiremos a instalação. O VirtualBox será iniciado para analisarmos seus recursos. Faremos uma visão geral de como funciona essa ferramenta de virtualização de sistemas operacionais e de máquinas.

Explorando as opções do VirtualBox

Na tela inicial, ao clicar em “Novo”, criaremos uma nova máquina virtual. Informaremos o nome da VM e selecionaremos o diretório onde a máquina virtual será criada (o arquivo correspondente à VM). Depois, poderemos abrir esse diretório para verificar como os arquivos ficam organizados. Selecionaremos a imagem que estamos baixando (uma imagem .iso; reparem na extensão .iso). Assim que o download (baixa) terminar, poderemos selecioná-la. Escolheremos o tipo do sistema: Linux, distribuição Ubuntu, para que o VirtualBox identifique corretamente os modos de instalação da imagem. Uma imagem .iso é um pacote com arquivos de instalação.

Podemos continuar, mas como nenhuma imagem .iso foi selecionada ainda, vamos cancelar para ver outras opções. Em “Abrir”, selecionaríamos um arquivo .ovf ou .ova, isto é, uma imagem já pronta em formato de virtualizador. Em “Preferências”, podemos configurar o ambiente de virtualização: alterar o idioma, ajustar configurações de exibição e modificar o diretório padrão de armazenamento das VMs. Vamos verificar rapidamente o armazenamento: temos cerca de 57 GB livres, então manteremos esse diretório. Há configurações avançadas de entrada, incluindo a possibilidade de habilitar USB nos dispositivos de conexão (mostraremos isso mais adiante). Também podemos importar e exportar: ao abrir um arquivo, selecionamos o tipo de arquivo aceito para importação direta; após a criação de uma VM, podemos exportá-la, gerando um arquivo em formato de virtualizador para utilizá-lo em outros locais, em outros virtualizadores ou em outras máquinas. Assim, a VM sai pronta para simplesmente ligarmos e utilizarmos em outros hipervisores (hypervisors — hipervisores).

Na seção de extensões, instalaremos os pacotes necessários. Será preciso baixar as extensões para habilitar reconhecimento de controladores (drivers — controladores) e outros recursos. Em “Mídias”, podemos carregar a partir de um meio e simular um dispositivo. Por exemplo, se tivermos uma imagem .iso e quisermos montá-la, adicionaremos a mídia e a montaremos como se fosse um leitor de disco (CD/DVD) ou uma unidade USB. Essa mídia ficará armazenada e poderá ser anexada a qualquer sistema operacional convidado, permitindo que a máquina virtual leia esse conteúdo.

Configurando redes e avaliando recursos

Na parte de rede, ao instalar o VirtualBox na máquina, ele cria uma interface de rede e define um IP virtual. Essa interface não está vinculada a nenhuma interface física. Se abrirmos o PowerShell e executarmos o comando ipconfig, veremos a rede física (a placa Wi‑Fi da máquina), que possui o endereçamento IP da rede residencial, além das redes virtualizadas: a do WSL do próprio Windows e o adaptador do VirtualBox, que cria a rede virtual. Reconhecemos essa rede pelo intervalo exibido na própria interface do VirtualBox. Podemos criar outras interfaces, como uma HostOnlyNetworkInterface, que criará uma nova interface de rede. Ao criar, passamos a ter, por exemplo, as redes 192.168.5.1 e 192.168.59.1. É possível ver as propriedades de cada uma, realizar alterações, configurar o adaptador automaticamente ou manualmente, conforme a necessidade de conexão com recursos externos.

Para verificar isso no Windows, execute o comando a seguir no PowerShell:

ipconfig

Esse comando lista as interfaces físicas e virtuais, incluindo a criada pelo VirtualBox, permitindo validar endereços IP e faixas de rede utilizadas.

Em “Recursos”, observamos a utilização atual do sistema operacional em termos de CPU, memória e discos, lembrando que a VM compartilha os recursos com o sistema operacional da máquina física; ela não adiciona novos recursos, apenas utiliza os já disponíveis.

Criando a máquina virtual LogServer

Com o download (baixa) concluído, clicaremos em “Novo”. Definiremos o nome da máquina, por exemplo, “log server”. A VM ficará no diretório já configurado. Agora, selecionaremos a imagem .iso na pasta “Downloads” — o VirtualBox já a reconhece pelo formato. Em “OS edition”, manteremos Linux; o VirtualBox identificou Ubuntu para nós (exibiu 22.10 neste caso, embora tenhamos baixado a 22.04; isso não é relevante agora). Prosseguiremos. Se o assistente reclamar do nome, pode aparecer a mensagem “Hostname must be at least two alphanumeric characters”. Ajustaremos o nome para atender a essa exigência, removendo caracteres inválidos e deixando um nome válido para a máquina virtual.

Definiremos credenciais: usuário “virtualbox user” e senha “123456”, confirmando a senha. Essa será a senha do sistema operacional convidado. Finalizaremos a criação. Ao concluir, a VM será iniciada e a instalação da imagem .iso começará. Aguardaremos o término. Enquanto isso, já podemos observar como ficou a configuração: memória principal em 2 GB, algo que pode ser alterado (mais adiante mostraremos onde fazer isso). A máquina está inicializando para realizar a instalação. Depois, reduziremos esses recursos, pois não é necessário tanto neste momento.

Para quem estiver criando agora e desejar ajustar os recursos, é possível desligar a VM, acessar “Configurações” e, em “Sistema”, alterar a quantidade de memória e CPU. A VM precisa estar desligada para permitir a edição desses recursos. Podemos, por exemplo, reduzir para 1 CPU e 1 GB de RAM inicialmente. Neste momento, deixaremos a inicialização concluir. A partir daqui, seguiremos o processo de instalação de um sistema operacional desde o início.

Inicializando o Ubuntu Server e ajustando a rede

Não se trata de uma OVA ou OVF já configurada. Vamos realizar a configuração do zero. Inicializaremos o Ubuntu Server 22.04. No nosso ambiente, o sistema já inicia diretamente. Vamos acessar com o usuário VBox User e a senha 123456, que configuramos. O Cloud-Init está executando toda a etapa de inicialização do sistema operacional.

Esta é a interface de rede da máquina virtual: enp0s3. Quando a inicialização terminar, vamos desligar a máquina virtual, abrir as configurações, reduzir a memória (como planejado) e configurar a rede. Em Rede, vamos alterar de NAT para Bridge (modo ponte). Colocaremos a placa em modo Bridge para que a máquina virtual suba na mesma rede da nossa residência, obtenha um endereço IP via a mesma infraestrutura de rede do computador hospedeiro e permita comunicação direta, sem necessidade de túneis. O NAT cria um túnel e faz um arranjo para que nos conectemos à máquina; em Bridge, não. Em modo ponte, conectamo-nos diretamente à máquina virtual, sem esses subterfúgios, operando diretamente na camada 2, pois estamos na mesma rede da máquina virtual.

Aplicaremos o modo Bridge e confirmaremos com OK, já que o sistema permitiu. A memória ainda não pode ser ajustada neste momento, então manteremos como está. Observamos que a interface é Wi‑Fi; se houver mais de uma, devemos selecionar a interface adequada. Confirmaremos com OK.

Na tela inicial, ainda não é exibida a informação de IP. Não há expansão dessa área na interface. Obteremos o endereço IP assim que a máquina estiver disponível para acesso. O Cloud-Init continua em execução.

Observando os recursos da VM

Na interface, na parte inferior, conseguimos ver todos os recursos dessa máquina virtual:

Veremos todos esses itens em breve, quando a inicialização terminar. Faremos os ajustes necessários. Enquanto isso, vamos adiantar a preparação do ambiente.

Introduzindo o uso de IA no laboratório

Ao final do treinamento, teremos algumas aulas específicas sobre como utilizar a IA para nos apoiar no depurador de problemas, analisando logs e na tomada de decisões. Para que já nos acostumemos a solicitar informações à IA, especialmente no que diz respeito à criação de arquivos para nós — algo que poderíamos fazer manualmente, mas não é necessário — abriremos qualquer IA disponível. Pode ser o ChatGPT ou o Gemini. Neste caso, abriremos o Gemini.

No Gemini, informaremos o seguinte: estamos levantando um Ubuntu Server 22.04 e queremos subir o Graylog. Primeiro, vamos mostrar os logs gerados na parte de SSH e na parte de auditoria de segurança; depois, instalaremos o Docker, subiremos o Graylog e começaremos a levantar outras máquinas para enviar os logs ao Graylog. Esse será nosso primeiro laboratório.

Como exemplo prático, queremos subir o Graylog e precisamos de um Docker Compose completo, com persistência de dados e autenticação configurada. Ao enviar essa solicitação, a IA entende que vamos levantar um servidor Graylog em Docker, pois indicamos que queremos um arquivo de Docker Compose. A IA retorna as informações necessárias e propõe a estrutura do Docker Compose.

Detalhando a proposta de Docker Compose

A proposta inclui a seção services:

Vamos materializar essa proposta no arquivo docker-compose.yml, adicionando os serviços de forma progressiva. Começamos pela base de dados do Graylog, o MongoDB, já declarando a versão do Compose conforme retornado pela IA e a seção de serviços:

version: "3.8"

services:
  # MongoDB: Armazena configurações e metadados
  mongodb:
    image: "mongo:5.0"
    volumes:
      - "mongodb_data:/data/db"
    restart: "always"

Esse bloco define o serviço do MongoDB, com volume persistente mapeado para /data/db e política de reinício para garantir disponibilidade.

Adicionando o OpenSearch ao Compose

Em seguida, adicionamos o OpenSearch, que fará a indexação:

  # OpenSearch: O motor de busca (sucessor do Elasticsearch)
  opensearch:
    image: "opensearchproject/opensearch:2.4.0"
    environment:
      - "node.name=opensearch"
      - "cluster.name=graylog"
      - "discovery.type=single-node"
      - "bootstrap.memory_lock=true"
      - "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g"
      - "action.auto_create_index=false"
      - "plugins.security.ssl.http.enabled=false"
      - "plugins.security.disabled=true"
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536
    volumes:
      - "os_data:/usr/share/opensearch/data"
    restart: "always"

Note que configuramos o OpenSearch em modo single-node, ajustamos limites de memória/arquivos e mapeamos um volume para os dados de índice.

Configurando o serviço Graylog no Compose

Por fim, adicionamos o serviço principal do Graylog, com dependências explícitas, entrypoint aguardando o OpenSearch e variáveis de ambiente essenciais, além das portas de entrada para os protocolos mais comuns:

  # Graylog: A aplicação principal
  graylog:
    image: "graylog/graylog:5.0"
    depends_on:
      mongodb:
        condition: "service_started"
      opensearch:
        condition: "service_started"
    entrypoint: /usr/bin/tini -- wait-for-it opensearch:9200 --  /docker-entrypoint.sh
    environment:
      # Senha do usuário admin (admin)
      # IMPORTANTE: Altere este valor para um hash SHA-256 da sua senha
      - "GRAYLOG_PASSWORD_SECRET=somepasswordpepper"
      - "GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918"
      - "GRAYLOG_HTTP_BIND_ADDRESS=0.0.0.0:9000"
      - "GRAYLOG_HTTP_EXTERNAL_URI=http://127.0.0.1:9000/"
      - "GRAYLOG_ELASTICSEARCH_HOSTS=http://opensearch:9200"
    ports:
      # Porta para a interface web
      - "9000:9000"
      # Portas para receber logs
      - "1514:1514"   # Syslog TCP
      - "1514:1514/udp" # Syslog UDP
      - "12201:12201" # GELF TCP
      - "12201:12201/udp" # GELF UDP
    volumes:
      - "graylog_data:/usr/share/graylog/data"
    restart: "always"

Para concluir, declaramos os volumes persistentes na raiz do arquivo:

volumes:
  mongodb_data:
  os_data:
  graylog_data:

Existe ainda um volume do Graylog para persistência de dados e a política de reinício restart: always, garantindo que o serviço seja religado automaticamente em caso de falhas ou quando o ambiente for derrubado e levantado novamente. Observamos que a chave version no Docker Compose moderno está deprecada e não precisa mais ser especificada no arquivo. Se a IA trouxer essa linha (como no nosso exemplo), você pode mantê-la ou removê-la — o Compose atual funciona sem ela.

Preparando o VS Code e organizando arquivos

Não vamos copiar o arquivo agora. Voltaremos à nossa máquina virtual. Ela ainda está subindo; está demorando um pouco. Enquanto isso, trabalharemos com o Visual Studio Code. Se ainda não o tiverem, façam o download do VS Code no seu sistema operacional. Pesquisando por “Download VS Code” no Google, a primeira opção é a válida. Baixem conforme o sistema operacional. O VS Code integra-se ao Copilot; se quisermos usar uma IA, podemos configurá-la e autenticar no GitHub. Neste momento, não vamos autenticar no GitHub. Usaremos uma IA no navegador apenas para criar os arquivos, entendê-los e aplicar efetivamente as configurações. Depois, começaremos a interagir com a IA nas aulas finais, avaliando os logs e executando essas análises.

Verifiquemos o andamento da instalação: ainda está instalando o kernel e concluindo a inicialização da máquina; ao final, o sistema ficará pronto. O processo está um pouco lento, provavelmente por haver poucos recursos disponíveis.

No VS Code, vamos clicar na opção do Explorador de Arquivos (Explorer), abrir um diretório, navegar até a pasta "Documentos" e criar a pasta "greylog". Em seguida, abriremos a pasta "greylog" no VS Code. Agora já podemos criar o primeiro arquivo: clicaremos em novo arquivo e escreveremos docker-compose.yml. Esse primeiro arquivo YAML será o que acabamos de gerar com a ajuda da IA. Voltaremos ao VS Code e colaremos o conteúdo indicado pela IA. Por ora, não faremos alterações. Se quisermos expor outras portas, adicionaremos na seção apropriada; há várias que podemos expor e veremos isso adiante. Salvaremos o arquivo.

Inserindo o docker-compose completo e revisando o plano

Conteúdo completo do docker-compose.yml, conforme a IA sugeriu:

version: "3.8"

services:
  # MongoDB: Armazena configurações e metadados
  mongodb:
    image: "mongo:5.0"
    volumes:
      - "mongodb_data:/data/db"
    restart: "always"

  # OpenSearch: O motor de busca (sucessor do Elasticsearch)
  opensearch:
    image: "opensearchproject/opensearch:2.4.0"
    environment:
      - "node.name=opensearch"
      - "cluster.name=graylog"
      - "discovery.type=single-node"
      - "bootstrap.memory_lock=true"
      - "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g"
      - "action.auto_create_index=false"
      - "plugins.security.ssl.http.enabled=false"
      - "plugins.security.disabled=true"
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536
    volumes:
      - "os_data:/usr/share/opensearch/data"
    restart: "always"

  # Graylog: A aplicação principal
  graylog:
    image: "graylog/graylog:5.0"
    depends_on:
      mongodb:
        condition: "service_started"
      opensearch:
        condition: "service_started"
    entrypoint: /usr/bin/tini -- wait-for-it opensearch:9200 --  /docker-entrypoint.sh
    environment:
      # Senha do usuário admin (admin)
      # IMPORTANTE: Altere este valor para um hash SHA-256 da sua senha
      - "GRAYLOG_PASSWORD_SECRET=somepasswordpepper"
      - "GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918"
      - "GRAYLOG_HTTP_BIND_ADDRESS=0.0.0.0:9000"
      - "GRAYLOG_HTTP_EXTERNAL_URI=http://127.0.0.1:9000/"
      - "GRAYLOG_ELASTICSEARCH_HOSTS=http://opensearch:9200"
    ports:
      # Porta para a interface web
      - "9000:9000"
      # Portas para receber logs
      - "1514:1514"   # Syslog TCP
      - "1514:1514/udp" # Syslog UDP
      - "12201:12201" # GELF TCP
      - "12201:12201/udp" # GELF UDP
    volumes:
      - "graylog_data:/usr/share/graylog/data"
    restart: "always"

volumes:
  mongodb_data:
  os_data:
  graylog_data:

Vamos conferir como está a criação da máquina: ainda está concluindo algumas configurações. Retomando rapidamente o plano: estamos montando agora o servidor LogServer e veremos seus logs em seguida. O acesso será por SSH por meio da rede em modo ponte. Analisaremos os logs de auditoria, de segurança e do kernel. A partir da próxima aula, montaremos o Graylog de fato e os servidores de aplicação que enviarão logs ao Graylog. Hoje revisaremos o conceito de log que vimos na primeira aula, observando essas informações dentro de um servidor.

Sobre o curso Logs e Observabilidade: estratégias de coleta, análise e governança

O curso Logs e Observabilidade: estratégias de coleta, análise e governança possui 369 minutos de vídeos, em um total de 61 atividades. Gostou? Conheça nossos outros cursos de Confiabilidade & SRE 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 & SRE acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas