[PYTHON] Stellen Sie den Verfügbarkeitsstatus potenziell teurer Instanzen in Lambda auf Slack

Warum willst du das tun?

Während der Entwicklung können Sie Instanzen auf hoher Ebene in verschiedenen Tests starten. In seltenen Fällen können Sie jedoch versehentlich vergessen, sie zu löschen und zurückzukehren. Wenn Sie es am nächsten Tag bemerken, ist der Schaden gering. Aber was ist, wenn Sie es eine Weile nicht bemerkt haben, wie vor den Ferien? Es kann nicht gesagt werden, dass ein anständiger Geldbetrag angesammelt wird, und in einigen Fällen wird es kein Chaos sein, eine Disposition zu schreiben.

AWS verfügt über einen Mechanismus zum Auslösen von Warnungen basierend auf dem in Rechnung gestellten Betrag. Dies zeigt Ihnen jedoch nur, dass Sie sich bereits bis zu dem Punkt angesammelt haben, an dem es gefährlich ist, aber es handelt sich nicht um eine vorbeugende Maßnahme. Was tun Sie später, wenn Sie in 3 Tagen ein Monatsbudget ausgeben?

Erstens ist es eine Geschichte, die vor der Rückkehr überprüft werden muss, aber es ist eine Geschichte, ob Sie sie zu 100% schützen können, indem Sie Regeln erstellen und Checklisten erstellen. Gibt es nicht einen Fall, in dem die bestätigte Region anders ist? Eine Kreatur namens Programmierer schreibt ein Programm, mit dem eine Maschine etwas tun kann, was sie nicht tun möchte, oder? Ja, lass es uns tun.

AWS ist AWS

Ich weiß, dass awscli den Status einer Instanz annehmen kann. Wo machst du das? Sie können auf dem Server Ihres Unternehmens cronen, aber Sie können es trotzdem nicht auf AWS tun, Lambda ein- oder zweimal am Tag.

Awscli mit Lambda

Das Know-how für awscli mit Lambda finden Sie unter AWS CLI auf Lambda und S3 Sync ausführen. Ich werde darauf verweisen.

Nehmen wir an, dass es vorerst eine Python3-Umgebung gibt.

> mkdir check-aws
> cd check-aws
> pip install awscli -t .

Die aws-Datei ist genau das

#!/usr/bin/env python3

import sys
import awscli.clidriver
def main():
    return awscli.clidriver.main()
if __name__ == '__main__':
    result = main()
    sys.exit(result)

x Probieren Sie es an

> chmot +x aws
> ./aws
<Abkürzung>

Wenn Sie in lambda_function.py eine Arbeitsinstanz finden, die mit ec2 und rds größer als groß ist, schreiben Sie einen Prozess, um sie in Slack zu werfen.

# -*- coding: utf-8 -*-

import subprocess
import json
import urllib.request

region_name = {
    'ap-northeast-1': 'Tokio',
    'ap-northeast-2': 'Seoul',
    'ap-southeast-1': 'Singapur'
}

check_result = []

def check_ec2(region):
    cmd = []
    cmd.append("./aws")
    cmd.append("ec2")
    cmd.append("describe-instances")
    cmd.append("--filter")
    cmd.append("Name=instance-state-name,Values=running")
    cmd.append("--region")
    cmd.append(region)

    result = subprocess.run(cmd, stdout = subprocess.PIPE)
    resjson = json.loads(result.stdout.decode('utf-8'))

    for resv in resjson['Reservations']:
        for ins in resv['Instances']:
            typ = ins['InstanceType'].split('.')[1]
            #Vergib klein
            if typ in ['nano', 'micro', 'small', 'medium']:
                continue
            insName = 'Anonym'
            for tag in ins['Tags']:
                if tag['Key'] == 'Name':
                    insName = tag['Value']
            insTyp = ins['InstanceType']
            insLnc = ins['LaunchTime']
            check_result.append('ec2 ' + region_name[region] + ' ' + insName + '(' + insTyp + ') ' + insLnc)

def check_rds(region):
    cmd = []
    cmd.append("./aws")
    cmd.append("rds")
    cmd.append("describe-db-instances")
    cmd.append("--region")
    cmd.append(region)

    result = subprocess.run(cmd, stdout = subprocess.PIPE)
    resjson = json.loads(result.stdout.decode('utf-8'))

    for ins in resjson['DBInstances']:
        typ = ins['DBInstanceClass'].split('.')[2]
        if typ in ['nano', 'micro', 'small', 'medium']:
            continue
        if ins['DBInstanceStatus'] != 'available':
            continue
        insName = ins['DBInstanceIdentifier']
        insTyp = ins['DBInstanceClass']
        check_result.append('rds ' + region_name[region] + ' ' + insName + '(' + insTyp + ')')

def lambda_handler(event, context):
    check_ec2('ap-southeast-1') #Singapur
    check_ec2('ap-northeast-1') #Tokio
    check_rds('ap-northeast-1') #Tokio

    if len(check_result) > 0:
        message = '\Instanzbetriebsstatus von groß oder größer<@hogehoge> \n'
        for str in check_result:
            message += str
            message += '\n'
        print(message)
        url = 'https://hooks.slack.com/services/xxxx/yyyy/zzzzzzzz'
        method = 'POST'
        headers = {'Content-Type' : 'application/json'}
        payload = {'text' : message}
        json_data = json.dumps(payload).encode('utf-8')
        request = urllib.request.Request(url, data=json_data, method=method, headers=headers)
        with urllib.request.urlopen(request) as res:
            body = res.read()

if __name__ == '__main__':
    lambda_handler('','')

Es ist eine gute Idee, jemandem, der die Situation kennt und die Instanz löschen kann, mehrere Slack-Benachrichtigungsnachrichten zu erwähnen (diejenigen, die die Benachrichtigung nicht ignorieren, sind ebenfalls unerwartet wichtig). Wenn Sie Slack nicht verwenden, können Sie es als SNS anordnen. Dieses Mal haben wir nur EC2 und RDS nach dem großen Ziel ausgewählt, aber ich denke, wir können auch die Anzahl der Instanzen und anderer Dienste verarbeiten. Ich weiß es nicht.

Lassen Sie uns überprüfen, ob dies auch funktioniert. Wenn Sie gehen können, stellen Sie bereit.

>zip -r check-aws *

Ich möchte es als Zip-Datei hochladen und testen, aber es gibt einige Einschränkungen. ・ Haben Sie eine PowerUserAccess-Rolle ・ Stellen Sie etwas mehr Zeit ein ・ Stellen Sie etwas mehr Speicher ein Es scheint, dass 128 MB Speicher ausreichen, aber ich denke, es ist besser, ihn auf ungefähr 1024 MB einzustellen, weil die CPU so schlecht ist. Anpassung erforderlich.

Testen Sie es und hoffentlich (wenn es nicht funktioniert, lesen Sie die Fehlermeldung und tun Sie etwas dagegen) und richten Sie den Auslöser ein und Sie sind fertig. Sollten wir nicht einfach so etwas wie "cron (0 9? * MON-FRI *)" im Zeitplanausdruck in EventBridge tun?

Dann.

Recommended Posts

Stellen Sie den Verfügbarkeitsstatus potenziell teurer Instanzen in Lambda auf Slack
Setzen Sie TensorFlow mit pip3 in die P2-Instanz
Einfache Serverüberwachung mit AWS Lambda (Python) und Ergebnisbenachrichtigung mit Slack
Beispiel für eine Slack-Benachrichtigung mit Python Lambda
Stoppen Sie eine Instanz mit einem bestimmten Tag in Boto3