LINEで送る
Pocket

今回は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で返ってきます。
今回は以下のコマンドで確認します。

ダーッとインスタンス情報なり、スナップショットの情報が出てくるかと。

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']
)

view raw
delete-eip.py
hosted with ❤ by GitHub

# 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
)

view raw
delete-elb-alb.py
hosted with ❤ by GitHub

# 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,
)

view raw
delete-rds.py
hosted with ❤ by GitHub

# 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
)

view raw
delete-s3.py
hosted with ❤ by GitHub

# 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のインストール

・Pythonスクリプトの変更

参考:
http://boto3.readthedocs.io/en/latest/index.html
http://qiita.com/Yuki_BB3/items/bf713a5141ea59b741dc
http://qiita.com/Yuki_BB3/items/7885e06f82bebfa8a3bb

LINEで送る
Pocket

カテゴリー: AWSboto3Python

adachin

1989年生まれのLancers SRE。 ホスティングから大規模なアドテクなどのインフラエンジニアとして携わり、AnsibleやTerraformでのインフラコード化を推進。副業では数社サーバー保守、未経験によるエンジニアのメンターなども実施している。また、「脆弱性スキャナVuls」のOSS活動もしており、自称エバンジェリスト/技術広報/テクニカルサポート/コントリビュータでもある。現在はサービスの信頼性向上、可用性、レイテンシ、パフォーマンス、モニタリング、緊急対応、インフラコード化、リファクタリング、セキュリティ強化、新技術の検証、Docker開発環境の提供、AWSでのインフラ構築、グループ会社のインフラをECS/Fargateへ移行、CakePHP4での管理画面作成、メンター、分析基盤の運用を担当している。

0件のコメント

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください