【AWSコスト削減】NATゲートウェイ構築の自動化

aws-cost-reduction-natgwのアイキャッチ画像 AWS

NATゲートウェイはEC2のように停止することができず、存在するだけで課金され続けます。使うときだけNATゲートウェイを構築できればコスト削減につながります。
ここでは、ローカル環境からNATゲートウェイを構築・削除する方法を解説します。

IAMユーザーの用意

ローカル環境からAWSのNATゲートウェイを構築・削除できるように、アクセス権限を持つIAMユーザーを用意します。
基本的なIAMユーザーの追加方法は、こちらの「IAMポリシーの追加」「IAMユーザーの追加」を参考にして下さい。

IAMポリシーは以下のように設定します。

IAMポリシーの設定

IAMユーザー追加時のCSVファイルから、「アクセスキーID」「シークレットアクセスキー」を把握します。

NATゲートウェイ構築の自動化

事前準備

AWSのネットワーク構築方法はこちらを参考にして下さい。

AWSマネージメントコンソール > サービス > VPC > サブネットで、「サブネットID」を把握します。Public Subnetです。

AWSのサブネットID

AWSマネージメントコンソール > サービス > VPC > ルートテーブルで、「ルートテーブルID」を把握します。Public Subnetです。

AWSのルートテーブルID

ソースの用意

ローカルにPython環境を用意します。
環境構築方法は、こちらを参考にして下さい。

NATゲートウェイ構築用のPythonファイルは「C:\lambda\lambda_natgw_start.py」とし、以下のように実装します。 NATゲートウェイに割り当てられるグローバルIPアドレス(Elastic IPアドレス)は毎回異なるものになります。

import boto3

subnet = 'サブネットID'  # 控えておいたサブネットID
rtb = 'ルートテーブルID'  # 控えておいたルートテーブルID
client = boto3.client('ec2', region_name='ap-northeast-1', aws_access_key_id='アクセスキーID', aws_secret_access_key='シークレットアクセスキー')  # 控えておいたアクセスキーID、シークレットアクセスキー

def create_ip():
    result = client.allocate_address(
        Domain='vpc'
    )
    return result['AllocationId']

def start_natgw(eip):
    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):
    response = client.create_route(
        DestinationCidrBlock = '0.0.0.0/0',
        NatGatewayId = natgw,
        RouteTableId = rtb
    )

def main():
    eip = create_ip()
    natgw = start_natgw(eip)
    atatch_natgw(natgw)

main()

NATゲートウェイ削除用のPythonファイルは「C:\lambda\lambda_natgw_stop.py」とし、以下のように実装します。

import boto3
import time

subnet = 'サブネットID'  # 控えておいたサブネットID
rtb = 'ルートテーブルID'  # 控えておいたルートテーブルID
client = boto3.client('ec2', region_name='ap-northeast-1', aws_access_key_id='アクセスキーID', aws_secret_access_key='シークレットアクセスキー')  # 控えておいたアクセスキーID、シークレットアクセスキー
bDeletedIp = False

def detach_natgw():
    response = client.delete_route(
        DestinationCidrBlock = '0.0.0.0/0',
        RouteTableId = rtb
    )

def stop_natgw():
    filters = [{'Name': 'state', 'Values': ['available']}]
    response = client.describe_nat_gateways(Filters=filters)
    for rec in response['NatGateways']:
        print('----- delete natgw -----')
        print(rec)
        print('------------------------')
        natgw = rec['NatGatewayId']
        client.delete_nat_gateway(NatGatewayId=natgw)

def delete_ip():
    response = client.describe_addresses(
        Filters=[
            {'Name': 'domain','Values': ['vpc'] }
        ]
    )
    for rec in response['Addresses']:
        if "NetworkInterfaceId" not in rec:
            # 直ぐには割り当て解除されない
            print('----- delete eip -----')
            print(rec)
            print('----------------------')
            client.release_address(AllocationId=rec['AllocationId'])
            global bDeletedIp
            bDeletedIp = True

def main():
    detach_natgw()
    stop_natgw()
    while True:
        delete_ip()
        if bDeletedIp:
            return 0
        else:
            print('waiting deleting eip ...')
            time.sleep(30)

main()

動作確認

NATゲートウェイ構築

ローカル環境のコマンドプロンプトで以下を実行します。

python C:\lambda\lambda_natgw_start.py

NATゲートウェイ削除

ローカル環境のコマンドプロンプトで以下を実行します。

python C:\lambda\lambda_natgw_stop.py

以上で、NATゲートウェイ構築の自動化ができるようになりました。

参考:グローバルIPの固定

NATゲートウェイに割り当てられるグローバルIPアドレス(Elastic IPアドレス)を固定する方法です。

AWSマネージメントコンソール > サービス > VPC > Elastic IPで、Elastic IP アドレスの割り当てを行います。
同IPアドレスの「割り当てID(アロケーションID)」を把握します。

AWSのグローバルIPの割り当てID

NATゲートウェイ構築用のPythonファイル「C:\lambda\lambda_natgw_start.py」を以下のように書き換えます。

import os
import boto3

subnet = 'サブネットID'  # 控えておいたサブネットID
rtb = 'ルートテーブルID'  # 控えておいたルートテーブルID
client = boto3.client('ec2', region_name='ap-northeast-1', aws_access_key_id='アクセスキーID', aws_secret_access_key='シークレットアクセスキー')  # 控えておいたアクセスキーID、シークレットアクセスキー

# グローバルIPを固定にしたい場合は、使用したいElastic IPアドレスの割り当てIDを指定
eip = "割り当てID"

def start_natgw():
    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):
    response = client.create_route(
        DestinationCidrBlock = '0.0.0.0/0',
        NatGatewayId = natgw,
        RouteTableId = rtb
    )

def main():
    natgw = start_natgw()
    atatch_natgw(natgw)

main()

NATゲートウェイ削除用のPythonファイル「C:\lambda\lambda_natgw_stop.py」を以下のように書き換えます。

import boto3
import time

subnet = 'サブネットID'  # 控えておいたサブネットID
rtb = 'ルートテーブルID'  # 控えておいたルートテーブルID
client = boto3.client('ec2', region_name='ap-northeast-1', aws_access_key_id='アクセスキーID', aws_secret_access_key='シークレットアクセスキー')  # 控えておいたアクセスキーID、シークレットアクセスキー

def detach_natgw():
    response = client.delete_route(
        DestinationCidrBlock = '0.0.0.0/0',
        RouteTableId = rtb
    )

def stop_natgw():
    filters = [{'Name': 'state', 'Values': ['available']}]
    response = client.describe_nat_gateways(Filters=filters)
    for rec in response['NatGateways']:
        print('----- delete natgw -----')
        print(rec)
        print('------------------------')
        natgw = rec['NatGatewayId']
        client.delete_nat_gateway(NatGatewayId=natgw)

def main():
    detach_natgw()
    stop_natgw()
    # グローバルIPアドレスは削除しない

main()
タイトルとURLをコピーしました