3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

#AWS 特定リソース指定時間帯稼働用Lambda

Last updated at Posted at 2024-04-11

EC2、Fargate、RDS指定時間帯稼働について:

下記コスト削減、セキュリティ保護などの理由で、AWS環境に稼働しているEC2、Fargate、およびRDSなどのリソースを特定の時間帯のみ稼働させる必要があります。

・ コスト削減:
特定の時間帯にのみリソースを利用することで、クラウドサービスのコストを削減できます。例えば、夜間や週末には利用者が少ない場合、サーバーの稼働を停止したり、リソースをダウンスケールすることで、不要なコストを抑えることができます。
・ セキュリティ保護:
特定の時間帯にのみシステムを稼働させることで、潜在的なセキュリティリスクを最小限に抑えることができます。また、リソースの不正利用を防ぐために、特定の時間帯にのみアクセスを許可することもあります。
・ リソース最適化:
特定の時間帯に高い負荷が予想される場合、それに応じてリソースをスケールアップすることができます。たとえば、特定の時間帯にWebサイトへのアクセスが急増する場合、その時間帯にだけEC2インスタンスやFargateコンテナの数を増やして、パフォーマンスを維持することができます。
・ メンテナンスやバッチ処理:
特定の時間帯にデータの処理やバッチジョブを実行する場合、そのためにサーバーを稼働させる必要があります。このような場合、必要なリソースをその時間帯にのみ利用可能にすることが重要です。

本記事ではEventBridge (CloudWatch Events)とLambdaの組み合わせで時間帯を指定し、リソースの稼働と停止を制御できるように実装していきます。

処理フロー:

(停止)

指定していた時間がきたらEventBridge (CloudWatch Events)がアクティブになる

稼働/停止用Lambdaを呼び出す

Lambda内部で今の時刻を取得し、停止時間帯の範囲であれば、対象リソースを停止する

終了

(開始)

指定していた時間がきたらEventBridge (CloudWatch Events)がアクティブになる

稼働/停止用Lambdaを呼び出す

Lambda内部で今の時刻を取得し、稼働時間帯の範囲であれば、対象リソースを再開始する

終了

指定時間帯稼働用Lambda作成:

以下の手順を踏んで作成します

  1. AWSコンソール画面の上部にある検索欄から「Lambda」を入力し、検索する
  2. Lambda詳細画面の左メニューの「関数」をクリックする
  3. 右上の「関数の作成」をクリックする
  4. 「一から作成」を選択する
  5. 「関数名」には任意の文字を入力する
  6. 「ランタイム」は「Python 3.8」を選択する
  7. 「関数の作成」をクリックする
  8. Lambda初期生成完了まで待つ
  9. 「設定」タブをクリックし、「一般設定」を編集する
  10. 「タイムアウト」項目を5分に修正する
  11. 「保存」を押す
  12. 「アクセス権限」をクリックし、ロール名をクリックする
  13. ロール設定画面に遷移され、許可ポリシーに必要な権限を付与する
  14. Lambda画面に戻り、画面上部に「+トリガーを追加」を選択する
  15. 「ソースを選択」をクリックし、EventBridge (CloudWatch Events)を選択する
  16. 「Create a new rule」を選択し、「Rule name」に任意の文字を入力する
  17. 「Rule type」は「Schedule expression」に選択し、日次実行パターンを入力する
  18. 「追加」をクリックする

完了

指定時間帯稼働用Lambdaサンプル:

start_stop.py

import boto3
import datetime


def lambda_handler(event, context):
    # 指定のタイムゾーンで現在の時刻を取得
    current_time = datetime.datetime.now(datetime.timezone.utc)
    # タイムゾーンを指定して、現在の時刻を日本時間に変換
    current_time_jp = current_time.astimezone(datetime.timezone(datetime.timedelta(hours=9)))
    # 現在の時刻を出力
    print("現在の日本時間:", current_time_jp)
    print("*****************************************************")

    # 現在の時刻は停止時間帯範囲内かどうかを確認
    if current_time_jp.hour >= 22 or current_time_jp.hour < 8:
        try:
            stop_rds_instance("YOUR_RDS_INSTANCE_ID")
        except Exception as e:
            message = f"Failed to stop rds: {str(e)}"
            print(message)
        try:
            stop_ec2_instance("YOUR_EC2_INSTANCE_ID")
        except Exception as e:
            message = f"Failed to stop ec2: {str(e)}"
            print(message)
        try:
            stop_fargate_service("YOUR_CLUSTER_NAME", "YOUR_FARGATE_SERVICE_NAME")
        except Exception as e:
            message = f"Failed to stop ecs: {str(e)}"
            print(message)
    else:
        print("Do nothing")

    # 現在の時刻は稼働時間帯範囲内かどうかを確認
    if current_time_jp.hour >= 8 or current_time_jp.hour <= 22:
        try:
            start_rds_instance("YOUR_RDS_INSTANCE_ID")
        except Exception as e:
            message = f"Failed to start rds: {str(e)}"
            print(message)
        try:
            start_ec2_instance("YOUR_EC2_INSTANCE_ID")
        except Exception as e:
            message = f"Failed to start rds: {str(e)}"
            print(message)
        try:
            start_fargate_service("YOUR_CLUSTER_NAME", "YOUR_FARGATE_SERVICE_NAME")
        except Exception as e:
            message = f"Failed to start ecs: {str(e)}"
            print(message)
    else:
        print("Do nothing")
    
    print("*****************************************************")
    

# RDS停止用関数
def stop_rds_instance(instance_id):
    rds = boto3.client('rds')
    print("Stop "+ instance_id + "...")
    response = rds.stop_db_instance(DBInstanceIdentifier=instance_id)
    print(response)
    print("Stop "+ instance_id + " finished")

# RDS開始用関数
def start_rds_instance(instance_id):
    rds = boto3.client('rds')
    print("Start "+ instance_id + " ...")
    response = rds.start_db_instance(DBInstanceIdentifier=instance_id)
    print(response)
    print("Start "+ instance_id + " finished")

# EC2停止用関数
def stop_ec2_instance(instance_id):
    ec2 = boto3.client('ec2')
    print("Stop "+ instance_id + " ...")
    response = ec2.stop_instances(InstanceIds=[instance_id])
    print(response)
    print("Stop "+ instance_id + " finished")

# EC2開始用関数
def start_ec2_instance(instance_id):
    ec2 = boto3.client('ec2')
    print("Start "+ instance_id + " ...")
    response = ec2.start_instances(InstanceIds=[instance_id])
    print(response)
    print("Start "+ instance_id + " finished")

# Fargate停止用関数
def stop_fargate_service(cluster_name, service_name):
    ecs = boto3.client('ecs')
    print("Stop "+ service_name + " ...")
    response = ecs.update_service(cluster=cluster_name, service=service_name, desiredCount=0)
    print(response)
    print("Stop "+ service_name + " finished")

# Fargate開始用関数
def start_fargate_service(cluster_name, service_name):
    ecs = boto3.client('ecs')
    print("Start "+ service_name + " ...")
    response = ecs.update_service(cluster=cluster_name, service=service_name, desiredCount=1)
    print(response)
    print("Start "+ service_name + " finished")

最後に:

AWS、GCPなどのクラウドサービスを利用する際に、やはり課金額やセキュリティなどが気になりますよね。時間帯ごとに稼働ステータスを変動することで色々便利になります。
本記事を参考いただき、お役に立っていれば幸いです。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?