今回はLambda(サーバレス)を使用してEC2のインスタンス、EBSのスナップショット、
EIP、ELB/ALB/RDS/S3/CloudFrontをterminate/delete(削除)する方法をブログします。(意外とググっても出てこない件)
例えば、検証用としてインスタンス立ち上げたままで忘れて課金されているとか。。
しかもインフラメンバーとかは毎回コンソール開いて確認するのはとても!
ダルイ。。。
そんなことないように3ヶ月に一回削除(terminate)できたらいいことでしょう!
基本jsonとPythonとの戦いなので、まずはLambdaの使い方からいってみましょう。
そういえばre:invent 2016ではc#がサポートされましたね〜(c#むりぽ)
■Lambdaとは
インスタンスベースの仮想サーバー(EC2、ElastiChache、Redshiftなど)を
使わずにアプリケーションを開発するアーキテクチャで、
毎回サーバを構築する必要がありません!なのでコスト削減に期待できます。
■Lambdaを使ってみる
AWSのインスタンス情報は基本jsonで返ってきます。
今回は以下のコマンドで確認します。
1 2 3 | #IAMの設定を事前にしときましょう $ aws ec2 describe-instances $ aws ec2 describe-snapshots |
ダーッとインスタンス情報なり、スナップショットの情報が出てくるかと。
AWS SDK For Python (Boto3)で書いてます。
・IAMにLambdaのロールを追加する
以下の3つの権限をぶち込んでください。
・Lambdaのコンソールを開き、新しく作成する
・Configure Function
・Dashboard
・スクリプトの紹介
やりたいことはKeyが「nodelete」Valueが「true」以外
のものはインスタンスterminate(削除)します。
空白のものも消えます。
つまり、上記のタグにしとけば消えることはありません。
あとはこのスクリプトをかましてcloud watchで3ヶ月に一回とかイベント設定すればOK。
# coding: utf-8 | |
# RDS delete | |
import boto3 | |
# nodelete,trueを変数化 | |
ND = 'nodelete' | |
TR = 'true' | |
def lambda_handler(event, context): | |
#if __name__ == '__main__': | |
client = boto3.client('cloudfront', "ap-northeast-1") | |
resp = client.list_distributions() | |
#print resp | |
all_list = [] | |
del_list = [] | |
for cf in resp['DistributionList']['Items']: | |
#print cf['Id'] | |
all_list.append(cf['Id']) | |
#print all_list | |
resp2 = client.list_tags_for_resource( | |
Resource = "arn:aws:cloudfront::xxxxxxxxxxxxxxxxx:distribution/" + cf['Id'] | |
) | |
#print resp2 | |
for tag in resp2['Tags']['Items']: | |
#print tag | |
if tag['Key'] == ND and tag['Value'] == TR: | |
del_list.append(cf['Id']) | |
#print(del_list) | |
diffset = set(all_list) – set(del_list) | |
#print(diffset) | |
targetlist = list(diffset) | |
#print(targetlist) | |
for target in targetlist: | |
#print target | |
response = client.delete_distribution( | |
Id=target | |
) |
# coding: utf-8 | |
#EC2に紐付いていないEIPを開放 | |
import boto3 | |
def lambda_handler(event, context): | |
#if __name__ == '__main__': #EC2 | |
client = boto3.client('ec2', "ap-northeast-1") | |
resp = client.describe_addresses() | |
#print(resp) | |
for addresses in resp['Addresses']: | |
#print(addresses['AllocationId']) | |
if not 'InstanceId' in addresses: | |
#print(addresses['AllocationId']) | |
client.release_address( | |
AllocationId=addresses['AllocationId'] | |
) |
# coding: utf-8 | |
#ELB delete | |
import boto3 | |
# nodelete,trueを変数化 | |
ND = 'nodelete' | |
TR = 'true' | |
def lambda_handler(event, context): | |
#if __name__ == '__main__': #EC2の場合 | |
client = boto3.client('elb') | |
#loadbalancersの情報を変数化 | |
resp = client.describe_load_balancers() | |
all_list1 = [] | |
del_list1 = [] | |
#loadbalancerNameでtagを出力 | |
#print resp | |
for elb in resp['LoadBalancerDescriptions']: | |
all_list1.append(elb['LoadBalancerName']) | |
#print(all_list) | |
resp2 = client.describe_tags( | |
LoadBalancerNames=[elb['LoadBalancerName']] | |
) | |
#print(resp2) | |
for tag in resp2['TagDescriptions']: | |
#tagがnodelete以外を出力 | |
for k in tag['Tags']: | |
#print k | |
if k['Key'] == ND and k['Value'] == TR: | |
del_list1.append(elb['LoadBalancerName']) | |
#print(del_list) | |
diffset1 = set(all_list1) – set(del_list1) | |
#print(diffset) | |
targetlist1 = list(diffset1) | |
#print(targetlist1) | |
response = client.delete_load_balancer( | |
LoadBalancerName=targetlist1 | |
) | |
#ALB delete | |
def lambda_handler(event, context): | |
#if __name__ == '__main__': | |
client = boto3.client('elbv2') | |
#loadbalancersの情報を変数化 | |
resp = client.describe_load_balancers() | |
all_list2 = [] | |
del_list2 = [] | |
#loadbalancerNameでtagを出力 | |
#print resp | |
for alb in resp['LoadBalancers']: | |
all_list2.append(alb['LoadBalancerArn']) | |
#print(all_list2) | |
resp2 = client.describe_tags( | |
ResourceArns=[alb['LoadBalancerArn']] | |
) | |
#print(resp2) | |
for tag in resp2['TagDescriptions']: | |
#tagがnodelete以外を出力 | |
for a in tag['Tags']: | |
#print a | |
if a['Key'] == ND and a['Value'] == TR: | |
del_list2.append(alb['LoadBalancerArn']) | |
#print(del_list) | |
diffset2 = set(all_list2) – set(del_list2) | |
#print(diffset2) | |
targetlist2 = list(diffset2) | |
#print(targetlist2) | |
response = client.delete_load_balancer( | |
LoadBalancerArn=targetlist2 | |
) |
# coding: utf-8 | |
# RDS delete | |
import boto3 | |
# nodelete,trueを変数化 | |
ND = 'nodelete' | |
TR = 'true' | |
def lambda_handler(event, context): | |
#if __name__ == '__main__': | |
client = boto3.client('rds', "ap-northeast-1") | |
resp = client.describe_db_snapshots() | |
#print resp | |
all_list = [] | |
del_list = [] | |
for rds in resp['DBSnapshots']: | |
all_list.append(rds['DBSnapshotIdentifier']) | |
#print(all_list) | |
resp2 = client.list_tags_for_resource( | |
ResourceName="arn:aws:rds:ap-northeast-1:xxxxxxxxxxxx:snapshot:" + rds['DBSnapshotIdentifier'] | |
) | |
#print resp2 | |
for tag in resp2['TagList']: | |
#print tag | |
if tag['Key'] == ND and tag['Value'] == TR: | |
del_list.append(rds['DBSnapshotIdentifier']) | |
#print(del_list) | |
diffset = set(all_list) – set(del_list) | |
#print(diffset) | |
targetlist = list(diffset) | |
#print(targetlist) | |
for target in targetlist: | |
#print target | |
response = client.delete_db_snapshot( | |
DBSnapshotIdentifier=target, | |
SkipFinalSnapshot=True | |
) |
# coding: utf-8 | |
# RDS delete | |
import boto3 | |
# nodelete,trueを変数化 | |
ND = 'nodelete' | |
TR = 'true' | |
#def lambda_handler(event, context): | |
if __name__ == '__main__': | |
client = boto3.client('rds', "ap-northeast-1") | |
resp = client.describe_db_instances() | |
all_list = [] | |
del_list = [] | |
for rds in resp['DBInstances']: | |
all_list.append(rds['DBInstanceIdentifier']) | |
#print(all_list) | |
resp2 = client.list_tags_for_resource( | |
ResourceName="arn:aws:rds:ap-northeast-1:xxxxxxxxxx:db:" + rds['DBInstanceIdentifier'] | |
) | |
#print resp2 | |
#タグ判別による出力 | |
for tag in resp2['TagList']: | |
#print tag | |
if tag['Key'] == ND and tag['Value'] == TR: | |
del_list.append(rds['DBInstanceIdentifier']) | |
#print(del_list) | |
diffset = set(all_list) – set(del_list) | |
#print(diffset) | |
targetlist = list(diffset) | |
#print(targetlist) | |
for target in targetlist: | |
print target | |
#print type(target) | |
response = client.delete_db_instance( | |
DBInstanceIdentifier=target, | |
SkipFinalSnapshot=True, | |
) |
# coding: utf-8 | |
# RDS delete | |
import boto3 | |
# nodelete,trueを変数化 | |
ND = 'nodelete' | |
TR = 'true' | |
def lambda_handler(event, context): | |
#if __name__ == '__main__': | |
client = boto3.client('s3', "ap-northeast-1") | |
resp = client.list_buckets() | |
#print resp | |
all_list = [] | |
del_list = [] | |
for s3 in resp['Buckets']: | |
#print s3 | |
all_list.append(s3['Name']) | |
#print(all_list) | |
try: | |
resp2 = client.get_bucket_tagging( | |
Bucket=s3['Name'] | |
) | |
except: | |
None | |
#print s3['Name'] | |
for tag in resp2['TagSet']: | |
#print tag | |
if tag['Key'] == ND and tag['Value'] == TR: | |
del_list.append(s3['Name']) | |
#print(del_list) | |
diffset = set(all_list) – set(del_list) | |
#print(diffset) | |
targetlist = list(diffset) | |
#print(targetlist) | |
for target in targetlist: | |
#print target | |
# #print type(target) | |
response = client.delete_bucket( | |
Bucket=target | |
) |
# coding: utf-8 | |
#EC2 SecurityGroups delete | |
import boto3 | |
# nodelete,trueを変数化 | |
ND = 'nodelete' | |
TR = 'true' | |
def lambda_handler(event, context): | |
#if __name__ == '__main__': #EC2上 | |
ec2 = boto3.client('ec2') | |
resp = ec2.describe_security_groups() | |
all_list = [] | |
del_list = [] | |
#print (resp) | |
for securitygroups in resp['SecurityGroups']: | |
for groupid in securitygroups['GroupId']: | |
all_list.append(securitygroups['GroupId']) | |
#print(all_list) | |
if 'Tags' in securitygroups: | |
for tag in securitygroups['Tags']: | |
#print(tag) | |
if tag['Key'] == ND and tag['Value'] == TR: | |
del_list.append(securitygroups['GroupId']) | |
#print(del_list) | |
diffset = set(all_list) – set(del_list) | |
#print(diffset) | |
targetlist = list(diffset) | |
#print(targetlist) | |
resp = ec2.delete_security_group( | |
GroupId=targetlist | |
) |
##スナップショットのTagsでKeyが「nodelete」Valueが「true」以外削除 | |
# coding: utf-8 | |
#EC2 snapshot delete | |
import boto3 | |
# nodelete,trueを変数化 | |
ND = 'nodelete' | |
TR = 'true' | |
def lambda_handler(event, context): | |
#if __name__ == '__main__': #EC2上 | |
ec2 = boto3.client('ec2') | |
resp = ec2.describe_snapshots() | |
all_list = [] | |
del_list = [] | |
#print (resp) | |
for snapshots in resp['Snapshots']: | |
for snapshotid in snapshots['SnapshotId']: | |
all_list.append(snapshots['SnapshotId']) | |
#print(all_list) | |
if 'Tags' in snapshots: | |
for tag in snapshots['Tags']: | |
#print(tag) | |
if tag['Key'] == ND and tag['Value'] == TR: | |
del_list.append(snapshots['SnapshotId']) | |
#print(del_list) | |
diffset = set(all_list) – set(del_list) | |
#print(diffset) | |
targetlist = list(diffset) | |
#print(targetlist) | |
resp = ec2.delete_snapshot( | |
GroupId=targetlist | |
) |
#Keyがnodelete、Valueがtrue以外は削除 | |
# coding: utf-8 | |
# EC2 terminate | |
import boto3 | |
#nodelete,trueを変数化 | |
ND = 'nodelete' | |
TR = 'true' | |
def lambda_handler(event, context): | |
#if __name__ == '__main__': #EC2上で | |
client = boto3.client('ec2') | |
resp = client.describe_instances() | |
all_list = [] | |
del_list = [] | |
for reservation in resp['Reservations']: | |
for instance in reservation['Instances']: | |
all_list.append(instance['InstanceId']) | |
#print(all_list) | |
if 'Tags' in instance: | |
#nodelete以外は削除 | |
for tag in instance['Tags']: | |
if tag['Key'] == ND and tag['Value'] == TR: | |
del_list.append(instance['InstanceId']) | |
#print(del_list) | |
diffset = set(all_list) – set(del_list) | |
#print(diffset) | |
targetlist = list(diffset) | |
#print(targetlist) | |
ec2.terminate_instances( | |
InstanceIds=targetlist | |
) |
■実際にテスト
今回はインスタンスをterminateするスクリプトでやってみます。
実際にまずは削除プログラムをコメントアウトして、
インスタンスIDがタグ判別で出力されるかやってみましょう。
■定期実行
Cloud Watchからイベントでルールの新規作成をします。
スケジュールを選択肢し、
ターゲットの追加で先程のLambdaを以下のように追加します。
追加するとLambdaのマネジメントコンソールから
Triggerに反映されているはずです。
■まとめ
始めはec2建ててaws cliで頑張ろうとしたが、
らむださんすごい。サーバ作らなくてもOK!自動化したときの嬉しさ!
他にもELBやらRDSやら削除できるので次回ブログしていきます。
そしてjsonとPythonの基本勉強しよう。
やっぱコードとか実際に課題にそって作るのが一番覚えると思う!
参考書は逆引きな感じで。
※ちなみにEC2から実行する場合は(もともとインスタンスにPythonが入っているので)
以下のようにしないとあかん。
・boto3のインストール
1 | $ sudo pip install boto3 |
・Pythonスクリプトの変更
1 2 3 | #def lambda_handler(event, context): #Lambdaの場合 if __name__ == '__main__': #EC2の場合 client = boto3.client('rds', "ap-northeast-1") #リージョンの追加 |
参考:
http://boto3.readthedocs.io/en/latest/index.html
http://qiita.com/Yuki_BB3/items/bf713a5141ea59b741dc
http://qiita.com/Yuki_BB3/items/7885e06f82bebfa8a3bb
0件のコメント