【コスト削減】すべてのリージョンから利用されていない Elastic IP をスクリプトで特定してみる

記事タイトルとURLをコピーする

こんにちは!エンタープライズクラウド部技術2課の日高です。
EC2などに紐づいていないElastic IPには料金がかかってしまうことを皆さんご存知でしょうか。

ということで、すべてのリージョンで利用されていない Elastic IPを特定するスクリプトを作成してみました。
スクリプトを利用するだけの場合は「作成スクリプトとその使い方」を、スクリプトの詳細を知りたい方は「スクリプトの詳細」をご覧ください。

作成スクリプトとその使い方

前提

  • AWS CLIがインストールされている
  • Python3がインストールされている
  • スイッチロールできる設定が済まされている(AWS CLI の設定 (~/.aws/config ファイル) にて、ロールの情報が設定されている)
  • 実行環境のOSがUnix系

※スイッチロールではなく、デフォルトに設定されているアカウントでスクリプトを実行したい場合は、各スクリプトの「PROFILE=<CLIのプロファイル名>」と「--profile $PROFILE」を削除して利用してください。

作成したスクリプト

すべてのリージョンにある未使用状態のElastic IPを特定し、unused_ips.txtに出力するスクリプトです。

#!/bin/bash -eu

# AWS CLIのプロファイル名
PROFILE="your_profile_name"

# 出力ファイル名
OUTPUT_FILE="unused_ips.txt"

# 既存の出力ファイルがあれば削除
rm -f $OUTPUT_FILE

# すべてのAWSリージョンのリストを取得
REGIONS=$(aws ec2 describe-regions --query 'Regions[].{Name:RegionName}'  --profile $PROFILE --output text)

# 各リージョンでループ
for region in $REGIONS; do
    echo "Checking region $region..."

    # 各リージョンの未使用のElastic IPを検索
    IPS=$(aws ec2 describe-addresses --region $region --query 'Addresses[?AssociationId==null].PublicIp'  --profile $PROFILE --output text)

    # 未使用のIPがある場合、それらとそのリージョン名を出力ファイルに追加
    if [ -n "$IPS" ]; then
        for ip in $IPS; do
            echo "$region: $ip" >> $OUTPUT_FILE
        done
    fi
done

echo "Finished. Unused IPs and their regions are listed in $OUTPUT_FILE"

利用方法

準備

  • 上記のスクリプトを実行するフォルダ配下に作成する。
  • この際your_profile_nameunused_ips.txt(出力ファイル名をunused_ips.txt以外にした場合)は書き換える。

実行コマンド

  • 下記コマンドを実行します。
  • bash <保存時のスクリプト名>
    • 私は「get_eip.sh」で保存しているのでbash get_eip.shが実行コマンドになります。

スクリプトの実行結果

スクリプトの実行画面は以下のようになります。
スイッチロールする際に、MFAを強制しているので下記画像ではMFAの入力が求められています。

スクリプトの実行結果はこのように未使用状態のElastic IPと、そのElastic IPが存在するリージョンが「unused_ips.txt」に出力されます。

スクリプトの詳細

シェルスクリプトの部分とAWS CLIの部分に分けて解説します。

#!/bin/bash -eu

# AWS CLIのプロファイル名
PROFILE="your_profile_name"

# 出力ファイル名
OUTPUT_FILE="unused_ips.txt"

# 既存の出力ファイルがあれば削除
rm -f $OUTPUT_FILE

# すべてのAWSリージョンのリストを取得
REGIONS=$(aws ec2 describe-regions --query 'Regions[].{Name:RegionName}'  --profile $PROFILE --output text)

# 各リージョンでループ
for region in $REGIONS; do
    echo "Checking region $region..."

    # 各リージョンの未使用のElastic IPを検索
    IPS=$(aws ec2 describe-addresses --region $region --query 'Addresses[?AssociationId==null].PublicIp'  --profile $PROFILE --output text)

    # 未使用のIPがある場合、それらとそのリージョン名を出力ファイルに追加
    if [ -n "$IPS" ]; then
        for ip in $IPS; do
            echo "$region: $ip" >> $OUTPUT_FILE
        done
    fi
done

echo "Finished. Unused IPs and their regions are listed in $OUTPUT_FILE"

シェルスクリプト

  • #!/bin/bash -eu
    • この行はshebangと呼ばれ、スクリプトがbashシェルを使用して実行されることを指定します。
    • -euオプションはエラーハンドリングに関連しており、 -eはスクリプトがエラーを発生させたときに停止し、-uは未定義の変数が参照されたときにスクリプトを停止します。
  • PROFILE="your_profile_name" :
    • これはプロファイル名を格納する変数を設定します。
    • your_profile_nameは、AWS CLIの設定に記述されたプロファイル名に置き換える必要があります。
  • OUTPUT_FILE="unused_ips.txt" :
    • 出力するテキストファイルの名前を定義します。
  • rm -f $OUTPUT_FILE
    • スクリプトが再実行されるときに、前の実行結果を消去するために、既存の出力ファイルを削除します。
  • for region in $REGIONS; do ... done
    • このforループは、各AWSリージョンで操作を行います。 *if [ -n "$IPS" ]; then ... fi
    • このif文は、特定のリージョンで未使用のElastic IPが存在する場合に、それらのIPを出力ファイルに書き込みます。
  • echo "Finished. Unused IPs and their regions are listed in $OUTPUT_FILE"
    • スクリプトの実行が終了したら、結果が保存されたファイル名を出力します。

AWS CLI

  • aws ec2 describe-addresses --region $region --query 'Addresses[?AssociationId==null].PublicIp' --profile $PROFILE --output text
    • aws ec2 describe-addresses
      • describe-addressesはEC2サービスのコマンドで、アカウントに関連付けられているすべてのElastic IPアドレスの情報を取得します。
    • --region $region
      • このフラグはAWSリージョンを指定します。
      • ここでは、シェルスクリプトの for ループにより各リージョンが順にセットされます。
    • --query 'Addresses[?AssociationId==null].PublicIp'
      • --queryオプションは、戻されたJSON形式の出力をフィルタリングし、特定のフィールドのみを取り出すために使用します。
      • ここでは、AssociationId==nullという条件でフィルタリングを行い、関連付けられていない(つまり未使用の)Elastic IPアドレスのみを取り出します。
      • そして、それらのElastic IPのパブリックIP部分(.PublicIp)のみを取得します。

※詳しくは以下をご覧ください

docs.aws.amazon.com

コスト削減効果

現在(2023年6月14日)インスタンスと関連付けられていない Elastic IP アドレスは東京リージョンの場合、0.005 USD/時です。

例えば、10個のインスタンスと関連付けられていない Elastic IP を特定し削除すると下記の計算式のようになります。
10個×0.005USD × 24時間 × 30日 = 36USD

つまり、10個のインスタンスと関連付けられていない Elastic IP を削除すると1か月(30日と仮定すると)当たり36USDほどのコスト削減効果があります。

※ Elastic IPの料金については、詳しくは以下をご覧ください

aws.amazon.com

まとめ

意外とインスタンスと関連付けられていない Elastic IPを放置しているとコストがかかることが分かりました。
積極的に使っていない Elastic IPを削除していきましょう!

本記事が誰かの助けになれば幸いです。

他にもコスト削減に役立つスクリプトを書いているのでよかったらご覧ください!

blog.serverworks.co.jp

日高 僚太(執筆記事の一覧)

EC部ソリューションアーキテクト2課 / AWS認定資格 12冠

2022年IT未経験で新卒入社しました。
最近はダーツとサウナが気になっています!
記事に関するお問い合わせや修正依頼⇒ hidaka@serverworks.co.jp