250日目 EC2のコストダウンを行った社畜M

## ♠はじめに
こんにちは、社畜Mだぜ。
今回は以前俺がやらせてもらったタスク課題の1つ「**AWSの従量課金タイプのリソースの無駄遣いを減らす**」という課題で俺がやったことをここに残すぜ！
さぁ、行くぜ！！！

**デュエル！**
## ♠使ったものの簡単な説明
その時の課題で使ったものはEC2・Lambda・Amazon EventBridgeの3つです。
まずはこの３つについて軽くおさらいしていきましょう。

### ♦EC2とは
EC2は、AWSが提供する仮想サーバーサービスで、必要な時に必要な分だけの計算リソースを柔軟に利用できます。用途に応じてインスタンスの種類やスペックを選び、スケーラブルでコスト効率の高いインフラ環境を構築可能です。
EC2を起動したままにしておくと、利用時間に応じて課金されます。インスタンスが動作中でなくても、EBSやElastic IPなどの関連リソースにも料金が発生する場合があるので注意が必要です。

### ♥Lambdaとは
Lambdaは、サーバーレスでコードを実行できるサービスで、インフラ管理を不要にし、イベント駆動型のアプリケーションを簡単に構築できます。利用者は必要なコードをアップロードし、イベントトリガー（例: APIリクエスト、S3更新など）に応じて自動実行されます。

### ♣Amazon EventBridgeとは
Amazon EventBridgeは、AWSサービス、SaaSアプリケーション、カスタムアプリケーション間でイベントをルーティングするフルマネージド型のイベントバスサービスです。イベント駆動型アーキテクチャを簡単に構築でき、フィルタリングやルール設定で効率的にイベントを処理します。スケーラブルで可用性が高く、シームレスな統合が可能です。
今回使用したのはAmazon EventBridgeのSchedulerです。Schedulerは、AWSリソースやアプリケーション間で定期的なイベントを簡単に設定・管理できるサービスです。指定したスケジュールに基づいてイベントをトリガーし、自動化を実現します。

## ♠今回の概要
今回の課題で使った上記３つをどう使うのかの説明を受けたものをかみ砕いて図にするとこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766505/9fbdfb10-f73e-4cfc-4f9c-6038d75d3be1.png)
今回の課題の目的は停止し忘れて動き続けるEC2をLambdとEventBridgeを使って指定の時間に止めることでコストダウンを図るというものです。
次にLambdaとEventBridgでは何を行うのかを説明していきます。

### ♥Lambda
Lambdの方ではEC2を停止させるコードを作ります。
最初はEC2全部見て動いているやつを止めるものを想定して作っていましたが断念し、下記の形になりました。
```Python:Lambda
import boto3
import os
import logging
from datetime import datetime

# CloudWatch Logs へのログ設定
logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):
    # 環境変数から停止タグの情報を取得
    stop_tag_key = os.environ['STOP_TAG_KEY']
    stop_tag_value = os.environ['STOP_TAG_VALUE']
    
    # EC2クライアントの初期化
    ec2 = boto3.client('ec2')
    
    # 停止対象のインスタンスを取得
    instances = ec2.describe_instances(
        Filters=[
            {'Name': f'tag:{stop_tag_key}', 'Values': [stop_tag_value]},
            {'Name': 'instance-state-name', 'Values': ['running']}
        ]
    )
    
    stopped_instances = []
    
    # 対象インスタンスを停止
    for reservation in instances['Reservations']:
        for instance in reservation['Instances']:
            instance_id = instance['InstanceId']
            
            # インスタンス名を取得
            instance_name = "Unknown"
            for tag in instance.get('Tags', []):
                if tag['Key'] == 'Name':
                    instance_name = tag['Value']
                    break
            
            try:
                ec2.stop_instances(InstanceIds=[instance_id])
                stopped_instances.append(f"{instance_name} ({instance_id})")
                logger.info(f"インスタンスを停止しました: {instance_name} ({instance_id})")
            except Exception as e:
                logger.error(f"インスタンスの停止に失敗しました: {instance_name} ({instance_id}). エラー: {str(e)}")
    
    # 結果のログ出力
    logger.info(f"停止したインスタンス: {', '.join(stopped_instances)}")
    logger.info(f"停止したインスタンス数: {len(stopped_instances)}")
    
    return {
        'statusCode': 200,
        'body': f'Successfully stopped {len(stopped_instances)} instances'
    }
```
こちらのコードの特徴として、以下のものがあります。
**・タグベースのインスタンス管理**
STOP_TAG_KEY: 停止対象のタグキー。
STOP_TAG_VALUE: 停止対象のタグ値。
これらのタグをもとにフィルタリングし、実行中のEC2のみを停止させます。

**・スケーラブルな環境変数の利用**
停止タグのキーと値を環境変数にすることで、Lambda関数のコードを変更せずに異なるタグでの操作が可能です。
<br>
注意としてこのLambdaを動作させるには以下の権限が必要になります。
- **ec2:DescribeInstances**ータグや状態に基づいてインスタンス情報を取得するため
- **ec2:StopInstances**ー指定したインスタンスを停止するため

### ♣Amazon EventBridge
後はAmazon EventBridge Schedulerで、
・実行する日時を設定
・使用するLambdaの名称をターゲットに設定
・アクセス用のロールを設定
これら行うことでAmazon EventBridge Schedulerの作成ができます。

後は停止させたいEC2にLambdaの時に記述した２つのタグを設定すれば指定した時間にEventBridge Schedulerが起動してLambdaを実行、タグが一致してかつ動いているEC2は止まるでしょう。

## ♠まとめ
今回の課題では、AWSの知識が少ない中での挑戦だったため、最初はわからないことだらけで作るのにかなりを時間をかけてしまった記憶もあります。
ですが、LambdaやEventBridgeの設定が上手くいって動いたときはうれしかったことを今も覚えています。私にとってもこの課題はAWSを学ぶいい機会でした。

## ♠おまけ
一気にキャラを変えていくぜ！
今回の社会人が知っておいた方がいいビジネスマナーはこいつだ！
「**名刺交換のマナー**」だぜ。
現代社会になっていても社会人なら取引先や初対面の相手など名刺交換は避けては通れないぜ、名刺交換するときには…
**目下の人から差し出す**ことがマナーだぜ。
取引先との名刺交換の場合は取引先の人間が目上、こっちが目下になるからな名刺を差し出すのはこっちが先だぜ。
いつ名刺交換するときがあるかはわからないからな、覚えておいてくれだぜ！

これで今回は終わりだぜ。
**ターンエンド**