🚫
EC2とRDSを週末に全部止める
今日のところは動作未確認。
Lambda関数(Python)
import os
import logging
import boto3
excluded_tag_key = os.getenv('EXCLUDED_TAG_KEY')
excluded_tag_value = os.getenv('EXCLUDED_TAG_VALUE')
logger = logging.getLogger()
logger.setLevel(logging.INFO)
ec2_client = boto3.client('ec2')
rds_client = boto3.client('rds')
def stop_ec2_instances():
response = ec2_client.describe_instances(Filters=[{'Name': 'instance-state-name', 'Values': ['running']}])
instances = [instance for reservation in response['Reservations'] for instance in reservation['Instances']]
for instance in instances:
tags = instance.get('Tags', [])
excluded = any(tag['Key'] == excluded_tag_key and tag['Value'] == excluded_tag_value for tag in tags)
if not excluded:
instance_id = instance['InstanceId']
ec2_client.stop_instances(InstanceIds=[instance_id])
logger.info(f'Stopped EC2 instance: {instance_id}')
def stop_rds_db_instances():
response = rds_client.describe_db_instances()
db_instances = response['DBInstances']
for db_instance in db_instances:
tags = db_instance.get('TagList', [])
excluded = any(tag['Key'] == excluded_tag_key and tag['Value'] == excluded_tag_value for tag in tags)
if not excluded:
db_instance_identifier = db_instance['DBInstanceIdentifier']
rds_client.stop_db_instance(DBInstanceIdentifier=db_instance_identifier)
logger.info(f'Stopped DB instance: {db_instance_identifier}')
def lambda_handler(event, context):
stop_ec2_instances()
stop_rds_db_instances()
CloudFormationテンプレート
AWSTemplateFormatVersion: 2010-09-09
Description: Create a Lambda function to stop EC2 instances and RDS instances regularly
Resources:
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: LambdaExecutionRole
PolicyDocument:
Version: 2012-10-17
Statement:
- Sid: StopEC2RDSInstances
Effect: Allow
Action:
- ec2:DescribeInstances
- ec2:StopInstances
- rds:DescribeDBInstances
- rds:StopDBInstance
Resource: '*'
- Sid: PutLogs
Effect: Allow
Action:
- logs:CreateLogStream
- logs:PutLogEvents
Resource: '*'
StopInstances:
Type: AWS::Lambda::Function
Properties:
Handler: index.lambda_handler
Role: !GetAtt LambdaExecutionRole.Arn
Runtime: python3.12
Timeout: 30
Environment:
Variables:
EXCLUDED_TAG_KEY: ExcludeFromAutoStop
EXCLUDED_TAG_VALUE: True
Code:
ZipFile: |
##### ここにPythonコードを貼り付ける #####
LambdaSchedule:
Type: AWS::Events::Rule
Properties:
Description: Invoke StopInstances function at 20:00 on Friday
ScheduleExpression: cron(0 11 ? * FRI *)
State: ENABLED
Targets:
- Arn: !GetAtt StopInstances.Arn
Id: LambdaSchedule
LambdaPermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt StopInstances.Arn
Principal: events.amazonaws.com
SourceArn: !GetAtt LambdaSchedule.Arn
LambdaLogGroup:
UpdateReplacePolicy: Delete
DeletionPolicy: Delete
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${StopInstances}
RetentionInDays: 30
あとがき
ChatGPT先生に教えてもらいましたが、二重の内包表記([instance for reservation in response['Reservations'] for instance in reservation['Instances']]
)を初めて知りました。しかしfor ...
は前後逆の方が分かりやすかったような……
any(tag['Key'] == excluded_tag_key and tag['Value'] == excluded_tag_value for tag in tags)
もChatGPT先生に教えてもらいましたが、自分では思いつかなかった気がします。
Discussion