はじめに
当チームではテスト環境等の社内利用用途を目的としたEC2インスタンスは業務時間内しか利用しないことが多いため、深夜帯や休日に稼働し続け無駄なコストがかかってしまうことがあります。
そういった不要なコストを抑えるためにテスト環境専用のサブネットを用意し、定時でサブネット内のすべてのインスタンスを停止する機能があると便利だなと思っていました。
件数が少ない時期はAmazon EventBridgeでルールを作成し個別で自動停止の設定をしていましたが、件数が増えるにつれ一括の設定が必要になり構築することにしました。
今回はLambdaを使って構築をしましたので設定方法を記述します。
構築イメージ
AWSサービス全体の構築イメージは以下の図の通りです。
今回設定方法を記述するのは以下の工程です。
- AWS EventBridgeで毎日PM10:00に指定のLambdaを実行するルールを設定する
- Lambdaで対象のサブネット配下にあるEC2インスタンスすべてを停止する関数を設定する
- IAM RoleでLambdaがEC2インスタンスを操作する権限を付与する
やってみる
AWS EventBridgeの設定
ルールを新規作成します。
UIに従って設定していくので特に難しい点はないと思います。
Cronが日本時間と9時間差があるので注意です。
Lambdaの設定
停止対象のサブネットIDにあるインスタンスを配列で取得し、すべて停止する処理をpythonで記述します。
IAMRoleが正しく設定されていないとインスタンスの情報を取得できないのでお気を付けください。
import boto3
def lambda_handler(event, context):
ec2 = boto3.client('ec2')
subnet_id = 'subnet-xxxxxxxxxxx' # 停止対象のサブネットIDを指定
response = ec2.describe_instances(
Filters=[
{'Name': 'subnet-id', 'Values': [subnet_id]},
{'Name': 'instance-state-name', 'Values': ['running']}
]
)
instance_ids = []
for reservation in response['Reservations']:
for instance in reservation['Instances']:
print(instance)
instance_ids.append(instance['InstanceId'])
if instance_ids:
stop_response = ec2.stop_instances(InstanceIds=instance_ids)
print(stop_response)
return stop_response
else:
return null
トリガーの設定をします。
EventBridgeで作成したルールを設定してください。
IAM Roleの設定
インスタンスの表示・停止権限を付与します。
以下のコードを設定したIAMポリシーをIAM Roleに紐づけます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EC2DescribeInstances",
"Effect": "Allow",
"Action": "ec2:DescribeInstances",
"Resource": "*"
},
{
"Sid": "EC2StopInstances",
"Effect": "Allow",
"Action": [
"ec2:StopInstances",
"ec2:DescribeInstances"
],
"Resource": "*"
}
]
}
以上の設定をすることで毎日PM22:00に対象サブネット内のインスタンスが自動停止されます。
おわりに
今までインスタンスを個別で管理していたので工数がかかっていたのですが、サブネット単位で管理できると大分工数削減につながるなと感じました。
また、野良インスタンスがずっと起動しっぱなしで不要なコストがかかってしまうことも回避できるので有用だと思いました。
本稿の内容だけで運用・管理できるわけではないので明確なオペレーションを策定していきたいと思います。