はじめに
以前、「関連づけられてないEIPをSlack通知 & 削除するLambda」を作成しました。
今回は上記のLambdaを応用し、何も関連づけられていない(= 「使用可能」状態)のEBSボリュームを削除するLambdaを作成してみました。
なぜ、作成するに至ったかというと、自分の所属するチームの検証環境には59台の「使用可能」状態のEBSが存在しており、毎月3000円ほど無駄な費用がかかっていたためです。
また、「使用可能」状態のEBSは「終了時に削除」が有効化されていないAMIからインスタンスを作成してしまうと、作成者の意図しないところで湧き出すのです。
なので、定期的に駆除したいと感じていました。
仕様
- 検証環境に存在する何も紐づけられていないEBSをSlack通知・削除(全リージョン)
- Amazon EventBridgeと組み合わせて毎日定時で実行
- 容赦ない削除、慈悲はない
- 削除されたくない場合、以下で回避可能
- EC2に紐づけておく
- スナップショットを取得しておく
- 以下のようなSlack通知
「何も関連づけられていないEBSボリュームはお金かかるし必要ないよね!?」
「消されるのが嫌だったらスナップショットを取得しておいてね!」
という気持ちで作っております。
作成方法
Lambdaの中身であるpythonスクリプトや権限以外はEIP削除用Lambdaと同じです
作成までの流れ
今回はpythonのファイルと外部モジュールをzipパッケージ化してLambdaへアップロードします。
手順は以下となります。
- Cloud9でzipパッケージを作成
- Lambdaを作成
- Amazon EventBridgeのルール作成
1. Cloud9でzipパッケージを作成
1-1. Cloud9のコンソールで[Create environment]をクリック
1-2. 名前を適当につけて[Next Step]
1-3. 以降のステップは何も変更しないで[Next Step] > [Create environment]
1-4. Cloud9が起動したら、ターミナルで以下のコマンドを実行
# ディレクトリを作成し、作成したディレクトリへ移動
$ mkdir lambda_workspace && cd lambda_workspace
# Lambdaに呼び出されるPythonのファイルを作成
$ touch lambda_function.py
1-5. 「lambda_function.py」を開き、以下のスクリプトをコピペして保存
# coding:utf-8
import datetime
from http import client
import os
import json
import boto3
import pytz
import requests
SLACK_WEBHOOK_URL = os.environ['SLACK_WEBHOOK_URL']
SLACK_CHANNEL = os.environ['SLACK_CHANNEL']
def get_instances():
client = boto3.client('ec2')
regions = client.describe_regions()['Regions']
instances = []
for region in regions:
client = boto3.client('ec2', region_name=region['RegionName'])
response = client.describe_volumes(
Filters=[
{
'Name': 'status',
'Values': [
'available',
]
},
]
)
volumes = response['Volumes']
if not volumes:
continue
for volume in volumes:
instance = dict()
instance['id'] = volume['VolumeId']
tags = volume.get('Tags')
instance['name'] = 'null'
instance['owner'] = 'null'
if tags is not None:
for tag in tags:
if tag['Key'] == 'Name':
instance['name'] = tag['Value']
elif tag['Key'] == 'Owner':
instance['owner'] = tag['Value']
elif tag['Key'] == 'owner':
instance['owner'] = tag['Value']
instance['type'] = volume['VolumeType']
instance['size'] = volume['Size']
instance['region'] = region['RegionName']
instances.append(instance)
return instances
def delete_volume(instances):
if not instances:
return None
for instance in instances:
client = boto3.client('ec2',region_name=instance['region'])
client.delete_volume(VolumeId=instance['id'])
def build_message(instances):
if not instances:
return None
now = datetime.datetime.now(pytz.timezone('Asia/Tokyo'))
text = '{} アタッチされていないEBS一覧'.format(now.strftime('%Y年%m月%d日%H時%M分'))
atachements_text = ''
for instance in instances:
atachements_text += '削除→ name: {}, type: {}, size: {}GB, id: {}, region: {}\n'.format(
instance['name'], instance['type'], instance['size'], instance['id'], instance['region'])
atachements = {'text': atachements_text, 'color': 'red'}
message = {
'text': text,
'channel': SLACK_CHANNEL,
'attachments': [atachements],
}
return message
def post_message(message):
response = requests.post(SLACK_WEBHOOK_URL, data=json.dumps(message))
response.raise_for_status()
def lambda_handler(event, context):
instances = get_instances()
message = build_message(instances)
if message:
post_message(message)
delete_volume(instances)
1-6. Cloud9のターミナルで以下のコマンドを実行
# 必要なライブラリ(pytzとrequests)を「lambda_workspace」のディレクトリへインストール
$ pip install pytz -t .
$ pip install requests -t .
# 「lambda_workspace」のディレクトリの中身をzip圧縮
$zip -r lambda_workspace.zip *
2. Lambdaを作成
2-1. Lambdaのコンソールで[関数の作成]をクリック
2-2. 任意の関数名を入力し、ランタイムに「Python3.9」を選択し、[関数の作成]をクリック
2-3. 作成されたLambdaの[コード]タブから[アップロード元] > [.zipファイル]をクリック
2-4. 1の手順で作成したzipファイルをアップロード
2-5. [設定]タブ > [アクセス権限] > ロールをクリック
2-6. Lambdaのデフォルトロールにアタッチされているポリシーをクリック
2-7. [ポリシーの編集]をクリックし、ポリシーに以下の権限を追加
- ec2:DescribeRegions
- ec2:DescribeVolumes
- ec2:DeleteVolume
2-8. 作成したLambdaの[設定]タブから[環境変数] > [編集]をクリックし、以下を入力
(※値は適宜修正してください)
キー | 値 |
---|---|
SLACK_CHANNEL | 通知したいチャンネル名 |
SLACK_WEBHOOK_URL | SlackのWebhook URL (例:https://hooks.slack.com/services/~) |
2-9. 作成したLambdaの[設定]タブから[一般設定]でタイムアウトを3分に変更
3. Amazon EventBridgeの設定
※スケジュールで(毎日)Lambda実行したい場合はこの手順が必要
3-1. Amazon EventBridgeのコンソールで[ルール]をクリック
3-2. [名前]を適当に入れて[ルールタイプ]スケジュールを選択し[次へ]
3-3. Cron式でスケジュールを入力
以下の例は毎日18:00に実行される
3-4. ターゲットで前の手順で作成したLambdaを選択し[次へ]
3-5. あとは任意で設定し、ルールを作成
これで毎日18:00に何も関連付けられていないEBSを駆逐です!
おわりに
不要なEBSにお困りの皆様、是非こちらのLambdaをお使いください!!