Efetuando lifecycle no AWS S3 via Lambda

Introdução

Ativando logs do ALB

Esta semana eu precisei ativar os logs do ALB na AWS, para realizar um troubleshooting devido um incidente, então encaminhei os logs de acesso ao S3.

A principal vantagem de ativar os logs do ALB é a capacidade de solucionar problemas e identificar gargalos de desempenho. Ao analisar os logs, é possível detectar padrões de tráfego, identificar erros e anomalias, e tomar medidas corretivas para melhorar a eficiência do aplicativo.

Além disso, os logs do ALB também são valiosos para fins de conformidade e segurança. Eles registram informações como endereços IP, URLs acessadas e códigos de status HTTP, o que pode ser crucial para investigar atividades suspeitas, identificar possíveis ataques e realizar auditorias de conformidade.

Custos

No entanto, é importante ter em mente que o armazenamento de logs pode ter um custo significativo, especialmente em ambientes de alta demanda ou com muitas requisições. Os logs podem ocupar um espaço considerável em seu armazenamento de dados, o que pode resultar em cobranças adicionais.

Para mitigar os custos associados aos logs do ALB, é recomendável implementar uma estratégia de gerenciamento eficiente. Isso pode incluir a configuração de políticas de retenção para limitar a quantidade de tempo que os logs são armazenados, a utilização de compactação de logs para reduzir o tamanho dos arquivos e o uso de serviços de análise de dados para processar e filtrar os logs de forma mais eficiente.

Também é importante considerar a configuração adequada das permissões de acesso aos logs do ALB. Garantir que apenas as equipes e os indivíduos relevantes tenham acesso aos logs pode ajudar a evitar vazamentos de informações sensíveis e minimizar riscos de segurança.

Em resumo, ativar os logs do ALB na AWS é fundamental para monitorar e analisar o tráfego de rede e garantir o desempenho e a segurança adequados do aplicativo. No entanto, é importante estar ciente dos custos associados ao armazenamento de logs e adotar práticas de gerenciamento eficientes para otimizar o uso e minimizar despesas desnecessárias.

Problema

Como muitos sabem, os custos para armazenar uma quantidade massiva de logs no S3 é enorme, então eu resolvi ativar o lifecycle do próprio S3, especificando um caminho especifico(onde estão os logs do ALB) para ele excluir os logs mais antigos do que 2 dias.

No entanto, passaram 2 dias e os objetos seguiam no bucket, gerando custos desnecessários.

Num outro bucket, onde ativei o lifecycle para o bucket inteiro, o processo estava ocorrendo conforme o esperado.

Solução

Já que a solução oferecida pela AWS não estava funcionando conforme o esperado, decidi seguir numa outra abordagem, criando um script em Python que faça este processo de lifecycle.

Requisitos

Para criar uma estrutura onde o processo de lifecycle ocorresse de forma automatizada, semelhante ao que eu conseguiria através da configuração do S3, foram necessários:

  • S3 Bucket
  • AWS Lambda em Python
  • Policy para Role da Lambda
  • Bucket policy
  • Cron no Amazon EventBridge

Criando a Lambda

O primeiro passo é acessar a console da AWS e ir no serviço de Lambda.

Dentro de Lambda, acessar:

  • Menu Functions
  • Clicar em Create function

Na janela que vai abrir, deixe marcada a opção Author from scratch, em Function name eu coloquei “s3-lifecycle”(você pode escolher o nome que achar mais adequado) e no Runtime escolha “Python 3.9”.

Segue imagem de exemplo:

O restante deixe como está, clicar em Create function.

Será mostrada uma tela como esta:

No trecho onde consta um código em Python de exemplo, vamos remover as linhas e adicionar o nosso código:

import boto3
from datetime import datetime, timedelta, timezone

def delete_objects(bucket_name, prefix, days):
    s3 = boto3.client('s3')
    cutoff_date = datetime.now(timezone.utc) - timedelta(days=days)

    objects_to_delete = []

    paginator = s3.get_paginator('list_objects_v2')
    page_iterator = paginator.paginate(Bucket=bucket_name, Prefix=prefix)

    for page in page_iterator:
        if 'Contents' in page:
            for obj in page['Contents']:
                key = obj['Key']
                last_modified = obj['LastModified'].replace(tzinfo=timezone.utc)
                if last_modified < cutoff_date:
                    objects_to_delete.append({'Key': key})

    if len(objects_to_delete) > 0:
        s3.delete_objects(Bucket=bucket_name, Delete={'Objects': objects_to_delete})
        print(f'{len(objects_to_delete)} objects deleted.')
    else:
        print('No objects found to delete.')

def lambda_handler(event, context):
    bucket_name = 'devops-mind'
    prefix = 'tshoot-incidente-alb/AWSLogs/'
    days = 2

    delete_objects(bucket_name, prefix, days)

Neste script, vocês precisam ajustar apenas os seguintes campos:

  • bucket_name
    • Nome do bucket onde estão armazenados os objetos.
  • prefix
    • Prefixo/caminho onde estão armazenados os objetos(os logs no nosso caso).
  • days
    • Quantidade de dias onde os objetos são considerados antigos e podem ser deletados.

Após ajustado o código, vai constar uma mensagem “Changes not deployed”, você pode clicar em Deploy.

Antes de prosseguir com a utilização da Lambda ou configuração do EventBridge, precisamos ajustar as permissões, tanto no Bucket do S3, quanto na role que é utilizada pela Lambda.

Ajustando policies da Role e do Bucket

Para que todo o processo ocorra da maneira adequada, são necessárias permissões relacionadas ao bucket do S3.

Bucket Policy

Partindo da idéia que você já tenha um bucket no S3(não vou cobrir a parte de criação do bucket neste artigo), acesse:

  • Aba Permissions
  • No trecho sobre Bucket Policy, clique em Edit

Vamos adicionar a seguinte policy:

{
    "Version": "2008-10-17",
    "Id": "Policy1335892530063",
    "Statement": [
        {
            "Sid": "DevOps-Mind-lambda",
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.us-east-1.amazonaws.com"
            },
            "Action": [
                "s3:*"
            ],
            "Resource": "arn:aws:s3:::devops-mind/tshoot-incidente-alb/AWSLogs/*",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "123456"
                }
            }
        }
    ]
}

Edite os campos, conforme os recursos e estrutura dos seus objetos no S3.

Também é necessário editar o SourceAccount, procurei deixar permissões para recursos de uma conta específica apenas.

Em actions deixamos todas, mas poderíamos liberar actions mais específicas. Visando deixar o artigo mais simples, vamos seguir permitindo todas elas mesmo.

Após terminar os ajustes na policy, clique em Save changes.

Policy para a Role

Quando criamos a Lambda, foi criada junto com ela uma Role.

No meu caso a role é a s3-lifecycle-role-fggxxkgz:

Precisamos criar uma policy e atrelar a esta role, para garantir que ela tenha os privilégios necessários no nosso bucket do S3.

Acesse o serviço do IAM na AWS, clique em Policies e depois no botão Create policy, conforme destacado em amarelo na imagem abaixo:

Vamos utilizar o seguinte código para criar a nossa policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DevOpsMindBucket1",
            "Effect": "Allow",
            "Action": "s3:ListAllMyBuckets",
            "Resource": "*"
        },
        {
            "Sid": "DevOpsMindBucket2",
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::devops-mind/tshoot-incidente-alb/AWSLogs/*",
                "arn:aws:s3:::devops-mind"
            ]
        }
    ]
}

Nossa tela estará assim:

Defina um nome para a policy e clique em Create policy:

Feito isto, procure pela role no IAM.

Acesse a Role e clique em Add permissions.

Após isto, clique em Attach policies:

Selecione a policy na busca.

Clique em Add permissions.

Resultado esperado:

Configurando automação

Para que o processo de lifecycle ocorra conforme o esperado, precisamos configurar uma trigger na nossa Lambda.

O jeito mais fácil é indo até a console da AWS, acessar novamente a nossa Lambda e clicar em Add trigger, conforme destacado em amarelo:

Configure o event source para utilizar o EventBridge.

Defina um nome para a rule e adicione uma descrição.

Em Schedule expression, adicione os valores:

cron(0 12 * * ? *)

A expressão cron cron(0 12 * * ? *) em uma regra do Amazon EventBridge define um agendamento de evento que ocorre todos os dias às 12:00 (meio-dia) UTC.

Vamos analisar a expressão cron em detalhes:

  • O primeiro campo (0) indica o valor dos minutos. Nesse caso, 0 significa que o evento ocorrerá no início de cada hora.
  • O segundo campo (12) indica o valor da hora. Nesse caso, 12 indica que o evento ocorrerá às 12 horas.
  • O terceiro campo (*) indica o valor do dia do mês. Nesse caso, * significa que o evento ocorrerá em qualquer dia do mês.
  • O quarto campo (*) indica o valor do mês. Nesse caso, * significa que o evento ocorrerá em qualquer mês.
  • O quinto campo (?) é usado para substituir o campo de dia da semana (*) quando o agendamento é baseado no dia do mês. Nesse caso, ? indica que não há uma especificação de dia da semana.
  • O sexto campo (*) indica o valor do ano. Nesse caso, * significa que o evento ocorrerá em qualquer ano.

Portanto, a regra de evento com essa expressão cron será acionada todos os dias, exatamente às 12:00 (meio-dia) UTC.

Após configurar todos os campos, teremos algo parecido com isto:

Clique em Add, para finalizar o processo.

Resultado esperado:

Material de apoio

  • Documentação AWS Lambda
  • Programar expressões usando rate ou cron

Conclusão

Quando o lifecycle do S3 não funciona corretamente, pode ser frustrante lidar com armazenamento desnecessário de objetos ou falta de exclusão de itens expirados. Felizmente, ao utilizar as AWS Lambdas, você pode criar um processo personalizado para gerenciar o lifecycle dos objetos de forma automatizada e eficiente.

Através das Lambdas, você pode solucionar problemas específicos de lifecycle no S3, garantindo que os objetos sejam corretamente transicionados ou excluídos de acordo com suas regras de negócio. Além disso, as Lambdas oferecem flexibilidade e escalabilidade, permitindo que você adapte o processo de acordo com suas necessidades em constante mudança.

Ao utilizar as AWS Lambdas para automatizar o processo de lifecycle do S3, você poderá manter seu armazenamento otimizado e reduzir custos desnecessários, certamente o Julius aprovaria estas ações.

Fernando Müller Junior
Fernando Müller Junior

Eu sou o Fernando Müller, um Tech Lead SRE com 16 anos de experiência em TI, atualmente eu trabalho na Appmax, uma fintech localizada no Brasil. Apaixonado por trabalhar com arquiteturas e aplicações Cloud Native, ferramentas Open Source e tudo que existe no mundo SRE, sempre procurando se desenvolver e aprender constantemente(Lifelong learning), atuando em projetos inovadores!

Artigos: 28

Um comentário

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *