開発環境のNAT Gatewayをfck-natに変えたら月額$45が$4になった話

開発環境のNAT Gatewayをfck-natに変えたら月額$45が$4になった話

2026.04.29

こんにちは。サービス開発室の武田です。

開発環境のAWSコストを見直していたところ、NAT Gatewayが月額約$45も占めていることに気付きました。本番環境ならまだしも、ほとんど使っていない開発環境で毎月$45は結構大きいですね。

そこで、NAT Gatewayの代替として fck-nat をAWS CDKで導入してみました。結果として開発環境のNATコストを月額$4まで削減できました。今回はその実装方法をまとめます。

NAT Gatewayは存在するだけでお金がかかる

東京リージョン(ap-northeast-1)でのNAT Gatewayの料金は次のようになっています。

項目 料金
時間課金 $0.062/時間(約$45/月)
データ処理 $0.062/GB

時間課金がそのまま固定費となります。開発環境で1つ、本番環境で2つ(冗長構成)配置していると、それだけで月額$135です。

環境 NAT Gateway数 月額(固定費のみ)
開発 1 ~$45
本番 2 ~$90
合計 3 ~$135

開発環境は通信量がほとんどないにもかかわらず、本番と同じ固定費がかかります。これだとちょっともったいないですね。

そもそもなぜNAT Gatewayが必要かというと、プライベートサブネット上のリソース(ECSタスク、Lambda関数など)から外向きの通信をするためです。具体的にはECRからのイメージ取得、外部APIの呼び出し、CloudWatch Logsへのログ送信などですね。

fck-natとは

fck-natは、NAT Gatewayの代替としてEC2インスタンスで動作するNATソリューションです。Gravitonインスタンス(t4g系)に対応していて、最小構成のt4g.nanoを使うとかなり安く運用できます。

公式の説明によると、t4g.nanoでも最大5Gbpsのバーストトラフィックに対応するとのこと。開発環境の通信量であれば十分でしょう。

コストを比較するとこうなります。

方式 インスタンス 月額
マネージドNAT Gateway - ~$45
fck-nat t4g.nano ~$4
fck-nat t4g.micro ~$6

10倍以上の差ですね。しかもcdk-fck-natというCDK向けのパッケージが用意されているので、導入もそんなに難しくありません。Auto Scaling Groupでインスタンスを管理してくれるため、障害時にも自動的に再作成されます。

CDKでの実装

パッケージのインストール

npm install cdk-fck-nat

環境別にNAT方式を切り替える

開発環境ではfck-nat、本番環境ではマネージドNAT Gatewayを使い分けるのがよさそうです。実際に書いてみたコードがこちらです。

import * as cdk from 'aws-cdk-lib'
import * as ec2 from 'aws-cdk-lib/aws-ec2'
import { FckNatInstanceProvider } from 'cdk-fck-nat'
import type { Construct } from 'constructs'

export interface NetworkStackProps extends cdk.StackProps {
  environment: string
}

export class NetworkStack extends cdk.Stack {
  public readonly vpc: ec2.Vpc

  constructor(scope: Construct, id: string, props: NetworkStackProps) {
    super(scope, id, props)

    // dev環境: fck-nat(t4g.nano)でコスト削減($45→$4/月)
    // prod環境: マネージドNAT Gateway(高可用性)
    const natGatewayProvider =
      props.environment === 'dev'
        ? new FckNatInstanceProvider({
            instanceType: ec2.InstanceType.of(
              ec2.InstanceClass.T4G,
              ec2.InstanceSize.NANO
            ),
          })
        : undefined

    this.vpc = new ec2.Vpc(this, 'Vpc', {
      maxAzs: 2,
      natGateways: props.environment === 'prod' ? 2 : 1,
      // dev環境のみfck-natを使用
      ...(natGatewayProvider && { natGatewayProvider }),
      subnetConfiguration: [
        {
          cidrMask: 24,
          name: 'Public',
          subnetType: ec2.SubnetType.PUBLIC,
        },
        {
          cidrMask: 24,
          name: 'Private',
          subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
        },
      ],
    })

    // fck-natのセキュリティグループ設定
    // VPC内からの全トラフィックを許可(NATとして動作するために必要)
    if (natGatewayProvider instanceof FckNatInstanceProvider) {
      natGatewayProvider.securityGroup.addIngressRule(
        ec2.Peer.ipv4(this.vpc.vpcCidrBlock),
        ec2.Port.allTraffic()
      )
    }
  }
}

FckNatInstanceProviderはCDKのNatProviderインタフェースを実装しているので、VPCのnatGatewayProviderにそのまま渡せます。natGatewayProviderを指定しなければ通常のマネージドNAT Gatewayが使われます。そこで条件付きスプレッド(...(natGatewayProvider && { natGatewayProvider }))を使い、環境ごとに切り替えています。

ハマりやすいポイントは最後のセキュリティグループ設定です。fck-natはEC2インスタンスで動作するため、VPC内からのトラフィックを受け付けるルールを明示的に追加する必要があります。マネージドNAT Gatewayではここの設定は不要(AWSが裏でやってくれる)ですが、fck-natでは自前で設定しないとパケットがとおりません。

なお、instanceofでチェックすることで、本番環境(fck-natを使わない環境)ではこの処理がスキップされるようになっています。

デプロイ

コンテキスト値で環境を切り替えてデプロイします。

# 開発環境(fck-natが使われる)
npx cdk deploy --context environment=dev

# 本番環境(マネージドNAT Gatewayが使われる)
npx cdk deploy --context environment=prod

導入後のコスト

実際に置き換えてみた結果がこちらです。

環境 変更前 変更後 削減額
開発 NAT Gateway $45/月 fck-nat(t4g.nano) $4/月 $41/月
本番 NAT Gateway x2 $90/月 変更なし $90/月 $0

年間で約$492の削減です。複数の開発環境(feature環境やステージング)があればさらに大きなインパクトが出ます。

どんな環境に向いているか

fck-natは何でもかんでも置き換えればよいというものではありません。今回の検証を踏まえて、向き不向きを整理してみます。

向いているのは、開発・ステージング環境のようにコスト最適化が重要で、多少のダウンタイムが許容できるケースです。t4g.nanoのバースト帯域(最大5Gbps)で十分な通信量であり、単一AZ構成で問題ない開発環境ならばっちりはまります。

逆に本番環境では向いていないと言えます。インスタンス障害時にAuto Scaling Groupによる復旧で数分のダウンタイムが発生します。NAT Gatewayは最大100Gbpsのスループットに対応しているため、高スループットが必要な場面でもマネージド版が無難です。コンプライアンス要件でマネージドサービスの使用が必須の場合も同様ですね。

そもそもNATがいらないケースもある

ちなみに、アーキテクチャによってはNAT自体を廃止できる場合もあります。たとえば次のようなケースです。

  • ECSタスクをパブリックサブネットに配置している
  • 外部通信がVPC Endpointで代替できる(S3、ECR、STS、CloudWatch Logsなど)
  • Lambda関数をVPC外で動作させている

VPC Endpointの追加コストとNATのコストを比較し、最適な構成を選ぶとよいでしょう。

まとめ

cdk-fck-natを使えば、CDKコードのちょっとした変更だけで開発環境のNATコストを削減できました。コンテキスト値で環境を切り替える形にしておくと、開発と本番で構成の差分を一元管理できて運用も楽です。

開発環境のAWSコストに悩んでいる方は、まずNAT Gatewayの置き換えから試してみてはいかがでしょうか。

この記事をシェアする

関連記事