【AWS】Lambda用のNAT Gatewayの自動起動・終了


NAT Gatewayのコスト

東京リージョンの場合は下記の料金が発生します。
$0.062 per NAT Gateway Hour

自動化したい作業を手動で確認

NAT Gatewayを削除してみる

ルートを編集する

VPCのルートテーブルのページに移動し、ルートの編集を指定する。

下記の設定項目を削除する

送信先:0.0.0.0/0
ターゲット:nat-(作成したやつ)

NATゲートウェイの削除

VPCのNATゲートウェイの設定画面に移動し、NATゲートウェイの削除

Elastic IPの解放

VPCのElasticIPの設定でアドレスの解放を行う

NATゲートウェイを復元してみる

NATゲートウェイの作成

VPCのNATゲートウェイの設定画面に移動し、NATゲートウェイの作成

作成時にElastic IPを割り当てることができるので、ここで割り当ててしまう。

ルートテーブルの編集

NATゲートウェイにルーティングしたいルートテーブルを選択し、下記の設定を行います。

送信先:0.0.0.0/0
ターゲット:nat-(作成したやつ)

Elastic IP名の修正

NATゲートウェイの作成時に生成されたElastic IPに名前を付けておきます。
※必ず付ける必要はありませんが、多くなると管理できなくなる為、付けておいた方が良いと思います。

構成

今回は、決まった時間に自動起動・終了するようにしたいと思います。
以下の図のように、CloudWatch Events をトリガーにし、Lambdaを動作させる構成にします。

操作する内容は以下の通りです。

■ NAT GateWay 起動時
1. 月曜~金曜 朝9時に実行
2. Elastic IPの作成
3. NAT GateWayの作成
4. サブネットのルートテーブルにNAT GateWayを割り当て

■ NAT GateWay 終了時
1. 月曜~金曜 夜7時に実行
2. サブネットのルートテーブルからNAT GateWayをデタッチ
3. NAT GateWayの削除
4. Elastic IPの解放

起動処理の自動化

実行ロールの作成

IAMのロール作成画面から、ロールを作成します。

必要なポリシーは
- CloudWatchLogsFullAccess
- AmazonVPCFullAccess
- AWSLambdaBasicExecutionRole
の3点です。
ロール名は適当な物を付けてください。

Lambdaの作成

関数の作成ページから、設計図の使用を選択し、キーワードにlambda-canaryを指定し、lambda-canaryを選択して、設定ボタンを押す。

基本的な情報

要素 設定
関数名 任意の名前
実行ロール 既存のロールを使用する
既存のロール 上記の手順で作成したロールを選択してください

CloudWatch Events トリガー

要素 設定
ルール 新規ルールの作成
ルール名 NAT_Start
ルールの説明 Create Elastic IP and NAT gateway.
スケジュール式 cron(0 0 ? * MON-FRI *)

※スケジュール式は、協定世界時(UTC)なので注意してください。
スケジュール式の時差について

トリガーの有効化については、チェックを外しておいてください。

ソースコードと環境変数は後ほど編集しますので、そのまま関数の作成をクリックしてください。

ソースコード

起動自動化
import os
import boto3
import logging
import json

""" ログ設定 """
logger = logging.getLogger()
logger.setLevel(logging.INFO)

""" 変数設定 """
subnet = os.environ['SUBNET_ID']

client = boto3.client('ec2')

def allocate_Eip():
    """ Elastic IPの取得処理 """
    response = client.allocate_address(Domain='vpc')
    return response.get('AllocationId')

def start_natgw(Eip,Subnet):
    """ NAT GateWayの開始処理 """
    response = client.create_nat_gateway(
        AllocationId=eip,
        SubnetId=Subnet
    )
    natid = response['NatGateway']['NatGatewayId']
    client.get_waiter('nat_gateway_available').wait(NatGatewayIds=[natid])
    return(natid)

def atatch_natgw(natgw, Subnet):
    """ サブネットへの割り当て処理 """
    filters = [ { 'Name': 'association.subnet-id', 'Values': [Subnet] } ]
    response = client.describe_route_tables(Filters = filters)
    rtb = response['RouteTables'][0]['Associations'][0]['RouteTableId']
    response = client.create_route(
        DestinationCidrBlock = '0.0.0.0/0',
        NatGatewayId = natgw,
        RouteTableId = rtb
    )

def lambda_handler(event, context):
    logging.info('■ 開始')
    eip = allocate_Eip()
    natgw = start_natgw(eip, Subnet)
    atatch_natgw(natgw, Subnet)
    logging.info('■ 終了')

終了処理の自動化

実行ロールの作成

起動時用に作成したものを利用します。

Lambdaの作成

関数の作成ページから、設計図の使用を選択し、キーワードにlambda-canaryを指定し、lambda-canaryを選択して、設定ボタンを押す。

基本的な情報

要素 設定
関数名 任意の名前
実行ロール 既存のロールを使用する
既存のロール 上記の手順で作成したロールを選択してください

CloudWatch Events トリガー

要素 設定
ルール 新規ルールの作成
ルール名 NAT_Stop
ルールの説明 Delete Elastic IP and NAT gateway.
スケジュール式 cron(0 10 ? * MON-FRI *)

※スケジュール式は、協定世界時(UTC)なので注意してください。
スケジュール式の時差について

トリガーの有効化については、チェックを外しておいてください。

ソースコードと環境変数は後ほど編集しますので、そのまま関数の作成をクリックしてください。

ソースコード