AWS Lambda

Lambdaで関連付けされていないElasticIPを解放する

はじめに

こんにちは、omkです。

最近は社内のAWS検証環境のコストの削減に取り組んでいます。
AWSの良いところといえば検証用にサーバを立てて用がなくなればそのまま消してしまえるところだと思います。
しかし、EC2インスタンスを消してもEBSやEIPはそのまま残り続け、消さない限りは費用が掛かります。

社内の検証環境でもいくつか使っていないEIPが発生していたので解放しておいたのですが、手動で管理するのも面倒なのでCloudWatchイベントで定期的にLambdaを起こして消していきます。

ElasticIPの料金について

EIPの料金は以下に記載があります。
https://aws.amazon.com/jp/ec2/pricing/on-demand/#Elastic_IP_Addresses
1つの実行中のインスタンスに対してEIPを1つ無料で付けることが出来ます。それ以降は有料です。
また、実行されていないインスタンスに関連付けられたEIP、関連付けられていないEIPに対して費用が掛かります。

今回は関連付けられていないEIPをすべて解放してこちらで掛かる費用を削減します。

実装

CloudWatchイベントは平日の20時に実行されることとします。

00 11 ? * 2-6 *

これのターゲットをLambdaに設定します。

では、Lambda関数を記述していきます。今回はRuby2.7でAWS SDKを使用して実装します。

require 'json'
require 'aws-sdk'

# 割り当てられていないEIPの解放
def lambda_handler(event:, context:)
    # 全EIPの情報取得
    ec2_client = Aws::EC2::Client.new(region: "ap-northeast-1")
    adresses = ec2_client.describe_addresses({})
    for i in 0..(adresses[0].length - 1)
        if(adresses[0][i].association_id == nil) then
            # アソシエ―ションID == nil のとき関連付けなし
            # 解放
            resp = ec2_client.release_address({
                allocation_id: adresses[0][i].allocation_id,
            })
        end
    end
end

流れとしては、EIPの情報をすべて取得してそれぞれのアソシエーションIDを確認、アソシエーションIDが設定されていない場合は解放する、というものです。

アソシエーションIDについてのドキュメントは見つけられなかったのですが、EC2インスタンスやNATゲートウェイに(そもそものENIに?)関連付けられているEIPについてはアソシエーションIDが付与されており、そうでないEIPには付与されていません。
また、関連付け先のEC2インスタンスやNATゲートウェイを削除した場合、関連がなくなりアソシエーションIDも消えます。

よって関連付けの有無をアソシエーションIDで判定し、このような処理になっています。
(因みにインスタンスIDはEIPがNATゲートウェイに関連づいている場合も空なので判定には使いませんでした)

まとめ

使って掛かる費用は大切ですが使わないことで掛かる費用は勿体ないですね。
忘れがちなところに使っていないリソースが溜まっていくのできれいにしましょう。