EC2やRDS、ELBの停止忘れ、削除し忘れを防ぐ!LambdaScheduleイベント #reinvent
この記事は古いのでこちらを御覧ください!!
コンニチハ。千葉です。
突然ですが、開発環境などで使っているEC2やRDS、ELBを停止し忘れた、消し忘れた!という経験をお持ちの方へ。
私、よくパソコン抱っこしながら寝落ちするのですが、ELBを作成しっぱなし、課金発生してた!ということがあります。
無駄にお金を払わないように、インスタンス停止や不要なリソースの削除はコマメに行いたいところです。
そんな中、新しくLambdaScheduleイベントがリリースされました。これは使うしかない!ということで、リソースの状況を教えてくれるツールを作ってみました。
構成
Lambdaで1日1回スケジュールをトリガーに発火させます。 そこで、EC2、RDS、ELBの起動状況を取得、SNS経由からメールで通知してくれます。
リソースが起動している場合は、こんな感じでメールがきます。逆にリソースが起動していない時は、メールは来ません!
作ってみた
SNSの作成
まず、メール送信するためにSNSトピックを作成します。
SNSの画面から、[Topics] > [Create new topic]を選択します。
[Topic name]と[Display name]を入力します。
リソース状況の通知先のメールアドレスを設定します。先ほど作成した、トピックにチェックを入れ、[Actions] > [Subscribe to topic]を選択します。
[Email]を選択し、通知先のメールアドレスを入力します。
先ほど入力したメール宛に、購読するかの確認メールが来ます。[Confirm subscription]をクリックして購読登録します。
SNS側でメールアドレスが購読状態になっているかを確認します。トピック一覧より、対象トピックのARNをクリックします。 また、ARNは後で使うのでメモっておきます。
[Subscription ID]が[arn:aws:sns:〜]、[Endpoint]に登録したメールアドレスが表示されているかを確認します。
これで、SNSの作成は完了です。
Lambdaファンクションの作成
今回は、Pythonでコードを記述します。 それではLambdaファンクションを作成していきます。
[Create a Lambda function]をクリックし、Lambdaファンクションを作成していきます。
[Skip]をクリックします。
[Name]、[Description]を入力し、[Python]を選択します。
[Lambda function code]には、下記のコードを入力します。
[TOPIC_ARN]には、先ほど作成したSNSトピックのARN(先ほどメモしたもの)を入力します。
import boto3 TOPIC_ARN = 'arn:aws:sns:ap-northeast-1:XXXX:XXXX' def lambda_handler(event, context): try: # Check for EC2 ec2 = boto3.client('ec2') ec2_resp = ec2.describe_instances(Filters=[{'Name':'instance-state-name','Values':['running']}] ) ec2_count = len(ec2_resp['Reservations']) if not ec2_count == 0: send_message.append("[EC2 is running!!]") for i in range(0, ec2_count): send_message.append(ec2_resp['Reservations'][i]['Instances'][0]['Tags'][0]['Value']) send_message.append("") # Check for ELB elb = boto3.client('elb') elb_resp = elb.describe_load_balancers() elb_count = len(elb_resp['LoadBalancerDescriptions']) if not elb_count == 0: send_message.append("[ELB is running!!]") for i in range(0, elb_count): send_message.append(elb_resp['LoadBalancerDescriptions'][i]['LoadBalancerName']) send_message.append("") # Check for RDS rds = boto3.client('rds') rds_resp = rds.describe_db_instances() rds_count = len(rds_resp['DBInstances']) if not rds_count == 0: send_message.append("[RDS is running!!]") for i in range(0, rds_count): send_message.append(rds_resp['DBInstances'][i]['DBInstanceIdentifier']) send_message.append("") # Send mail send_subject = "[AWS]Money Save" send_message = ["Please check resources...\n"] for i in send_message: print(i) sns = boto3.client('sns') sns_resp = sns.publish( TopicArn = TOPIC_ARN, Message = "\n".join(send_message), Subject = send_subject ) return 0 except Exception as e: print(e) print('Error getting object {} from bucket {}. Make sure they exist and your bucket is in the same region as this function.'.format(key, bucket)) raise e
[Lambda function handler and role] > [Role]にて、今回用のRoleを作成します。
[Basic execution role]を選択します。
ロールの作成画面が表示されます。(chromeではポップアップの許可が必要だったため、適宜許可します)
[IAM ロール]は[新しいIAMロールの作成]を選択、[ロール名]を入力します。
[編集] > [OK]をクリックします。
ポリシードキュメントには、以下を入力します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:DescribeInstances", "rds:DescribeDBInstances", "elasticloadbalancing:DescribeLoadBalancers", "sns:Publish", "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "*" } ] }
[Advanced settings]で、Lambda実行時間のタイムアウトを[30秒]にします。
[Next]をクリックします。
設定内容を確認し、[Create function]をクリックします。
テスト実行してみます。[Save and test]をクリックします。
Lambdaファンクションが実行されます。下にスクロールし、実行結果を確認し[succeeded]となっていることを確認します。
ここで、
- EC2インスタンスが"起動"している
- ELBが"存在"している
- RDSインスタンスが"存在"している
場合、登録したメールアドレスにメールが来ます。
あとは、1日1回スケジュール実行するようにトリガーの設定をして終わりです。
[Event sources]タブを選択し、[Add event source]をクリックします。
[Ebvent source type]で[Scheduled Event]を選択。[Schedule expression]で[rate(1 day)]を選択します。
[Submit]をクリックして設定完了です。
あとは、リソースが起動している場合は日時でメールが来ます。
さいごに
Lambdaスケジュール、とっても便利です。スナップショット等、cron専用に立てていたサーバの代替としても利用できそうです。