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作成:
以下の手順を踏んで作成します
- AWSコンソール画面の上部にある検索欄から「Lambda」を入力し、検索する
- Lambda詳細画面の左メニューの「関数」をクリックする
- 右上の「関数の作成」をクリックする
- 「一から作成」を選択する
- 「関数名」には任意の文字を入力する
- 「ランタイム」は「Python 3.8」を選択する
- 「関数の作成」をクリックする
- Lambda初期生成完了まで待つ
- 「設定」タブをクリックし、「一般設定」を編集する
- 「タイムアウト」項目を5分に修正する
- 「保存」を押す
- 「アクセス権限」をクリックし、ロール名をクリックする
- ロール設定画面に遷移され、許可ポリシーに必要な権限を付与する
- Lambda画面に戻り、画面上部に「+トリガーを追加」を選択する
- 「ソースを選択」をクリックし、EventBridge (CloudWatch Events)を選択する
- 「Create a new rule」を選択し、「Rule name」に任意の文字を入力する
- 「Rule type」は「Schedule expression」に選択し、日次実行パターンを入力する
- 「追加」をクリックする
完了
指定時間帯稼働用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などのクラウドサービスを利用する際に、やはり課金額やセキュリティなどが気になりますよね。時間帯ごとに稼働ステータスを変動することで色々便利になります。
本記事を参考いただき、お役に立っていれば幸いです。