DEV Community

Henrique Santos
Henrique Santos

Posted on

2 2 2

Expansão de disco automática EC2 (Lambda+CloudWatch+SNS)

1- Crie uma política no IAM com as permissões.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:PutMetricData",
                "cloudwatch:GetMetricStatistics",
                "cloudwatch:ListMetrics",
                "ec2:DescribeTags"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ssm:GetParameter"
            ],
            "Resource": "arn:aws:ssm:::parameter/AmazonCloudWatch-*"
        }
    ]
}

Enter fullscreen mode Exit fullscreen mode

2- Crie uma função (role) para EC2 e adicione a politica criada na etapa 1.

3- Instale o agente do CloudWatch na instância. (nesse exemplo estou utilizando em uma maquina linux ubuntu).

wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
sudo dpkg -i -E ./amazon-cloudwatch-agent.deb

Para coletar as métricas necessárias rode os comandos:

cd /opt/aws/amazon-cloudwatch-agent/bin 
wget https://raw.githubusercontent.com/railandermarques/cloudwatchmonitoring/master/config.json 
cd /opt/aws/amazon-cloudwatch-agent/etc/ 
cp -av ../bin/config.json amazon-cloudwatch-agent.json 
mkdir -p /usr/share/collectd/ 
touch /usr/share/collectd/types.db 
sudo sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json -s 
systemctl enable amazon-cloudwatch-agent 
systemctl status amazon-cloudwatch-agent
Enter fullscreen mode Exit fullscreen mode

4-Crie um tópico SNS com nome de sua escolha.

5- Acesse o CloudWatch no console AWS > All Alarms > Create Alarm > Select metric, e pesquise por CWAgent, verifique o que possui métricas de disco.

  • Selecione a métrica “disk_used_percent” com o path da partição que o disco utiliza. (Nesse caso estou monitorando para expandir o disco root.)

Image description

  • Defina o período no qual você deseja receber alertas e indique a porcentagem igual ou maior na qual você deseja que o disco seja expandido. Em seguida, clique em "Next".

Image description

6 - Na aba "Notificação", selecione "Em alarme", "Selecionar um tópico SNS existente" e escolha o tópico que foi criado na etapa 4. Em seguida, clique em "Next".

Image description

7- Defina um nome para o alarme, clique em "Next" e, em seguida, em "Create alarm".

8- Este exemplo envia alertas para um grupo do Discord e para que isso funcione, é necessário adicionar a camada "requests" ao Lambda. Siga as etapas abaixo:

Image description

9- Crie uma função Lambda com um nome de sua escolha, selecione Python 3.9 e atribua uma função que permita o acesso a todos os EBS e instâncias EC2 (neste exemplo, foi utilizado o acesso de Administrador, mas é possível ajustar isso para uma permissão mais restrita).

10- Dentro da função Lambda, na aba "Layers", clique em "Add a Layer" e selecione a camada criada na etapa 8.

11- Cole o código python no lambda_function.py

Observação: esse código esta expandindo o disco root, partição /dev/xvda 1, tipo ext4. Caso o disco tenha uma configuração diferente é necessario alterar os comandos da linha 50.
Linha 41 - alterar ID do volume que será expandido.
Linha 48 - alterar o ID da instância.
Linha 55 - Alterar endereço do webhook do discord (colocar o do chat que ira receber os alertas da finalização de expansão).
Linha 56 - Editar mensagem a ser enviada para o alerta do Discord.

import boto3
import time
import json
import requests


def expandir_volume_ebs(volume_id):
    ec2_client = boto3.client('ec2')

    response = ec2_client.describe_volumes(VolumeIds=[volume_id])
    current_size = response['Volumes'][0]['Size']
    new_size = current_size + 1

    response = ec2_client.modify_volume(
        VolumeId=volume_id,
        Size=new_size
    )

    return response

def executar_comandos_shell(instance_id, comandos):
    ssm_client = boto3.client('ssm')

    response = ssm_client.send_command(
        InstanceIds=[instance_id],
        DocumentName="AWS-RunShellScript",
        Parameters={'commands': comandos}
    )

    return response

def enviar_mensagem_discord(webhook_url, message):
    data = {
        'content': message
    }
    response = requests.post(webhook_url, json=data)
    if response.status_code != 204:
        print('Falha ao enviar mensagem para o Discord:', response.text)

def lambda_handler(event, context):
    volume_id = "vol-0d2dfdd723adb27bd"

    response = expandir_volume_ebs(volume_id)
    print("Volume expandido:", response)

    time.sleep(180)

    instance_id = "i-0ac8a7a16a50b9f06"

    comandos = ['sudo su', 'growpart /dev/xvda 1', 'resize2fs /dev/xvda1']

    response = executar_comandos_shell(instance_id, comandos)
    print("Comandos executados:", response)

    webhook_url = 'https://discord.com/api/webhooks/1123651003187728464/OYQ_--_Am'
    message = 'O disco root /dev/xvda 1 da instância i-0ac8a7a16a50b9f06 foi expandido!'
    enviar_mensagem_discord(webhook_url, message)

    return {
        'statusCode': 200,
        'body': json.dumps('Lambda executada !')
    }
Enter fullscreen mode Exit fullscreen mode

12 -Após o lambda ser executado você deve receber um alerta no chat do discord do webhook.

Image description

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs