情報畑でつかまえてロゴ
本サイトは NTTテクノクロスが旬の IT をキーワードに
IT 部門が今知っておきたい最新テクノロジーに関する情報をお届けするサイトです

サーバレスでNAT Gatewayの起動・停止を管理してみた【押忍!ソフト道場】

今回はAWSにおける、サーバレスを用いたNAT Gatewayの費用削減のノウハウを展開いたします。

はじめに

こんにちは。NTTテクノクロスの渡邉です。
今回はAWSにおける、サーバレスを用いたNAT Gatewayの費用削減のノウハウを展開いたします。

サーバレスとは

本稿ではサーバレスを、以下の特徴を持つシステム、およびアーキテクチャと定義します。

  • イベントドリブンで駆動するアーキテクチャで構築される
  • VM・ネットワーク管理をクラウド事業者に委ねる(PaaS or SaaSを含む)ことで、運用負荷が低いシステム
  • 実行に必要なコンピューティングリソースは自動で割り当てられ、必要に応じて自動でスケールされる

サーバレスで構成されるシステムは、適切に設計することで、コンピューティングリソースの占有時間を少なく利用できるため、IaaSに比べて安価に利用できる場合が多い、というメリットもあります。
AWSにおいては「Lambdaとマネージドサービスで作られる、EC2を利用しないシステム」と捉えても良いでしょう。

余談ですが、今年度から社内研修として「AWSサーバレスアーキテクチャ研修」を開催できることが決まりました!
半年前のブログで語った野望がようやく叶いました。何でも言ってみるものですね(笑)
今年秋の開催を目標に、講義資料を鋭意作成中です。

検証環境でよくある「NAT Gateway費用問題」

話が逸れましたが、本題に入りましょう。
前提として、次のような検証環境を用意するケースを想定します。

  • 製品調査(技術調査)のため、検証環境をAWS上に構築する
  • セキュリティを考慮し、検証用サーバはインターネットと直接に接しないNW上に配置する
  • 作成リソース、実行基盤の管理は必要最小限とする

上記の要件の場合、例えば以下の構成を思いつくのではないでしょうか?

image1

検証サーバをDMZ配下におき、インターネットへのアクセスはNAT Gatewayを用いる、シンプルな構成ですね。
ダイアグラムはこれで良いとして、大まかにコスト計算をしてみましょう。

要件整理・コスト計算

AWSのコスト計算の前に、インスタンスタイプや起動時間、リージョンなども考える必要がありそうです。
もう少し要件を整理してみましょう。

  • 検証用サーバはm4.large, 踏み台サーバはt2.nanoを利用する。
  • 検証は営業時間内のみで実施される。
    • よって、サーバを起動させる必要のある時間は、22(営業日)×8(時間)=176時間
  • 利用料金は日本リージョンで計算(2018/3月末時点のもの。)
  • EBS・NW費用などは、検証イメージが固まった段階で再び見積もる。

利用イメージが固まってきましたね。それでは、費用を見積もってみましょう。

image2

No.サーバインスタンスタイプA.1ヶ月付けっぱなしB.営業時間のみ起動(EC2)
1 踏み台サーバ t2.nano $ 5.57 $ 0.76
2 検証用サーバ m4.large $ 94.43 $ 20.64
3 NAT Gateway - $ 45.39 $ 45.39
- 合計金額 - $ 145.39 $ 66.79


A.案では、検証用環境としては思ったより費用がかかるかも?といったところ。
B.案では月々$66.79となり、A.案の半額以下で利用できそうです。コスト管理の重要性が分かりますね。

もしも、NAT Gatewayが停止できたなら

ここで気になるのは、NAT Gatewayの利用料金です。
2018/03現在、NAT Gatewayは起動・停止相当の操作が出来ないため、起動している限り一ヶ月分の利用料金が必要です。
NAT運用の手間から解放されると捉えれば、かなりお値打ちです。が、今回のような小さい構成の場合、 「サーバ代が約$21なのに、NATは倍の費用がかかるの?」 とコスト部門のメンバに質問されてしまうかもしれません。

仮にNAT Gatewayの起動・停止が出来れば、どの程度コストカットできるのでしょうか。計算してみます。

No.サーバインスタンスタイプA.1ヶ月付けっぱなしB.営業時間のみ起動(EC2) C.営業時間のみ起動(EC2 & NAT)
1 踏み台サーバ t2.nano $ 5.57 $ 0.76 $ 0.76
2 検証用サーバ m4.large $ 94.43 $ 20.64 $ 20.64
3 NAT Gateway - $ 45.39 $ 45.39 $ 9.92
- 合計金額 - $ 145.39 $ 66.79 $31.32

NATの起動時間を管理することで、更にコストを削減できますね!(パターンC)
全体費用が数百ドルを超えるような、大規模な商用システムの運用費としては、$35は大した金額ではないかもしれません。
ただ、今回のような「ちょっと使ってみる」環境として捉えた時、予算全体の4~5割を占める額です。

起動・停止相当を実現してコストダウン出来るかどうか、少し考えてみましょう。

NAT Gatewayの起動・停止をどのように実現するか

NAT Gatewayの主な利用目的としては、

  • DMZ越しにインターネット接続がしたい
  • 特定のIPアドレスでインターネット接続がしたい
  • NATサーバの運用管理から解放されたい

といったところでしょうか。 基本的な要件としては、NATサーバが同じIPアドレスを保持できれば、サーバの種類は問いません。
(= NAT Gatewayを一旦リリースしても良い。)

したがって、
・ NAT Gatewayの起動 = 特定のIPを持つNAT Gatewayの作成+VPC設定(ルートテーブル)
・ NAT Gatewayの停止 = 特定のIPを持つNAT Gatewayの削除+VPC設定(ルートテーブル)

と定義することで、擬似的に起動・停止の実現が可能です。
手作業で毎日作成・削除する、というのは当然避けたいのでバッチ化したいですよね。
せっかくAWSで運用しているので、ここはサーバレスで実現してみましょう。

サーバレスで起動・停止を実現する

前述の構成図に必要なバッチを追加しました。
今回は実行基盤を作り込まずにAPIを叩くのが目的なので、AWS BatchではなくLambdaで実行します。

image3

CloudWatch Eventsを始業時刻、終業時刻に設定し、それぞれバッチ(Lambda)を起動しています。
Lambdaを用いることで、Cron実行サーバ自体の管理や、Cron同士の排他制御から解放されるのも大きなメリットです。

1.起動バッチの作成

それでは、2つのバッチを設定していきましょう。
前提として、Lambdaに関しては、Python3.6で作成するものとします。

一から作成することもできますが、AWSが用意した構成を利用すれば、CloudWatch Events & Lambdaの構成を簡単に作成できます。
マネジメントコンソールのサービス欄から「lambda」を選択し、関数を作成しましょう。
lambda関数の作成で選択できる「設計図」から「lambda-canary-python3」を選択してください。

設定値は、以下の項目を更新します。

No.設定項目設定値
1 CloudWatch Eventsのスケジュール式 cron(0 0 ? * MON-FRI *)
2 IamRole AmazonVPCFullAccess, AWSLambdaBasicExecutionRole を設定したロール
3 環境変数 EIP_ID:<設定するEIPのアロケーションID>、SUBNET_ID:<サブネットID>
4 実行時間 180秒

CloudWatch Eventsのスケジュール式は、JSTではなくUTCで記載することに注意してください。
NAT Gatewayの構築に120秒程度かかるので、実行時間はそれより大きい値を設定する必要があります。
今回は余裕を見て、180秒としましょう。

Lambdaのソースコードは、以下のイメージで作成します。

  • 指定したSubnet、EIP情報を持つNAT Gatewayの作成
  • 作成完了をget_waiterで待つ ( ≒作成成功の確認 )
  • 作成したNAT Gatewayへのルーティング設定を追加する

今回は、下記のサンプルコードを設定してください。


import os import boto3
eip = os.environ['EIP_ID'] subnet = os.environ['SUBNET_ID']
client = boto3.client('ec2')
def start_natgw(Eip,Subnet): 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): natgw = start_natgw(eip, Subnet) atatch_natgw(natgw, Subnet)

2.停止バッチの作成

次に停止バッチを作成しましょう。
起動バッチと同じく、関数を設計図「lambda-canary-python3」から作成し、以下の設定を更新します。

No.設定項目設定値
1 CloudWatch Eventsのスケジュール式 cron(30 8 ? * MON-FRI *)
2 IamRole AmazonVPCFullAccess, AWSLambdaBasicExecutionRole を設定したロール
3 環境変数 SUBNET_ID:<サブネットID>

Lambdaのソースコードは、以下のイメージで作成します。

  • 作成したNAT Gatewayへのルーティング設定を削除
  • 指定したSubnetのNAT Gatewayの削除

今回は、下記のサンプルコードを設定してください。

import os
import boto3

Subnet = os.environ['SUBNET_ID']
client = boto3.client('ec2')
def stop_natgw(Subnet): filters = [ { 'Name': 'subnet-id', 'Values': [Subnet] }, { 'Name': 'state', 'Values': ['available'] } ] response = client.describe_nat_gateways(Filters=filters) natgw = response['NatGateways'][0]['NatGatewayId'] client.delete_nat_gateway(NatGatewayId=natgw)
def detach_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.delete_route( DestinationCidrBlock = '0.0.0.0/0', RouteTableId = rtb )
def lambda_handler(event, context): detach_natgw(Subnet) stop_natgw(Subnet)

これで起動・停止システムが完成しました! 簡単ですね。

サーバレス化でかかる諸費用

機能を実現したので満足してしまいそうですが、今回追加したサーバレスシステムに必要なコストもきちんと計算しましょう。
サーバレスでNATの起動管理をした場合のコスト削減結果は、最終的に下記の通りです!

image4

No.項目料金料金の考え方
1 lambda起動時間(NAT起動) $0.0054912 実行時間(概算:120000 ms)× 実行回数(営業日:22) × 128MBでの費用レート($/ms)
2 lambda起動時間(NAT停止) $0.00002288 実行時間(概算:500ms)× 実行回数(営業日:22) × 128MBでの費用レート($/ms)
3 EIP保持費用 $6.44 営業日(22日) × 16.5(営業日外の時間) + 休日(8日) × 24(時間)

Lambdaを活用することで、結果としてパターンBに比べ43%($29.03)の費用削減が出来ました! Lambda実行料金(No.1、No.2)については、おそらく無料枠の範囲で利用できるでしょう。 仮に支払うとしても、合計1円以下ですね。

ちなみに今回は紹介しませんが、NATのIPを固定する必要が無い場合は、更に$6程度のコストカットも可能です。 ユースケースに応じてlambdaをアレンジしてください。

おわりに

上記のようにサーバレスアーキテクチャを用いることで、オペレータの運用コストをかけずに、AWS費用を簡単に削減できました。
サーバレスは気になるけれど、まだ開発システムには組み込めないな......という方も、まずは運用ツールとして導入するのはいかがでしょうか。

著者プロフィール
渡邉 洋平
渡邉 洋平
AWS基盤上での商用メール配信システムや画像解析処理システム構築経験を持つ。最近ではAWS関連の支援業務も兼務。 部署名にクラウドが付いてなくても頑張ります。 自家製チャーシューやほうれん草のおひたし、レトルトを用いない麻婆豆腐など自炊も随時勉強中。