この記事は、ギークフィードアドベントカレンダー 2024の25日目の記事となります。
こんにちは、櫻井です。
さっそくですが、NAT Gatewayを1ヶ月間利用した際の大体の価格を存知でしょうか。
NAT Gatawayをプロビジョニングしただけでおよそ *a 6700円程度の支払いが必要になります。
また、処理データ1GBあたりにも$0.062加算されるので、仮に100GBの処理を行った場合
追加で *b 930円の支払いが必要になります。
合計すると、7630円もかかります。
本番環境で利用するならいざしらず、開発環境でNAT Gatewayを当たり前のようにプロビジョニングしていたら馬鹿にならない価格になってしまいますね。
もし8000円弱かかっていたコストを400円程度に抑えることができれば、だいぶお財布に優しくなると思います。
ということで今回は、開発環境用で利用するNATインスタンスを構築して、最大20分の1程度のコストカット出来る方法を紹介します。
※a 10.062(NatGatawayの1時間あたりの料金/$) * 24 (時間)* 30(日) * 150(為替相場)で計算
※b 0.062(NatGatawayのデータ処理1GBあたりの料金/$) * 100(GB) * 150(為替相場)で計算
目次
NATインスタンスの料金体系
NATインスタンスのコストは
・EC2インスタンスの使用料
・EBSの使用料
・パブリックIPの使用料
の3つからなります。
EC2インスタンスの価格
EC2の使用料はインスタンスタイプとインスタンスサイズによって変わります。ここでは低価格で利用できるインスタンスをピックアップしています。
インスタンス名 | オンデマンドの時間単価 |
t4g.nano | USD 0.0042 |
t4g.micro | USD 0.0084 |
t4g.small | USD 0.0168 |
EC2の価格について詳しく知りたい方は公式ドキュメントを参照してください。
EBSの価格
EBSの使用料もEBSの種類によって変わります。
汎用 SSD (gp3) – ストレージの場合、1ヶ月あたりUSD 0.096/GBが課金されます。
EBSの価格について詳しく知りたい方は公式ドキュメントを参照してください。
パブリックIPアドレスの価格
パブリック IPv4 アドレスは 1 時間あたり0.005 USDが課金されます。
パブリックIPv4アドレスの価格について詳しく知りたい方は公式ドキュメントを参照してください。
一番安く運用した場合のコスト
・EC2: t4g.nano
・EBS: 汎用 SSD (gp3) 8GB
・パブリックIPv4アドレス
を利用した際の24時間起動し続けた場合の価格と、業務時間中のみ起動した場合の価格について見ていきます。
24時間起動した場合の月あたりのコスト
EC2(t4g.nano):0.0042 USD × 24時間 × 30日 = 3.024 USD
EBS(汎用 SSD gp3, 8GB):0.096 USD × 8GB = 0.768 USD
パブリックIPv4: 0.005 USD × 24時間 × 30日 = 3.6 USD
日本円に換算すると(為替相場150円で計算)
(3.024 + 0.768 + 3.6)* 150 = 1108円 かかることがわかりました。
業務時間中のみ起動した場合の月あたりのコスト
EC2は平日の9:00 – 19:00まで起動しているとすると
EC2(t4g.nano):0.0042 USD × 10時間 × 21日 = 0.882 USD
EBS(汎用 SSD gp3, 8GB):0.096 USD × 8GB = 0.768 USD
パブリックIPv4: 0.005 USD × 10時間 × 21日 = 1.05 USD
日本円に換算すると(為替相場150円で計算)
(0.882 + 0.768 + 1.05)* 150 = 405円 かかることがわかりました。
NAT Gatawayを1ヶ月利用すると7630円かかり
NATインスタンスを営業時間中のみ1ヶ月間利用した場合は405円 なので、
最大 7630 – 405 = 7225円のコストカットが出来ることがわかります。
NAT GatewayとNAT インスタンスの違い
では、NAT Gateway とNATインスタンスではどのような違いがあるかを見比べていきます。
結論からいうと、今から比較を行った際に挙がるNATインスタンスのデメリットにより、
本番環境にNATインスタンスを利用することはあまりおすすめしません。
ただし、検証環境で利用する分には十分だと思います。
可用性・信頼性
NAT Gateway
・自動的にフェイルオーバーを行う
・複数AZで冗長化が行われている
・AWSによって管理されており、ユーザー側でメンテナンスが不要
NATインスタンス
・単一のEC2で動作する場合、単一障害点になる
・高可用性を実現したい場合は、複数のインスタンスの監視とフェイルオーバーの仕組みを構築する必要がある
パフォーマンス
NAT Gateway
・最大100 Gbps まで拡張できる
・トラフィックに応じて自動的に拡張する
NATインスタンス
・インスタンスタイプに依存する
・スケールアップを行いたい場合は手動でインスタンスタイプを変更する必要がある
コスト
NAT Gateway
・NAT Gatewayの稼働時間と、処理データ量に基づいて課金
・高価
NATインスタンス
・EC2インスタンスとEBSとパブリックIPの利用に基づいて課金
・小さいサイズのインスタンスを利用することで安価になる
管理の手間・セキュリティー
NAT Gateway
・AWSによって管理される
・パッチ適用やメンテナンスが不要
・セットアップが簡単
NATインスタンス
・OSのアップデートやセキュリティーパッチの適用が必要
・設定やトラブルシュートの知識が必要
・セキュリティーグループの管理が必要
以上のことからNATインスタンスを利用した場合、価格を抑えることが出来る反面、本番環境での運用に耐えうる構成を作ろうとすると考えなくてはいけない項目が多くなってしまいます。
よって、本番環境では利用せず、開発環境のみで利用することを推奨します。
NATインスタンスを構築するためのテンプレートを作成する
ここからはNATインスタンスを構築していきます。
今後AWS Service Catalogを利用して複数アカウントに展開できるようにCloud Formation(以下Cfn) テンプレートを作成しました。
以下が全体像です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
AWSTemplateFormatVersion: "2010-09-09" Description: "NAT Instance Template for AWS Service Catalog" Parameters: VpcId: Description: VPC ID where NAT Instance will be deployed Type: AWS::EC2::VPC::Id PublicSubnetId: Description: Public Subnet ID where NAT Instance will be deployed Type: AWS::EC2::Subnet::Id PrivateRouteTableId: Description: Route Table ID for private subnet Type: String KeyPairName: Description: EC2 Key Pair name Type: AWS::EC2::KeyPair::KeyName InstanceType: Description: NAT Instance Type Type: String Default: t4g.nano AllowedValues: - t4g.nano - t4g.micro - t4g.small Resources: NatInstanceSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Security Group for NAT Instance VpcId: !Ref VpcId SecurityGroupIngress: - IpProtocol: -1 FromPort: -1 ToPort: -1 CidrIp: 0.0.0.0/0 SecurityGroupEgress: - IpProtocol: -1 FromPort: -1 ToPort: -1 CidrIp: 0.0.0.0/0 Tags: - Key: Name Value: nat-instance-sg NatInstanceRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: ec2.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore Tags: - Key: Name Value: nat-instance-role NatInstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Roles: - !Ref NatInstanceRole NATInstance: Type: AWS::EC2::Instance Properties: KeyName: !Ref KeyPairName ImageId: ami-018a608de9486664d InstanceType: !Ref InstanceType IamInstanceProfile: !Ref NatInstanceProfile NetworkInterfaces: - AssociatePublicIpAddress: true DeviceIndex: "0" SubnetId: !Ref PublicSubnetId GroupSet: - !Ref NatInstanceSecurityGroup SourceDestCheck: false BlockDeviceMappings: - DeviceName: /dev/xvda Ebs: VolumeType: gp3 VolumeSize: 8 DeleteOnTermination: true Tags: - Key: Name Value: "NatInstance" UserData: Fn::Base64: | #!/bin/bash # スクリプトの実行ログを記録 exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1 # ネットワークインターフェースが完全に初期化されるまで待機 sleep 10 # IP forwardingの有効化 sudo sysctl -w net.ipv4.ip_forward=1 echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf # システムアップデートとnftablesのインストール sudo yum -y upgrade sudo yum install -y nftables # nftablesの設定 sudo nft flush ruleset sudo nft add table nat sudo nft add chain nat prerouting { type nat hook prerouting priority -100 \; } sudo nft add chain nat postrouting { type nat hook postrouting priority 100 \; } # インターフェース名を取得(代替方法) IFACE=$(ip route get 8.8.8.8 | grep -oP 'dev \K\S+') # masqueradeルールの設定 sudo nft add rule nat postrouting oifname "$IFACE" masquerade # 設定の永続化 sudo mkdir -p /etc/nftables sudo nft list ruleset > /etc/nftables/al2023-nat.nft echo 'include "/etc/nftables/al2023-nat.nft"' | sudo tee /etc/sysconfig/nftables.conf # nftablesサービスの有効化と起動 sudo systemctl enable nftables sudo systemctl restart nftables # 設定の確認 echo "Current nftables rules:" sudo nft list ruleset PrivateSubnetRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTableId DestinationCidrBlock: 0.0.0.0/0 InstanceId: !Ref NATInstance Outputs: NatInstanceId: Description: NAT Instance ID Value: !Ref NATInstance NatInstanceSecurityGroupId: Description: Security Group ID for NAT Instance Value: !Ref NatInstanceSecurityGroup |
では、各セクションについて解説していきます。
パラメータセクション
こちらはCfnテンプレートからリソースを作成するタイミングで値を設定したい項目です。
作成する毎に異なる値を利用したい内容は、パラメータとして設定することで変数化することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Parameters: VpcId: Description: VPC ID where NAT Instance will be deployed Type: AWS::EC2::VPC::Id PublicSubnetId: Description: Public Subnet ID where NAT Instance will be deployed Type: AWS::EC2::Subnet::Id PrivateRouteTableId: Description: Route Table ID for private subnet Type: String KeyPairName: Description: EC2 Key Pair name Type: AWS::EC2::KeyPair::KeyName InstanceType: Description: NAT Instance Type Type: String Default: t4g.nano AllowedValues: - t4g.nano - t4g.micro - t4g.small |
VpcId:NATインスタンスを配置するVPCを選択できるようにします。
PubicSubnetId:NATインスタンスを配置するサブネットを選択できるようにします。
PrivateRouteTableId:NAT経由でインターネットアクセスするサブネットのルートテーブルを入力できるようにします。
KeyPairName:SSH接続用のキーペアを選択できるようにします。
InstanceType:インスタンスタイプを選択できるようにします。
リソースセクション
ここでは、Cfnテンプレートから作成するリソースを定義します。
セキュリティーグループ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
NatInstanceSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Security Group for NAT Instance VpcId: !Ref VpcId SecurityGroupIngress: - IpProtocol: -1 FromPort: -1 ToPort: -1 CidrIp: 0.0.0.0/0 SecurityGroupEgress: - IpProtocol: -1 FromPort: -1 ToPort: -1 CidrIp: 0.0.0.0/0 Tags: - Key: Name Value: nat-instance-sg |
- NATインスタンス用のセキュリティグループを作成
- すべてのインバウンド/アウトバウンドトラフィックを許可
をおこなっています。
IAMロールとインスタンスプロファイル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
NatInstanceRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: ec2.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore Tags: - Key: Name Value: nat-instance-role |
- EC2インスタンス用のIAMロールの作成
- IAMロールに対して Systems Manager接続用のポリシーを付与(セッションマネージャー越しにEC2に接続する際に利用します)
- IAMロールをEC2のインスタンスプロファイルとして設定
をおこなっています。
NATインスタンス
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
NATInstance: Type: AWS::EC2::Instance Properties: KeyName: !Ref KeyPairName ImageId: ami-018a608de9486664d InstanceType: !Ref InstanceType IamInstanceProfile: !Ref NatInstanceProfile NetworkInterfaces: - AssociatePublicIpAddress: true DeviceIndex: "0" SubnetId: !Ref PublicSubnetId GroupSet: - !Ref NatInstanceSecurityGroup SourceDestCheck: false BlockDeviceMappings: - DeviceName: /dev/xvda Ebs: VolumeType: gp3 VolumeSize: 8 DeleteOnTermination: true Tags: - Key: Name Value: "NatInstance" UserData: Fn::Base64: | #!/bin/bash # スクリプトの実行ログを記録 exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1 # ネットワークインターフェースが完全に初期化されるまで待機 sleep 10 # IP forwardingの有効化 sudo sysctl -w net.ipv4.ip_forward=1 echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf # システムアップデートとnftablesのインストール sudo yum -y upgrade sudo yum install -y nftables # nftablesの設定 sudo nft flush ruleset sudo nft add table nat sudo nft add chain nat prerouting { type nat hook prerouting priority -100 \; } sudo nft add chain nat postrouting { type nat hook postrouting priority 100 \; } # インターフェース名を取得(代替方法) IFACE=$(ip route get 8.8.8.8 | grep -oP 'dev \K\S+') # masqueradeルールの設定 sudo nft add rule nat postrouting oifname "$IFACE" masquerade # 設定の永続化 sudo mkdir -p /etc/nftables sudo nft list ruleset > /etc/nftables/al2023-nat.nft echo 'include "/etc/nftables/al2023-nat.nft"' | sudo tee /etc/sysconfig/nftables.conf # nftablesサービスの有効化と起動 sudo systemctl enable nftables sudo systemctl restart nftables # 設定の確認 echo "Current nftables rules:" sudo nft list ruleset |
- パブリックIPの自動割り当て
- Source/Destination Checkの無効化(NAT機能に必要)
- gp3タイプのEBSボリューム設定
- UserData
- インスタンス起動時に実行されるスクリプトで、NAT機能の設定を自動化
ルート設定
1 2 3 4 5 6 |
PrivateSubnetRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTableId DestinationCidrBlock: 0.0.0.0/0 InstanceId: !Ref NATInstance |
- プライベートサブネットからのインターネット向けトラフィックをNATインスタンスにルーティング
次は作成したCfnテンプレートを使用して、実際にリソースを起動していきます。
Cfnテンプレートを利用してリソースを起動する
AWSコンソールにログインを行いCloudFormationのページに移動して、”スタックの作成” → “新しいリソースを使用(標準)”をクリックします。
テンプレートの指定で”テンプレートファイルのアップロード”を選択して、先ほど作成したCfnテンプレートをアップロードします。
スタック名:任意の名前
InstanceType:起動するEC2インスタンスのタイプを選択します
KeyPairName:EC2に設定するキーペアを選択します
PrivateRouteTableId:NAT経由でインターネットアクセスするサブネットのルートテーブルを入力します
PublicSubnetId:NATインスタンスを配置するサブネットを選択します
VpcId:NATインスタンスを配置するサブネットがあるVPCを選択します
上記の項目を入力したら”次へ”をクリックします。
“AWS CloudFormation によって IAM リソースが作成される場合があることを承認します。”のチェックボックスにチェックを入れて “次へ”をクリックします。
入力した項目に間違いがないことを確認したら”送信”をクリックします。
NATインスタンスを利用してインターネットにアクセスする
では最後に起動したNATインスタンスを利用してインターネットにアクセスできるかを検証していきます。
先ほどPrivateRouteTableIdで指定したRouteTableに紐づいているプライベートサブネットにEC2インスタンスを起動します。
※EC2インスタンスの起動方法については省略します。
起動が完了したらEC2にログインを行い、疎通確認を行います。
1 2 3 4 5 6 7 8 9 10 |
sh-5.2$ ping 8.8.8.8 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=116 time=2.67 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=116 time=2.45 ms 64 bytes from 8.8.8.8: icmp_seq=3 ttl=116 time=2.37 ms 64 bytes from 8.8.8.8: icmp_seq=4 ttl=116 time=2.48 ms ^C --- 8.8.8.8 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3006ms rtt min/avg/max/mdev = 2.365/2.492/2.672/0.112 ms |
疎通が確認できました。
まとめ
弊社では、各社員に対してSandbox環境のAWSアカウントを1つずつ配布しているので、Sandbox環境だけでも30個近くのアカウントを保有しています。
もし仮に各SandboxアカウントがすべてNAT Gatewayを使った場合、1ヶ月あたり
30アカウント * 7630円 = 228900円も課金されてしまいます。
こちらをすべてNATインスタンスに置き換えた場合、
228900 – (30 * 400) = 216900円もの節約ができることがわかります。おおきいですね。
ということでありがとうございました!
- NAT GatawayからNAT インスタンスに乗り換えて約95%のコスト削減をしてみた - 2024-12-25
- Amazon Connectで同じ電話番号から何回かかってきたかをカウントしてみた - 2024-12-25
- 特定の時間あたりのlambda実行数をSlackに通知する - 2023-12-23
- 公衆電話からでも使える電話帳サービスをLEX + AmazonConnectで作ってみた - 2023-12-19
- SQSを使ってlambdaを10秒ごとに定期実行する - 2023-12-14