>> Apresentação e considerações

Fala pessoal, estamos ai em mais um Post sobre AWS, dessa vez vamos falar de um recurso chamado “CloudWatch Logs”, e vou procurar contemplar todos os passos de forma prática para que ao final desse Post você possa compreender todos os passos necessários para tal implantação.

>> Tá, mais isso serve quê?

CloudWatch Logs é a solução de centralização de Logs da AWS.

É possível enviar seus arquivos de log dos sistemas, dos aplicativos e personalizados existentes para o CloudWatch Logs e monitorá-los em tempo quase real. Isso pode ajudar você a entender e a operar melhor seus sistemas e aplicativos, e os logs podem ser armazenados usando armazenamento altamente durável e de baixo custo para posterior acesso.

Existem “N” soluções de armazenamento de Logs como a stack ELK, Graylog, entre outros, no caso do CloudWatch Logs o esforço de implementação e manutenção é mínimo, pois não precisamos gerenciar o ambiente coletor de Logs em si, basta simplesmente ter o agente, fazer os apontamentos necessários e de forma simples e rápida você já tem os seus logs disponíveis para consulta.

https://aws.amazon.com/pt/cloudwatch/details/#log-monitoring

>> Pré requisitos

Nesse post estou partindo do princípio que você já possui:

  • Pelo menos uma instância EC2 Linux em execução na AWS;
  • Máquina Linux ou MacOS com AWS CLI instalada;
  • AWS Access Key ID e Secret Access Key com permissões de administrador da conta.

Com essas informações em mãos, ou quer dizer configuradas na máquina vamos começar.

Let`s go!

>> Criando o Grupo de Log (Log Group)

Vamos um criar um log group com um nome específico.

Obs.: No caso vamos criar somente 1, mais para que informação existe o limite de até 5000 log groups por região.

Diretrizes ao nomear um grupo de log:

  1. Únicos dentro de uma região para uma conta AWS.
  2. Entre 1 e 512 caracteres.
  3. Pode-se utilizar os seguintes caracteres:
    a-z, A-Z, 0-9
    ‘_’ (sublinhado)
    ‘-‘ (hífen),
    ‘/’ (barra invertida)
    ‘.’ (ponto).

Entendido isso, vamos a criação!

No exemplo vamos simular a coleta de Logs do site “churropsondevops.tech” rodando em cima de um NGINX , e vamos coletar logs, para isso vamos criar um LogGroup para segmentar a nossa criação.

Para isso vá até a máquina que você possui a CLI e as chaves da AWS, e vamos começar a brincadeira.

~# aws --region us-east-1 logs create-log-group --log-group-name churropsondevops.tech

Agora vamos criar o Log Stream, aqui vamos definir os fluxos dos nossos logs para o grupo que criamos.

Ao contrário dos grupos, o Log Steam não tem limitações para a criação dentro de um log group

Diretrizes para nomear um log stream:

  1. Nome de Log stream deve ser único no Log Group.
  2. Pode ter entre 1 e 512 caracteres .
  3. Caracteres não permitidos:
    ‘:’ (colon)
    ‘*’ (asterisk)
~# aws --region us-east-1 logs create-log-stream --log-group-name churropsondevops.tech --log-stream-name nginx-access.log

~# aws --region us-east-1 logs create-log-stream --log-group-name churropsondevops.tech --log-stream-name nginx-error.log

http://docs.aws.amazon.com/cli/latest/reference/logs/create-log-stream.html

http://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/QuickStartEC2Instance.html

>> Adicionando uma política de retenção

Vamos definir agora a política de retenção do nosso grupo, para manter somente os últimos 5 dias de logs.

~# aws --region us-east-1 logs put-retention-policy --log-group-name churropsondevops.tech --retention-in-days 5

>> Resultado do que foi feito até o momento

Vá em Services -> CloudWatch -> Logs

Na interface vemos o nosso Log Group criado com a retenção de 5 dias

Captura de Tela 2017-06-24 às 16.24.38

No print abaixo vemos os Streams que criamos, se o seu está assim, sucesso estamos no caminho!!!

Captura de Tela 2017-06-24 às 16.25.26

>> Criando a IAM ROLE

A comunicação do agent com o CloudWatch Logs é realizada através de uma IAM ROLE, ou seja, dessa forma não precisamos criar chaves no IAM e configurar na instância, as ROLES são a forma fortemente recomendada para situações em que algum recurso da AWS precise se comunicar com outro.

Baseado sempre na documentação oficial da AWS, temos abaixo a política (Policy) necessária para que a instância seja capaz de enviar os logs para o CloudWatch Logs.

https://aws.amazon.com/pt/blogs/security/new-attach-an-aws-iam-role-to-an-existing-amazon-ec2-instance-by-using-the-aws-cli/

Crie o arquivo abaixo e cole o conteúdo, pois vamos usar esse arquivo para o Input da criação da nossa Policy.

~# vim /tmp/cw-logs-policy.json

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogStreams"
    ],
      "Resource": [
        "arn:aws:logs:*:*:*"
    ]
  }
 ]
}

Com o documento criado, vamos criar a nossa Policy utilizando a CLI da AWS.

~# aws --region us-east-1  iam create-policy --policy-name AllowEC2CloudWatchLogs --policy-document file:///tmp/cw-logs-policy.json

{
    "Policy": {
        "PolicyName": "AllowEC2CloudWatchLogs",
        "PolicyId": "ANPAJF5ZRF7JJANBG6DTC",
        "Arn": "arn:aws:iam::745505968289:policy/AllowEC2CloudWatchLogs",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "IsAttachable": true,
        "CreateDate": "2017-06-24T20:08:18.516Z",
        "UpdateDate": "2017-06-24T20:08:18.516Z"
    }
}

Vamos criar a role, essa role que vamos utilizar em nossa instância EC2, criei o arquivo a seguir

~# cat /tmp/assume-role-policy-ec2.json
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Principal": {"Service": "ec2.amazonaws.com"},
    "Action": "sts:AssumeRole"
  }
}

Agora vamos criar nossa role:

~# aws --region us-east-1 iam create-role --role-name EC2-DefaultCustomRole --assume-role-policy-document file:///tmp/assume-role-policy-ec2.json


{
    "Role": {
        "Path": "/",
        "RoleName": "EC2-DefaultCustomRole",
        "RoleId": "AROAIPTH3ZKUTVLVKHI7E",
        "Arn": "arn:aws:iam::745505968289:role/EC2-DefaultCustomRole",
        "CreateDate": "2017-06-24T20:03:07.627Z",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": {
                "Effect": "Allow",
                "Principal": {
                    "Service": "ec2.amazonaws.com"
                },
                "Action": "sts:AssumeRole"
            }
        }
    }
}

Vamos associar a nossa role criada com a nossa policy.

~# aws iam attach-role-policy --policy-arn arn:aws:iam::745505968289:policy/AllowEC2CloudWatchLogs --role-name EC2-DefaultCustomRole

Criar nosso Instance Profile, e adicionando ele a role

~# aws iam create-instance-profile --instance-profile-name EC2-Instance-Profile

~# aws iam add-role-to-instance-profile --role-name EC2-DefaultCustomRole --instance-profile-name EC2-Instance-Profile

Agora vamos identificar o ID da nossa instância

http://docs.aws.amazon.com/cli/latest/userguide/controlling-output.html

Identificando o Instance ID da instância que queremos atacar a role

~# aws --region us-east-1 ec2 describe-instances --query 'Reservations[].Instances[].[Placement.AvailabilityZone, State.Name, InstanceId,InstanceType,Platform,Tags.Value,State.Code,Tags.Values]' --output text |grep running

us-east-1c	running	i-059fd6f2a57b0cd1e	t2.micro	None	None	16	None

Com o Instance ID vamos associar ao instance profile

~# aws --region us-east-1 ec2 associate-iam-instance-profile --instance-id "i-059fd6f2a57b0cd1e" --iam-instance-profile Name=EC2-Instance-Profile

{
    "IamInstanceProfileAssociation": {
        "AssociationId": "iip-assoc-035a21846b64845de",
        "InstanceId": "i-059fd6f2a57b0cd1e",
        "IamInstanceProfile": {
            "Arn": "arn:aws:iam::745505968289:instance-profile/EC2-Instance-Profile",
            "Id": "AIPAIEA7TUVV77YHVGUNE"
        },
        "State": "associating"
    }
}

>> Configurando o Agent na instância EC2

Amazon Linux

~# yum update -y
~# yum install -y awslogs
~# chkconfig awslogs on

Outras distribuições

http://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/QuickStartEC2Instance.html

Inserindo as configurações

mv /etc/awslogs/awslogs.conf /etc/awslogs/awslogs.conf.ORIG
~# vim /etc/awslogs/awslogs.conf

# Insira essas configurações dentro do arquivo

[nginx-access.log]
log_group_name = churropsondevops.tech
log_stream_name = nginx-access.log
datetime_format = '%Y-%m-%dT%H:%M:%S%z'
time_zone = LOCAL
file = /var/log/nginx/access.log
initial_position = start_of_file
encoding = utf_8

[nginx-error.log]
log_group_name = churropsondevops.tech
log_stream_name = nginx-error.log
datetime_format = '%Y-%m-%dT%H:%M:%S%z'
time_zone = LOCAL
file = /var/log/nginx/error.log
initial_position = start_of_file
encoding = utf_8

Inicie o serviço

~# service awslogs start

Os logs podem ser acompanhados em:

~# tailf /var/log/awslogs.log 

>> Visualizando os logs no Console

Basta acessar o painel da AWS, e pronto os logs podem ser visualizados e filtrados de acordo com a necessidade!

Captura de Tela 2017-06-24 às 18.35.15

Captura de Tela 2017-06-24 às 18.37.57.png

>> Troubleshooting

Caso você se depare com uma mensagem de erro semelhante a essa, precisa verificar se a Role está definida corretamente na instância e com as permissões necessárias.

~# tailf /var/log/awslogs.log

    raise error_class(parsed_response, operation_name)
ClientError: An error occurred (AccessDeniedException) when calling the PutLogEvents operation: User: arn:aws:sts::745505968289:assumed-role/CustomMetrics/i-0c6b667fe9a42573b is not authorized to perform: logs:PutLogEvents on resource: arn:aws:logs:us-east-1:745505968289:log-group:rdglinux-projetoX-frontend:log-stream:httpd-error_log

>> Conclusão

Esse foi um exercício que visou passar por todas as etapas para que os processos sejam conhecidos, com isso acredito que já podemos nos virar bem e explorar mais formas e mais opções de se chegar ao resultado.

Espero que tenham gostado, não esqueçam de deixar seu comentário e compartilhar com seus amigos!

Abraços!