Przejdź do treści

Jak wyłączyć wszystkie EC2 we wszystkich regionach AWS jednocześnie?

How to stop all EC2 in all AWS regions at the same time 2022 cloud.jpg

Witam wszystkich bardzo serdecznie, dzisiaj opiszę sposób, w jaki sobie radziłem z zatrzymywaniem maszyn EC2 na kontach testowych w chmurze AWS we wszystkich regionach jednocześnie. Przedstawię prosty tutorial, który krok po kroku pokaże, jak można zbudować takie rozwiązanie.

Mam różne konta AWS i problemem było dla mnie kiedyś to, że zapominałem wyłączać EC2, gdy zakończyłem testy. Oczywiście otrzymywałem powiadomienia o tym, że zaraz przekroczę budżet, więc nie straciłem za dużo kasy. O tym, jak możesz ustawić budżet i otrzymywać takie powiadomienia dowiesz się z tego artykułu Jak kontrolować koszty w chmurze AWS ?? – blog z tutorialem po polsku (lepczynski.it).

Dodatkowym problemem było to, że maszyny EC2 tworzyłem w różnych regionach. Czasem zapominałem gdzie, a nawet jeśli pamiętałem, to męczące było zaglądanie do każdego regionu i wyłączanie w każdym z nich maszyn.

Wymyśliłem prosty skrypt, który sprawdza wszystkie regiony w poszukiwaniu maszyn EC2. Jeśli znajdzie maszynę EC2, to ją zatrzyma. Skrypt oczywiście uruchamia się codziennie sam o określonej godzinie, w moim przypadku o 1 w nocy.

Poniżej znajdziesz kompletne rozwiązanie, które możesz także zastosować u siebie i przestać płacić za maszyny, które są niepotrzebnie włączone. Rozwiązanie sprawdzi się idealnie, nawet jeśli nie wiesz, ile masz maszyn i gdzie one są.

Plan działania – co będzie potrzebne:

  1. Polityka IAM pozwalająca tylko na znalezienie i zatrzymanie EC2
  2. Rola IAM z minimalnymi uprawnieniami
  3. Funkcja Lambda
  4. CloudWatch Event

1) Polityka IAM pozwalająca tylko na znalezienie i zatrzymanie EC2

Przejdź do IAM, wybierz Policies i utwórz nową IAM Policy, kliknij na Create policy.

create aws policy 2022
AWS Create policy

Teraz możesz utworzyć własną politykę albo użyć tej, którą ja stworzyłem stop_ec2. Wystarczy, że przełączysz się na JSON i wkleisz poniższą zawartość.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances",
                "ec2:DescribeInstanceAttribute",
                "ec2:DescribeRegions",
                "ec2:StopInstances",
                "ec2:DescribeInstanceStatus"
            ],
            "Resource": "*"
        }
    ]
}

2) Rola IAM z minimalnymi uprawnieniami

Teraz możesz utworzyć Rolę IAM. Przejdź do IAM, wybierz Roles. Utwórz nową IAM Role, kliknij Create role, a następnie wybierz Lambda.

aws create IAM role 2022
AWS Service – Lambda

Dodaj utworzoną wcześniej politykę i przejdź dalej. Teraz możesz dodać nazwę np. stop_ec2, opis do roli i kliknąć Create role.

add policy ro aws role 2022 stop ec2
AWS Roles – add permissions

3) Funkcja Lambda

Teraz przechodzimy do tworzenia Funkcji lambda. Z usług wybierz Lambda i kliknij Create function.

lambda aws create function
AWS Lambda – functions

Ja tworzę funkcję lambda używając Python 3.9 o nazwie stop_ec2.

Bardzo ważne! Pamiętaj by zmienć Execution role na tą rolę, którą utworzyłeś w poprzednim punkcie. W moim przypadku jest to stop_ec2. Politykę dodajesz do roli, a rolę dodajesz do funkcji to takie proste:)

create function aws lambda python
AWS Lambda from scratch

Funkcja jest bardzo prosta, ma za zadanie znaleźć wszystkie EC2 w danym koncie, we wszystkich regionach. Jeśli znajdzie EC2 to wypisuje ich id oraz stan. Wszystkie maszyny, które mają stan równy running, zostaną automatycznie zatrzymane.

import boto3 
ec2_client = boto3.client('ec2')
regions = [region['RegionName'] for region in ec2_client.describe_regions()['Regions']]

def lambda_handler(event, context):
    for region in regions:
        ec2_client = boto3.client('ec2', region)
        all_instances = ec2_client.describe_instances()
        if all_instances:
            print("List all instances:")
            for reservation in all_instances['Reservations']:
                for instance in reservation['Instances']:
                    print(instance['InstanceId'] + "-" + instance['State']['Name'])
                    
                    if instance['State']['Name'] == 'running':
                        print("Stopping ec2: " + instance['InstanceId'])
                        ec2_client.stop_instances(InstanceIds=[instance['InstanceId']])

TEST

function stop ec2
Logs from function stop_ec2

Oczywiście funkcję lambda można dodatkowo rozbudować, żeby np. działała tylko w określonym regionie. Wystarczy wtedy dodać jedną zmienną i if.

Można także utworzyć identyczną funkcję tylko uruchamiającą maszyny EC2. Dzięki temu można mieć jedną funkcję odpowiedzialną za wyłączanie maszyn a drugą za ich włączanie. Do tego dodajemy Cloud Watch Event, żeby funkcja uruchamiała się automatycznie i gotowe.

4) Cloud Watch Event

Gdy utworzyłeś już swoją funkcję i sprawdziłeś, czy działa prawidłowo, to możesz zautomatyzować jej uruchamianie np. przez dodanie CloudWatch Event. Dzięki temu możesz uruchomić funkcję o określonym czasie. Jeśli interesuje cię ten temat, to pisałem o tym też w artykule Jak mieć porządek na S3 – Lambda + CloudWatch Events 2022 (lepczynski.it).

Wystarczy, że klikniesz Add Trigger, z listy wybierzesz CloudWatch Events, dodasz nazwę i opis. Ja lubię używać wyrażeń cron, ale Ty nie musisz. Moja funkcja będzie uruchamiać się codziennie o pierwszej w nocy.

cloudwatch event stop ec2 2022
AWS Lambda – add trigger

Podsumowanie

Jak widać bardzo łatwo zrobić prostą funkcję lambda, która ułatwi życie i zaoszczędzi pieniądze. Pomimo iż nie jestem developerem, lubię używać funkcji Lambda w AWS, ponieważ mają szerokie zastosowanie i są naprawdę potężne.

Jeśli zainteresował cię artykuł, to spróbuj sam stworzyć taką funkcję jak ja, a potem ją rozbuduj i dostosuj do swoich potrzeb. Najlepiej jest się uczyć przez praktykę.