【コスト削減】すべてのリージョンにある利用されていないEBS(EBS Volume)をスクリプトで特定してみる

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

こんにちは!エンタープライズクラウド部技術2課の日高です。
本日は下記画像のように使用可能になっているものの利用されずに残っているEBS Volume(今後はEBSと表記)を特定するスクリプトを作成してみました。

スクリプトを利用するだけの場合は「作成スクリプトとその使い方」を、スクリプトの詳細を知りたい方は「スクリプトの詳細」をご覧ください。

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

前提

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

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

作成したスクリプト

使用可能になっているものの利用されずに残っているEBS Volumeを特定し、OUTPUT_FILEで指定したファイルに書き込むスクリプトになります。(下記の設定では"available_volumes.txt")

#!/bin/bash -eu

# 使用するプロファイル名
PROFILE="myprofile"

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

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

# 各リージョンで "Available" 状態のEBSボリュームを見つける
for region in $REGIONS
do
    echo "Checking region $region" >> $OUTPUT_FILE
    VOLUMES=$(aws ec2 describe-volumes --region $region --profile $PROFILE --filters Name=status,Values=available --query "Volumes[].VolumeId" --output text)
    if [ -z "$VOLUMES" ]; then
        echo "No available volumes in region $region" >> $OUTPUT_FILE
    else
        echo "Available volumes in region $region:" >> $OUTPUT_FILE
        for volume in $VOLUMES
        do
            echo $volume >> $OUTPUT_FILE
        done
    fi
done

利用方法

準備

  • 上記のスクリプトを実行するフォルダ配下に作成する。

※この際PROFILE="myprofile"OUTPUT_FILE="available_volumes.txt"は用途に合わせて書き換えてください。

実行コマンド

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

スクリプトの実行結果

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

スクリプトの実行結果は、以下の画像のようにAvailable volumes in region <リージョン名>と、そのリージョンにある使用可能になっているものの利用されずに残っているEBS VolumeのIDが、「available_volumes.txt」(出力ファイルをOUTPUT_FILE="available_volumes.txt"にしているため)に出力されます。

スクリプトの詳細

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

#!/bin/bash -eu

# 使用するプロファイル名
PROFILE="myprofile"

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

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

# 各リージョンで "Available" 状態のEBSボリュームを見つける
for region in $REGIONS
do
    echo "Checking region $region" >> $OUTPUT_FILE
    VOLUMES=$(aws ec2 describe-volumes --region $region --profile $PROFILE --filters Name=status,Values=available --query "Volumes[].VolumeId" --output text)
    if [ -z "$VOLUMES" ]; then
        echo "No available volumes in region $region" >> $OUTPUT_FILE
    else
        echo "Available volumes in region $region:" >> $OUTPUT_FILE
        for volume in $VOLUMES
        do
            echo $volume >> $OUTPUT_FILE
        done
    fi
done

シェルスクリプト

  • #!/bin/bash -eu
    • この行は「shebang」または「hashbang」と呼ばれ、スクリプトを実行する際にどのシェルを使用するかを指定します
    • -eはエラーが起きた時にスクリプトの実行を停止させ、-uは未定義の変数が使われた場合にエラーを出力します。
  • PROFILE="myprofile"
    • 変数PROFILEに文字列 "myprofile" を設定しています。この"myprofile"はAWS CLIが使用するプロファイル名を示します。
  • OUTPUT_FILE="available_volumes.txt"
    • 変数OUTPUT_FILEに文字列 "available_volumes.txt" を設定しています。
    • この"available_volumes.txt"は出力するテキストファイルの名前を示します。
  • for region in $REGIONS
    • REGIONS変数の各要素(リージョン名)に対してループを開始します。
  • echo "Checking region $region" >> $OUTPUT_FILE
    • 現在のリージョン名をテキストファイルに出力します。
    • >> は出力リダイレクトを示し、既存のファイルに追加する形で出力します。
  • if [ -z "$VOLUMES" ]; then
    • VOLUMES変数が空(つまり、"Available" 状態のEBSボリュームがない)場合、次のecho文を出力します。
  • else :
  • この部分のコードは、if に対応する条件が偽 (false) の場合に実行されます。
  • つまり、 $VOLUMES 変数が空でない場合(つまり、"Available" 状態のEBSボリュームが一つでも見つかった場合)に実行されます。
  • echo "Available volumes in region $region:" >> $OUTPUT_FILE
    • 現在のリージョンで "Available" 状態のEBSボリュームが見つかったことを示すメッセージをテキストファイルに出力します。
  • for volume in $VOLUMES
    • $VOLUMES 変数に含まれる各要素(ボリュームID)に対してループを開始します。
  • echo $volume >> $OUTPUT_FILE
    • 現在のボリュームIDをテキストファイルに出力します。
  • done
    • for ループの終了を示します。
  • fi
    • if 文の終了を示します。
  • 最後の done
    • 最初の for ループ(リージョンを走査するループ)の終了を示します。

AWS CLI

aws ec2 describe-regions --profile $PROFILE --query "Regions.{Name:RegionName}" --output text : describe-regions

  • aws ec2 describe-regions
    • EC2 (Elastic Compute Cloud) サービスを使用して、利用可能なリージョンの情報を取得するためのコマンドです。
  • --profile $PROFILE
    • プロファイルを指定するオプションです。
    • AWS CLIの設定ファイル (~/.aws/config) 内に定義されたプロファイル名を指定します。
    • プロファイルは、アクセスキーとシークレットアクセスキーなどの認証情報を関連付けるために使用されます。$PROFILEは、実際のプロファイル名に置き換える必要があります。
  • --query "Regions.{Name:RegionName}"
    • レスポンスから特定のフィールドを抽出するためのオプションです。
    • このクエリでは、Regions 配列内の各要素から RegionName フィールドを抽出しています。
  • --output text
    • 出力形式を指定するオプションで、結果をテキスト形式で表示します。

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

docs.aws.amazon.com

aws ec2 describe-volumes --region $region --profile $PROFILE --filters Name=status,Values=available --query "Volumes.VolumeId" --output text

  • aws ec2 describe-volumes
    • EBSボリュームの情報を取得するためのコマンドです。
  • --region $region
    • リージョンを指定するオプションです。
    • $regionは、実際のリージョン名に置き換える必要があります。
  • --profile $PROFILE
    • プロファイルを指定するオプションです。
    • AWS CLIの設定ファイル (~/.aws/config) 内に定義されたプロファイル名を指定します。
    • プロファイルは、アクセスキーとシークレットアクセスキーなどの認証情報を関連付けるために使用されます。$PROFILEは、実際のプロファイル名に置き換える必要があります。
  • --filters Name=status,Values=available
    • フィルタを指定するオプションです。
    • この場合、status フィールドが "available" という値のボリュームのみを取得します。
  • --query "Volumes.VolumeId"
  • レスポンスから特定のフィールドを抽出するためのオプションです。
    • このクエリでは、Volumes 配列内の各要素から VolumeId フィールドを抽出しています。
  • --output text
    • 出力形式を指定するオプションで、、結果をテキスト形式で表示します。

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

docs.aws.amazon.com

コスト削減効果

現状(2023年6月16日)かかるAmazon EBSの料金は、以下になります。

  • 汎用 SSD (gp3) - ストレージ:0.096USD/GB 月
  • 汎用 SSD (gp3) - IOPS:無料の 3,000 IOPS、および 3,000 を超えた分について 1 か月におけるプロビジョンド IOPS あたり 0.006USD
  • 汎用 SSD (gp3) - スループット:無料の 125 MB/秒、および 125 を超えた分について 1 か月におけるプロビジョンド MB/秒あたり 0.048USD
  • 汎用 SSD (gp2) ボリューム:1 か月にプロビジョニングされたストレージ 1 GB あたり 0.12USD
  • プロビジョンド IOPS SSD (io2) - ストレージ:0.142USD/GB 月
  • プロビジョンド IOPS SSD (io1) ボリューム:1 か月にプロビジョニングされたストレージ 1 GB あたり 0.142USD、さらに 1 か月にプロビジョニングされた IOPS あたり 0.074USD
  • スループット最適化 HDD (st1) ボリューム :1 か月にプロビジョニングされたストレージ 1 GB あたり 0.054USD
  • Cold HDD (sc1) ボリューム :0.018USD/プロビジョニングされたストレージの GB-月
  • プロビジョンド IOPS SSD (io2) - IOPS
    • 1 か月におけるプロビジョンド IOPS (最大 32,000 IOPS まで) あたり 0.074USD
    • 1 か月におけるプロビジョンド IOPS (最大 32,001~64,000 IOPS) あたり 0.052USD
    • 1 か月におけるプロビジョンド IOPS (64,000 IOPS 超) あたり 0.036USD†

例えば、使用可能な状態で利用していないEBS(汎用 SSD (gp3) )が合計1000 GiBあった場合、削除すると下記のコスト削減効果があります。

1000GiB×0.096USD×1ヵ月=96USD/月

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

aws.amazon.com

まとめ

容量が大きいEBSボリュームを放置しているとかなりの料金がかかってしまうことが分かりました。

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

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

blog.serverworks.co.jp

blog.serverworks.co.jp

blog.serverworks.co.jp

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

2024 Japan AWS Jr. Champions / 2024 Japan AWS All Certifications Engineers

EC部クラウドコンサルティング課所属。2022年IT未経験でSWXへ新卒入社。
記事に関するお問い合わせや修正依頼⇒ hidaka@serverworks.co.jp