EC2 com logs centralizados utilizando Loki + FluentBit + Grafana
Tags: aws, monitoring, cloud, linux
Published: 2023-01-25 13:07:55

acessei via SSM e por ai vai. Se eu tivesse um lugar com os logs centralizados das instâncias EC2, eu poderia consultar os logs das instância com problemas e trabalhar na resolução.

Com isso surgiu a ideia de montar este artigo para documentar e ajudar outras pessoas. Neste artigo não reinventei a roda, fiz um compilado do que já existe nas documentações oficiais. Entre outras documentações que fui encontrando para facilitar na configurações.

 Vou colocar aqui as adaptações que fiz para o meu cenário de atuação, mas também deixar de forma clara para que qualquer um possa utilizar.

> OBS: Neste artigo estou seguindo com uma estrutura de VPC já criada na AWS para as 2 instâncias utilizadas no LAB

Vou fazer um apresentação rápida e básica dos serviços que serão utilizados neste artigo:

**EC2** - é um serviço com recurso computacional, redimensionável e que pode ser utilizado para qualquer workload. Uma definição bem básica sobre este serviço disponibilizado pela AWS.

**FluentBit** - É o agente responsável por ler o arquivo de log e enviar para o Loki.

**Grafana Loki** - É uma stack de monitoramentos de logs.

**Grafana Dashbord** - É a ferramenta onde irei criar o dash de visualização de logs da instância que será utilizada como LAB.

Feito um breve resumo das ferramentas que serão utilizadas, vou iniciar a criação do servidor do Grafana.

Para criação do servidor que irá hospedar Grafana, Loki vou utilizar os comandos do awscli. Mas para criação deste ambiente poderia ter sido utilizado outras ferramentas de provisionamento e configurações, segue abaixo alguns exemplos de ferramentas

Um exemplo dessas ferramentas são: [Terraform](https://www.terraform.io/), [Cloudformation](https://aws.amazon.com/pt/cloudformation/), [Ansible](https://www.ansible.com/), [Chef](https://www.chef.io/), [Puppet](https://www.puppet.com/)

### Criando uma instância do EC2
Para iniciar a criação da instância, ao invés de criar uma chave _**.pem**_ vou importar a minha chave pública para acessar a instância:
```
aws ec2 import-key-pair --key-name "grafana-server" --public-key-material fileb://~/.ssh/id_rsa.pub
```
Na sequência vou criar um security group:

```
aws ec2 create-security-group --group-name grafana-server  --description "Grafana EC2 Server" --vpc-id vpc-668d120f
```
Agora vou criar 2 regras de ingress no security group criado:

```
aws ec2 authorize-security-group-ingress --group-id sg-02c489bbdeffdca1d --protocol tcp --port 22 --cidr 192.168.15/32

aws ec2 authorize-security-group-ingress --group-id sg-02c489bbdeffdca1d --protocol tcp --port 3000 --cidr 192.168.15/32

aws ec2 authorize-security-group-ingress --group-id sg-02c489bbdeffdca1d --protocol tcp --port 3100 --cidr 192.168.15/32
```
**_Na última regra liberando a porta 3100 ela é necessária para que o fluent-bit possa se comunicar com o Loki e fazer o envio dos logs._**

**_Deixei as regras do security group somente para acesso da minha rede local_**

Criando a instância:

```
aws ec2 run-instances --image-id ami-0b5eea76982371e91 --instance-type t3.medium --key-name grafana-server --security-group-ids sg-0aa58857d399d42d0 --subnet-id subnet-0f322466aad742642 --associate-public-ip-address
```

## Instalando e configurando Docker, Grafana e o Loki

Com o ambiente criado, vou seguir com a instalação do Grafana e Loki. Neste ponto vou subir 2 containers, que irão se comunicar pela rede interna do docker. Vou acessar a console para pegar o endereço público da instância. Para criação da instância utilizei a AMI com Amazon Linux 2, então o acesso será feito desta forma:

```
ssh ec2-user@ec2-174-129-133-73.compute-1.amazonaws.com
```
Logado na instância vou fazer a instalação do serviço do docker:

```
sudo yum update -y
sudo yum install docker -y
sudo service docker start
sudo usermod -a -G docker ec2-user
```
Após ter feito a instalação se receber a seguinte mensagem:

```
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json": dial unix /var/run/docker.sock: connect: permission denied
```
**_É necessário dar um logout e fazer o login novamente_**

Agora vou criar a rede no docker e subir o container do Grafana e do Loki

Criando a rede:

```
docker network create networklogs --driver bridge
```
Rede criada vou subir os 2 containers:

```
docker run -d --name=grafana --network monitoring -p 3000:3000 grafana/grafana-os

docker run -d --name=loki --network monitoring -p 3100:3100 grafana/loki
```
Se os 2 container subiram sem problemas, podemos acessar via browser a console do Grafana.

```
http://ec2-174-129-133-73.compute-1.amazonaws.com:3000
```
Se estiver tudo ok, essa tela deverá se exibida

![tela de login grafana](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uwsukzm0olukcy13sv47.png)
Nessa tela o usuário e senha padrão é admin admin. Após logar você será solicitado a alterar a senha.

Logado na interface vamos fazer a config do Loki, para isso a engrenagem no painel lateral esquerdo > Plugins

![configuração do plugin do Loki](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8e2la8x4cuq7i2c3r4zz.png)
Nos plugins vai na busca para procurar pelo plugin do Loki

![plugin loki](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ruapqh7huk1f8plp5lgl.png)
Agora clique no botão azul  Create a Loki data source

![create loki Datasource](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sao82a9a380o8007gfj5.png)
Agora vou preencher as informações solicitadas. Em url perceba que coloquei

```
http://loki:3100
```
Porque este endereço?

Lembra que incialmente eu cria uma rede interna docker, certo? Com isso ao invés de chamar

```
http://localhost:3100
```
Eu estou chamando na url pelo nome do container.

Feito as configs, pode clicar em Save & test. Caso aparece essa mensagem:

![log ainda não está sendo enviado](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/moq2oybhs19euwg33pi3.png)
É porque ainda não estamos enviando os logs com os labels utilizado nas querys. 

Ambiente do Grafana e Loki configurados, vamos configurar o ambiente que fará o envio dos logs. Aqui vou utilizar os mesmo comandos iniciais, já vou partir para o acesso via SSH e instalação do Nginx, que enviará os logs do access.log para o servidor do Loki.

Instalando Nginx no Amazon Linux 2

```
sudo yum install nginx -y

sudo service nginx start
```
Necessário somente instalar e dar start no serviço

Na instância onde o Nginx está instalado, é necessário que tenha o docker instalado também. Pois será necessário para subir o container do fluent-bit  para que seja feito o envio dos logs.

Iniciando o container do fluent-bit para o envio dos logs, aqui vou utilizar a configuração padrão sem mexer em labels ou qualquer outra config. O valor da variável LOKI_URL vou colocar o ip interno da instância do servidor do Grafana, para que isso não passe pela internet para não termos gastos desnecessários.

```
docker run -d -v /var/log/nginx:/var/log/nginx -e LOG_PATH="/var/log/nginx/access.log" -e LOKI_URL="http://10.42.12.1:3100/loki/api/v1/push" grafana/fluent-bit-plugin-loki:latest
```
Assim que o container estiver up, de alguns acesse o Nginx pelo public DNS e de alguns F5 para gerar logs no access.log

Um detalhe, se for novamente na parte dos plugins, verá que aquela mensagem do Datasource que printei anteriormente na config do Loki não está mais aparecendo uma vez que estamos enviando os logs.

Vou validar se os logs estão chegando no Loki, para isso vou fazer um query. Na interface do Grafana, vá em Explore

![query](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1mzl3dxx2bn7z7yiqqc9.png)
Em label filters selecione o seguintes valores:

![label filters](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jm58odwzqw862hhtktma.png)
A query deverá fica desta forma. Agora vamos rodar a query e ver se temos os logs da instância do nginx.

![logs nginx](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pxwhahvdtpfdsovr0ypf.png)
Se na parte inferior, retornar desta forma

![resultado](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gkr2c6lzwhzevnun44au.png)
Funcionou com sucesso as configs.

Tentei demonstrar basicamente a criação de um servidor Grafana com plugin do Loki para coleta dos logs de um Nginx, instalado em uma instância EC2. Os logs aqui foram enviados utilizando o fluent-bit, com as configurações default. Aqui eu utilizei o fluent-bit para fazer a coleta e envio dos logs, mas poderia ser utilizado qualquer outro ship para o envio de logs, por exemplo o Promtail.

E ai vamos se conectar? Entre em contato comigo:
https://www.linkedin.com/in/pcmalves/


Referências:
https://hub.docker.com/r/grafana/fluent-bit-plugin-loki
https://grafana.com/docs/loki/latest/clients/fluentbit/
https://grafana.com/blog/2020/07/13/loki-tutorial-how-to-set-up-promtail-on-aws-ec2-to-find-and-analyze-your-logs/