AWS VPC設計入門|サブネット・セキュリティグループ・NATの基礎ハンズオン

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > AWS(Amazon Linux) > AWS VPC設計入門|サブネット・セキュリティグループ・NATの基礎ハンズオン
「AWS VPCって設計が複雑そうで、どこから手をつければいいか分からない」
そう感じているエンジニアは多いはずです。VPC(Virtual Private Cloud)はAWSの基盤となるネットワーク機能ですが、
CIDRブロック・サブネット・セキュリティグループ・NATゲートウェイと用語が多く、最初は混乱しがちです。

この記事では、aws vpc 設計の基礎からマルチAZ構成まで、実際の設計パターンをハンズオン形式で解説します。
Webサービスの本番環境で主流になっている「3層アーキテクチャ(ALB・EC2・RDS)」での実装パターンを中心に、VPCフローログを使った通信の可視化とセキュリティ監査の方法、VPCエンドポイントによるNATコスト削減、Transit Gateway接続時のCIDR重複回避まで含めて、「まず動くVPCを作りたい」「セキュリティ設定が正しいか確認したい」「NATコストを抑えたい」という初級~中級者に向けて体系的にカバーします。
設計の詳細な冗長化・マルチAZ応用については、AWS冗長設計入門もあわせて参照してください。

この記事のポイント

・VPCのCIDRは作成後に変更できない——最初に余裕を持った/16で設計することが鉄則
・サブネットはパブリック(ALB)・アプリプライベート(EC2)・DBプライベート(RDS)の3層に分ける
・セキュリティグループはALB-SG→EC2-SG→RDS-SGの順にSG参照で連携させる
・S3・DynamoDB向けGateway型VPCエンドポイント(無料)でNATゲートウェイのコストを削減できる
・VPCフローログでACCEPT/REJECTを記録し、SG/NACLの設定検証と通信監査に活用する


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

AWS VPCとは何か(基本概念)

AWS VPC(Virtual Private Cloud)は、AWSクラウド上に作成する論理的な仮想ネットワーク空間です。
物理的なデータセンターでいう「社内LAN」を、クラウド上に丸ごと再現するイメージを持つと分かりやすいです。

VPCを使うと、以下のことが実現できます。
・IPアドレスの範囲を自分で決められる(CIDRブロック)
・インターネットに公開するゾーンと非公開ゾーンを分けられる(パブリック・プライベートサブネット)
・どのIPからどのポートへのアクセスを許可するか細かく制御できる(セキュリティグループ・ネットワークACL)
・複数のアベイラビリティゾーン(AZ)にまたがる冗長構成を組める(マルチAZ)
・VPCフローログでネットワーク通信のACCEPT/REJECTを記録して可視化できる
・プライベートサブネット内のリソースをNATゲートウェイ経由で安全にインターネットへ接続できる

AWSの多くのサービス(EC2・RDS・ELB・Lambda等)はVPC内に配置するため、
aws vpc 設計の基礎を押さえることが、AWSの実践スキル全体に直結します。

VPCの主な構成要素

VPCを構成する要素を整理しておきましょう。

要素 役割
VPC 仮想ネットワーク空間全体。リージョン単位で作成する
サブネット VPC内を細かく区切ったIPアドレス範囲。AZ単位で作成する
インターネットゲートウェイ(IGW) VPCとインターネットを接続する出入り口
ルートテーブル サブネットごとの通信経路を定義する
セキュリティグループ インスタンス単位のファイアウォール(ステートフル)
ネットワークACL(NACL) サブネット単位のファイアウォール(ステートレス)
NATゲートウェイ プライベートサブネットからのアウトバウンド通信を中継する
VPCエンドポイント S3・DynamoDB等のAWSサービスへNATを経由せずVPC内から直接アクセスする
VPCフローログ ENIを通過するIPトラフィックのACCEPT/REJECTを記録する
VPC DNSホスト名 EC2インスタンスにDNSホスト名を付与する(RDS接続に必須)
AWSをゼロから学びたい方は、Amazon Linux入門講座もあわせてご覧ください。

VPC設計の基本:CIDRブロックの考え方

VPCを作成する際に最初に決めるのが「CIDRブロック」です。
CIDR(Classless Inter-Domain Routing)は、IPアドレスの範囲を「アドレス/プレフィックス長」で表す記法です。

VPCのCIDRブロックは、作成後に変更できません。設計ミスに気づいたときにはすでに遅く、VPC再構築・リソース移行という大掛かりな作業が待ち受けています。
後からCIDRを追加する「セカンダリCIDRブロック」の仕組みはありますが、既存のCIDRは変更・削除できず、ルーティング設計が複雑になります。
最初に余裕を持って設計することが、aws vpc 設計の鉄則です。

1. CIDRブロックの設計指針

実務でよく使われるVPC CIDRの目安を示します。

CIDRブロック 使用可能IPアドレス数 適したケース
10.0.0.0/16 65,536個 本番環境・大規模構成。サブネット分割の余裕が大きい(推奨)
10.0.0.0/24 256個 学習・検証環境。小規模で素早く試したい場合
172.16.0.0/16 65,536個 オンプレ環境とIPが重複しないよう別レンジを使いたい場合

本番環境では 10.0.0.0/16 を基本とし、サブネットに /24(256アドレス)を割り当てる設計がよく使われます。
ALBやRDSはENI(Elastic Network Interface)を複数消費するため、/28のような小さいサブネットは避けてください。

2. プライベートIPアドレス範囲(RFC 1918)を使う理由

VPC内では必ずプライベートIPアドレス範囲を使います。
インターネットには直接ルーティングされない専用の範囲であり、安全にVPC内部で自由にIPを割り振れます。

プライベートIPレンジ アドレス範囲 注意点
10.0.0.0/8 10.0.0.0 ~ 10.255.255.255 最も広く、マルチVPC・マルチ拠点構成に最適
172.16.0.0/12 172.16.0.0 ~ 172.31.255.255 中規模構成向け
192.168.0.0/16 192.168.0.0 ~ 192.168.255.255 家庭用ルーターでも使われるため、オンプレ接続時は重複に注意

複数のVPCやオンプレミス拠点とDirect ConnectやSite-to-Site VPNで接続する場合は、すべての拠点のCIDRが重複しないよう計画することが必須です。
実務では「10.0.0.0/8を会社全体で分割して各環境・拠点に払い出す」方式が一般的です(後述のTransit Gateway接続設計も参照)。

3. AWSが各サブネットで予約する5つのIPアドレス

各サブネットで、AWSが最初から5つのIPアドレスを予約しています。
たとえば 10.0.1.0/24(256アドレス)のサブネットの場合、実際に使えるIPは251個になります。

# 10.0.1.0/24 サブネットで予約されるIPアドレス 10.0.1.0 ネットワークアドレス 10.0.1.1 VPCルーター(デフォルトゲートウェイ) 10.0.1.2 Amazon DNSサーバー 10.0.1.3 AWSが将来の利用のために予約 10.0.1.255 ブロードキャストアドレス(AWSでは使用不可) # → 実際に使えるIPは 10.0.1.4 ~ 10.0.1.254 の 251個

この予約ルールは/28サブネットでとくに重要です。/28では16アドレスから5つを差し引いて11個しか使えません。
EKSクラスター(Amazon Elastic Kubernetes Service)では、PodにVPC CNIプラグインが個別IPを割り当てるため、
ノード10台・Pod各30個の構成なら300個以上のIPが必要です。EKSを使う計画があるなら、プライベートサブネットは最低でも/20(実質4,091アドレス)以上を確保してください。
Lambdaを大量に同時実行する場合も、ENI(Elastic Network Interface)を多数消費するため、同様にアドレス数に余裕のあるサブネット設計が必要です。

4. マルチAZ対応のサブネット分割計算例

VPC 10.0.0.0/16 を東京リージョンの2AZに展開する際のサブネット計算例を示します。
AZごとに大きなブロック(/18)を確保してから /24 に細分化する方式は、管理ツール上でのAZ単位の可視性が高く、将来サブネットを追加するときにアドレスの断片化を防げます。

# VPC全体:10.0.0.0/16(65,536アドレス) # AZ1(ap-northeast-1a)ブロック:10.0.0.0/18(16,384アドレス) 10.0.1.0/24 public-subnet-1a (ALB・NATゲートウェイ) 10.0.11.0/24 app-prv-1a (EC2アプリ層・Lambda) 10.0.21.0/24 db-prv-1a (RDS DB層) # AZ2(ap-northeast-1c)ブロック:10.0.64.0/18(16,384アドレス) 10.0.65.0/24 public-subnet-1c (ALB・NATゲートウェイ) 10.0.75.0/24 app-prv-1c (EC2アプリ層・Lambda) 10.0.85.0/24 db-prv-1c (RDS DB層) # 予備:10.0.128.0/17(将来の追加サブネット・3AZ拡張用)

東京リージョン(ap-northeast-1)では3つのAZを使用できます。本番環境で3AZ構成(9サブネット)にする場合は、
第3オクテットでパブリック(0番台)・アプリプライベート(10番台)・DB(20番台)を視覚的に区別すると運用しやすくなります。

# 3AZ構成(推奨):3AZ × 3役割 = 9サブネット # VPC: 10.0.0.0/16 (prod-vpc) # パブリックサブネット(ALB・NATゲートウェイ配置) pub-1a: 10.0.0.0/24 ap-northeast-1a pub-1c: 10.0.1.0/24 ap-northeast-1c pub-1d: 10.0.2.0/24 ap-northeast-1d # プライベートサブネット(EC2・ECS・Lambda配置) priv-1a: 10.0.10.0/24 ap-northeast-1a priv-1c: 10.0.11.0/24 ap-northeast-1c priv-1d: 10.0.12.0/24 ap-northeast-1d # DBサブネット(RDS・ElastiCache配置) db-1a: 10.0.20.0/24 ap-northeast-1a db-1c: 10.0.21.0/24 ap-northeast-1c db-1d: 10.0.22.0/24 ap-northeast-1d # 将来の追加分(管理・検査用に予約) mgmt: 10.0.30.0/24 ~ 10.0.39.0/24

2AZで十分なケースも多いですが、可用性要件が厳しい本番サービスでは3AZ構成を最初から計画しておくと、
後から1AZを追加する際のCIDR設計変更が不要になります。

5. AWS CLIでVPCを作成する

AWSコンソールだけでなく、CLIからも作成できます。手順を覚えておくとインフラのコード化(IaC)に役立ちます。

# VPCを作成する(東京リージョン・ap-northeast-1を前提) $ aws ec2 create-vpc --cidr-block 10.0.0.0/16 --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=prod-ap-northeast-1-vpc}]' # 実行結果(抜粋) { "Vpc": { "VpcId": "vpc-0a1b2c3d4e5f60001", "CidrBlock": "10.0.0.0/16", "State": "available" } } # VPCのDNSホスト名を有効にする(RDSのエンドポイント名解決に必要) $ aws ec2 modify-vpc-attribute --vpc-id vpc-0a1b2c3d4e5f60001 --enable-dns-hostnames

6. よくある失敗パターン3選

実務でよく遭遇するCIDR設計のミスを3つ挙げます。設計前に確認しておくと、後の大規模な作り直しを防げます。

失敗1: 全VPCに 10.0.0.0/16 を設定する
最も多い失敗です。本番・ステージング・開発の3環境すべてに同じCIDRを設定すると、
VPCピアリングやTransit Gatewayで接続しようとした段階でエラーになります。
CIDRが重複するVPC間ではピアリングを設定できません。環境ごとに第2オクテットを変える(本番=10.0、ステージング=10.1、開発=10.2)のが鉄則です。

失敗2: 192.168.0.0/16 を選ぶ
自宅や中小企業のルーターが192.168.0.0/24や192.168.1.0/24をデフォルトで使うケースが多く、
Site-to-Site VPNやClient VPNで接続する際にアドレスが衝突するリスクがあります。
テレワーク環境でClient VPNを使う本番システムでは特に要注意です。AWSのVPCには 10.0.0.0/8内のアドレスを使うのが最も安全です。

失敗3: VPC自体を/24などの小さいCIDRで作成する
「最初は小さく始めよう」という考えでVPC自体を/24にすると、サブネットを3役割×2AZ=6本に分割した時点でほぼ使い切ってしまいます。
VPCのCIDR = /16、サブネットのCIDR = /24 という組み合わせが基本です。
ALBやEKSのように多くのENIを消費するサービスを使う場合、/24より小さいサブネットではIP不足に陥ります。

パブリックサブネットとプライベートサブネットの設計

VPCの設計で最も重要な概念が「パブリックサブネット」と「プライベートサブネット」の使い分けです。
この2種類を適切に分けることで、インターネットに公開すべきリソースと非公開にすべきリソースを安全に管理できます。

1. パブリックサブネットの役割

パブリックサブネットは、インターネットゲートウェイ(IGW)へのルートを持ち、
インターネットと直接通信できるサブネットです。

典型的な用途は以下の通りです。
・Webサーバー(EC2インスタンス)
・ロードバランサー(ALB/NLB)
・踏み台サーバー(Bastion Host)
・NATゲートウェイ本体(後述)

# ルートテーブルに以下のルートを追加する # 送信先: 0.0.0.0/0 → ターゲット: インターネットゲートウェイ(igw-xxxxxxxxx) # これによりパブリックサブネット内のインスタンスはインターネットと通信可能になる # また、EC2インスタンスには「パブリックIPの自動割り当て」を有効にする # または Elastic IP(固定パブリックIP)を割り当てる

2. プライベートサブネットの役割

プライベートサブネットは、IGWへの直接ルートを持たず、インターネットから直接アクセスできないサブネットです。

典型的な用途は以下の通りです。
・データベースサーバー(RDS・ElastiCache)
・アプリケーションサーバー(APIサーバーなど)
・バッチ処理サーバー
・Lambda関数(RDS・ElastiCacheなどVPC内リソースへの接続が必要な場合)
・機密データを扱うサービス

プライベートサブネットに置いたリソースは直接インターネットからアクセスできないため、セキュリティが大幅に向上します。
ただしソフトウェアのアップデートなどでインターネットへのアウトバウンド通信が必要な場合は、NATゲートウェイを使います(後述)。

3. CIDRブロックの分割例

VPCを 10.0.0.0/16 で作った場合のサブネット割り当て例です。

サブネット名 CIDRブロック AZ 種別
public-subnet-1a 10.0.1.0/24 ap-northeast-1a パブリック
public-subnet-1c 10.0.2.0/24 ap-northeast-1c パブリック
private-subnet-1a 10.0.11.0/24 ap-northeast-1a プライベート(アプリ・Lambda)
private-subnet-1c 10.0.12.0/24 ap-northeast-1c プライベート(アプリ・Lambda)
db-subnet-1a 10.0.21.0/24 ap-northeast-1a プライベート(DB)
db-subnet-1c 10.0.22.0/24 ap-northeast-1c プライベート(DB)

パブリックは 10.0.1.x ~ 10.0.9.x、アプリは 10.0.10.x 台、DBは 10.0.21.x 以降のような「番号で種別を見分けやすい」設計にしておくと、
後から見返したときに混乱しにくくなります。

4. 3層アーキテクチャでのサブネット分割(Web・AP・DB層)

本番品質のWebシステムでは、プライベートサブネットをさらに「アプリ層(EC2)」と「DB層(RDS)」に分割するのがベストプラクティスです。
アプリ層とDB層を同じサブネットに混在させると、セキュリティグループの制御が複雑になり、
EC2が侵害された場合にRDSへも直接アクセスされるリスクが生じます。

層 役割 AWSサービス 配置サブネット例
Web層 HTTPS受付・SSL終端・負荷分散 ALB(Application Load Balancer) パブリック(10.0.1.0/24, 10.0.2.0/24)
アプリ層 ビジネスロジック実行・DBアクセス EC2(Auto Scalingグループ)・Lambda アプリプライベート(10.0.11.0/24, 10.0.12.0/24)
DB層 データ永続化・トランザクション RDS(マルチAZ有効)・ElastiCache DBプライベート(10.0.21.0/24, 10.0.22.0/24)

AWS CLIでアプリ層とDB層のプライベートサブネットを作成する例です。

# アプリ層用プライベートサブネット(ap-northeast-1a) $ aws ec2 create-subnet --vpc-id vpc-0a1b2c3d4e5f60001 --cidr-block 10.0.11.0/24 --availability-zone ap-northeast-1a --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=app-prv-1a}]' # アプリ層用プライベートサブネット(ap-northeast-1c) $ aws ec2 create-subnet --vpc-id vpc-0a1b2c3d4e5f60001 --cidr-block 10.0.12.0/24 --availability-zone ap-northeast-1c --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=app-prv-1c}]' # DB層用プライベートサブネット(ap-northeast-1a) $ aws ec2 create-subnet --vpc-id vpc-0a1b2c3d4e5f60001 --cidr-block 10.0.21.0/24 --availability-zone ap-northeast-1a --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=db-prv-1a}]' # DB層用プライベートサブネット(ap-northeast-1c) $ aws ec2 create-subnet --vpc-id vpc-0a1b2c3d4e5f60001 --cidr-block 10.0.22.0/24 --availability-zone ap-northeast-1c --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=db-prv-1c}]'

5. 環境ごとのVPC分離パターン

本番・ステージング・開発でVPCを別々に作る方式が、セキュリティ観点から推奨されます。
VPCを分けることで、セキュリティグループやIAMロールのミスが本番に影響するリスクを根本から排除できます。
第2オクテットを環境ごとに分けてCIDRを管理すると、管理台帳での視認性が高まります。

# 環境ごとにVPCを分けてCIDRを管理する例(第2オクテットで環境を区別) 本番VPC 10.0.0.0/16 (ap-northeast-1) ステージングVPC 10.1.0.0/16 (ap-northeast-1) 開発VPC 10.2.0.0/16 (ap-northeast-1) DR用VPC 10.3.0.0/16 (ap-northeast-3)

AWS Organizationsを使ってAWSアカウントごと分離する方式と組み合わせると、さらに安全です。
アカウント分離+VPC分離の2層設計が、AWS Well-Architected Frameworkでも推奨されています。

コストを最優先にしたスモールスタートでは、単一VPCの中でサブネットとセキュリティグループだけで環境を分離する方法も取られますが、
サービスが成長してVPC分離に移行する際に多大なコストがかかります。初期設計の段階でVPC分離を計画しておくことをすすめます。

6. サブネットの命名規則

Nameタグの命名規則を統一しておくと、複数人での運用時やAWSコンソール上での視認性が大幅に上がります。
「環境-層-AZ番号-subnet」の形式が管理しやすく、IaCと組み合わせたときも可読性が高いです。

・prod-public-az1-subnet(本番・パブリック・AZ1)
・prod-private-az1-subnet(本番・プライベート・AZ1)
・prod-db-az1-subnet(本番・DBサブネット・AZ1)

命名規則と合わせて、以下のタグを統一して付与すると運用コストが下がります。
・Env: prod / stg / dev
・Project: システム名
・ManagedBy: terraform / cloudformation / manual

タグを統一しておくと、Cost ExplorerでのVPCごとのコスト集計、AWS Configでのリソース変更監査が格段に楽になります。

セキュリティグループとネットワークACLの使い分け

VPCのセキュリティ制御は「セキュリティグループ」と「ネットワークACL(NACL)」の2層構造です。
この2つは似て非なるものであり、役割を理解して使い分けることが大切です。
なお、設定後はVPCフローログのactionフィールドで実際のACCEPT/REJECTを確認する習慣をつけると、意図通りに動作しているかすぐ検証できます(後述)。

1. セキュリティグループ(Security Group)

セキュリティグループは、EC2インスタンスなどのリソースに直接アタッチするファイアウォールです。

主な特徴は以下の通りです。
・ステートフル:インバウンドで許可した通信のレスポンスは自動的に許可される
・許可ルールのみ:「拒否」のルールは設定できない(ルールにないものは自動的に拒否)
・インスタンス単位:1つのインスタンスに複数のセキュリティグループを適用可能

# インバウンドルール(受信許可)設定例(Webサーバー用セキュリティグループ) # ルール1: HTTP (TCP 80) 送信元: 0.0.0.0/0 インターネットからのアクセスを許可 # ルール2: HTTPS (TCP 443) 送信元: 0.0.0.0/0 HTTPS接続を許可 # ルール3: SSH (TCP 22) 送信元: 203.0.113.50/32 自分のPCのIPアドレスのみ許可 # アウトバウンドルール(送信許可) # デフォルト: すべてのアウトバウンドを許可(0.0.0.0/0) # ステートフルのため、インバウンドで受けた通信のレスポンスは別途許可不要

2. ネットワークACL(NACL)

ネットワークACLはサブネット全体に適用するファイアウォールです。セキュリティグループとの違いをまとめます。

比較項目 セキュリティグループ ネットワークACL
適用対象 インスタンス単位 サブネット単位
ステート ステートフル ステートレス
拒否ルール 設定不可 設定可能
ルールの評価 全ルールをまとめて評価 番号順に評価(マッチしたら終了)
デフォルト動作 全拒否(許可ルールのみ追加) 全許可(デフォルトNACL)

実務上はセキュリティグループを主軸に設計し、NACLは追加の防御層として使うケースが多いです。
特定のIPアドレスを明示的にブロックしたい場合(DDoS対策など)は、NACLの「拒否ルール」が有効です。

NACLはステートレスのため、インバウンドを許可した通信のレスポンスについても
アウトバウンドのルールで明示的に許可する必要があります。
エフェメラルポート(一般的に1024~65535)を戻り通信用に開ける必要がある点に注意してください。

3. セキュリティグループの設計ベストプラクティス

セキュリティグループを設計する際の実践的なポイントをまとめます。
・最小権限の原則:必要なポートのみ、必要なソースIPのみを許可する
・SSH(22番ポート)は必ず特定のIPに制限:0.0.0.0/0(全世界)に開放しない
・セキュリティグループ間参照を使う:WebサーバーからDBサーバーへのアクセスは、IPではなくWebサーバー用SGを送信元に指定する
・Lambda・ECS等のサーバーレスリソースは専用SGを作る:インバウンドルール不要のリソースにはルールを追加しない(デフォルトの全拒否を維持)
・名前・説明文を丁寧に書く:後から見てどのリソース用か分かるように管理する

# DBサーバーのセキュリティグループのインバウンドルール # ポート: MySQL/Aurora (TCP 3306) # 送信元: sg-0123456789abcdef0 (Webサーバー用セキュリティグループのID) # →「WebサーバーのSGがアタッチされたインスタンスからのみ3306番を許可」という意味 # IPアドレスではなくSGを参照することで、インスタンスのIP変動に依存しない柔軟な設計になる # Lambda関数用SGの例(外部からの着信がないリソースはインバウンド不要) # sg-lambda: インバウンドルール=なし、アウトバウンドルール=すべて許可 # sg-rds: インバウンド TCP 3306 送信元: sg-lambda ← LambdaからDBへの接続を許可

4. 3層アーキテクチャでのセキュリティグループ連携設計

3層アーキテクチャ(ALB・EC2・RDS)のセキュリティグループ設計の核心は、送信元をIPアドレスではなくセキュリティグループIDで指定する点です。
これにより、EC2インスタンスのIPが動的に変わってもルールが自動で追従します。

# ステップ1: ALB-SG(インターネットからHTTPS/HTTPを受け付ける) $ aws ec2 create-security-group --group-name alb-sg --description "SG for ALB web layer" --vpc-id vpc-0a1b2c3d4e5f60001 # 実行結果: {"GroupId": "sg-0alb1234567890ef0"} # インターネットからHTTPS(443)とHTTP(80)を許可する $ aws ec2 authorize-security-group-ingress --group-id sg-0alb1234567890ef0 --protocol tcp --port 443 --cidr 0.0.0.0/0 $ aws ec2 authorize-security-group-ingress --group-id sg-0alb1234567890ef0 --protocol tcp --port 80 --cidr 0.0.0.0/0 # ステップ2: EC2-SG(ALB-SGからのみアプリポートを受け付ける) $ aws ec2 create-security-group --group-name ec2-app-sg --description "SG for EC2 app layer" --vpc-id vpc-0a1b2c3d4e5f60001 # 実行結果: {"GroupId": "sg-0ec21234567890fg0"} # --source-group でSGIDを指定(IPアドレスではなくSG参照) $ aws ec2 authorize-security-group-ingress --group-id sg-0ec21234567890fg0 --protocol tcp --port 8080 --source-group sg-0alb1234567890ef0 # → EC2へのアクセスはALBを経由したものだけに限定される # ステップ3: RDS-SG(EC2-SGからのみDBポートを受け付ける) $ aws ec2 create-security-group --group-name rds-db-sg --description "SG for RDS DB layer" --vpc-id vpc-0a1b2c3d4e5f60001 # 実行結果: {"GroupId": "sg-0rds1234567890gh0"} $ aws ec2 authorize-security-group-ingress --group-id sg-0rds1234567890gh0 --protocol tcp --port 3306 --source-group sg-0ec21234567890fg0 # ルール確認(IpRangesが空でUserIdGroupPairsのみが正しい状態) $ aws ec2 describe-security-groups --group-ids sg-0rds1234567890gh0 --query 'SecurityGroups[0].IpPermissions'

このSG連携設計(ALB-SG→EC2-SG→RDS-SGのチェーン)により、
・EC2へはALBを経由した通信だけが届く(直接攻撃をALB手前でブロック)
・RDSへはEC2からの通信だけが届く(EC2が侵害されてもRDSへは直接到達できない)
という2段階の防御が自動的に機能します。

NATゲートウェイの役割と設計パターン

プライベートサブネット内のEC2インスタンスは、直接インターネットと通信できません。
しかしソフトウェアの更新(yum/apt)や外部APIへのアクセスなど、インターネットへのアウトバウンド通信が必要な場面は多くあります。
このときに使うのが「NATゲートウェイ(NAT Gateway)」です。

1. NATゲートウェイの仕組み

NAT(Network Address Translation)ゲートウェイは、プライベートIPアドレスをパブリックIPアドレスに変換して
インターネットとの通信を中継するサービスです。

# 通信フロー(プライベートサブネットからインターネットへ) # プライベートサブネット内のEC2(10.0.11.10) # → NATゲートウェイ(パブリックサブネット・10.0.1.x) # → インターネットゲートウェイ(IGW) # → インターネット(yumリポジトリ等) # 設定のポイント: # 1. NATゲートウェイ自体はパブリックサブネットに置く(必須) # 2. NATゲートウェイにはElastic IP(固定パブリックIP)を割り当てる # 3. プライベートサブネットのルートテーブルに追加するルート: # 送信先: 0.0.0.0/0 → ターゲット: nat-xxxxxxxxxxxxxxxxx

2. NATゲートウェイの設定手順(概要)

AWSコンソールでの設定手順を示します。

# Step 1: Elastic IPを取得する # VPCコンソール → Elastic IP → 新しいElastic IPの割り当て # Step 2: NATゲートウェイを作成する # VPCコンソール → NATゲートウェイ → NATゲートウェイを作成 # - サブネット: パブリックサブネットを選択(プライベートサブネットではない) # - 接続タイプ: パブリック # - Elastic IP割り当てID: Step1で取得したEIPを選択 # Step 3: プライベートサブネットのルートテーブルを更新する # VPCコンソール → ルートテーブル → プライベートサブネット用ルートテーブルを選択 # → ルートを編集 → ルートの追加 # 送信先: 0.0.0.0/0 / ターゲット: NATゲートウェイ(nat-xxxxxxxxxxxxxxxxx)

3. NATゲートウェイのコスト注意点

NATゲートウェイは有料サービスであり、時間課金(約0.062 USD/時間)+データ転送量課金がかかります。
開発環境や検証環境では、コスト削減のためにNATゲートウェイの代わりに
「NATインスタンス(EC2インスタンスでNATを行う)」を使う選択肢もあります。
ただし可用性・運用負荷を考えると、本番環境ではNATゲートウェイを使うことを強くすすめます。

また、検証が終わったらNATゲートウェイを削除し、Elastic IPも解放しておくことも忘れずに。
削除し忘れると課金が続くため注意してください。

4. VPCエンドポイントでNATコストを削減する

VPC内のEC2・Lambda関数がS3やDynamoDBに頻繁にアクセスする場合、通信のたびにNATゲートウェイを経由すると
データ転送料金が積み上がります。VPCエンドポイントを設置することで、これらのAWSサービスへのトラフィックを
VPC内で完結させ、NATゲートウェイを経由しないルーティングに切り替えられます。

VPCエンドポイントには「Gateway型」と「Interface型」の2種類があります。

種別 対応サービス 料金 仕組み
Gateway型 S3・DynamoDB 無料 ルートテーブルにエンドポイントルートを自動追加
Interface型 SSM・Secrets Manager・ECR等 有料(0.014 USD/時間程度) ENI経由でVPC内プライベートIPに直接アクセス

まずはS3とDynamoDB向けのGateway型エンドポイント(無料)から導入するのが定石です。
ルートテーブルへのエンドポイントルート追加が自動的に行われ、EC2・Lambda側のコードは一切変更不要です。

# S3用Gatewayエンドポイントを作成(プライベートサブネットのルートテーブルに自動追加) $ aws ec2 create-vpc-endpoint --vpc-id vpc-0a1b2c3d4e5f60001 --service-name com.amazonaws.ap-northeast-1.s3 --route-table-ids rtb-xxxxAZa rtb-xxxxAZc # DynamoDB用Gatewayエンドポイントも同様に作成する $ aws ec2 create-vpc-endpoint --vpc-id vpc-0a1b2c3d4e5f60001 --service-name com.amazonaws.ap-northeast-1.dynamodb --route-table-ids rtb-xxxxAZa rtb-xxxxAZc # SSM Parameter Store用Interfaceエンドポイントを作成(Private DNS有効化) $ aws ec2 create-vpc-endpoint --vpc-id vpc-0a1b2c3d4e5f60001 --vpc-endpoint-type Interface --service-name com.amazonaws.ap-northeast-1.ssm --subnet-ids subnet-app1a subnet-app1c --security-group-ids sg-0ec21234567890fg0 --private-dns-enabled

Interface型エンドポイントで--private-dns-enabledを指定すると、
通常のサービスエンドポイント(例: ssm.ap-northeast-1.amazonaws.com)へのDNS名がVPC内のプライベートIPに解決されます。
コードを変更せずにそのまま使えるため、移行コストを最小化できます。
NATゲートウェイのデータ転送コストが月数万円規模になっている場合は、まずGateway型から導入して効果を確認してください。

マルチAZ構成で可用性を高める

AWSではデータセンターのような物理施設を「アベイラビリティゾーン(AZ)」と呼びます。
東京リージョン(ap-northeast-1)には複数のAZがあり、それぞれが物理的に独立した電源・ネットワークを持ちます。

マルチAZ構成とは、複数のAZにサブネット・リソースを分散配置することで、
1つのAZに障害が発生しても残りのAZでシステムを継続稼動させる設計
です。

1. マルチAZ構成の基本パターン

典型的なWebアプリケーションのマルチAZ構成を示します。

レイヤー AZ-1a(東京) AZ-1c(東京)
パブリックサブネット 10.0.1.0/24(ALB・踏み台) 10.0.2.0/24(ALB・NATゲートウェイ)
プライベートサブネット(Web) 10.0.11.0/24(EC2 Webサーバー・Lambda) 10.0.12.0/24(EC2 Webサーバー・Lambda)
プライベートサブネット(DB) 10.0.21.0/24(RDSプライマリ) 10.0.22.0/24(RDSスタンバイ)

この構成のポイントは次の通りです。
・ALB(Application Load Balancer)を2つのAZのパブリックサブネットに配置し、Webサーバーへのトラフィックを分散
・Webサーバーは2つのAZのプライベートサブネットに配置(ALB配下でオートスケーリング対応)
・RDSはマルチAZで配置し、プライマリに障害発生時にスタンバイへ自動フェールオーバー

なお、NATゲートウェイは各AZに1つずつ配置するのがベストプラクティスです。
1つのAZにNATゲートウェイが集中すると、そのAZに障害が起きたときに
他のAZからのインターネットアウトバウンド通信も止まってしまいます。
Lambda関数を複数AZのプライベートサブネットに分散配置している場合も同様です。
各AZのプライベートサブネット用ルートテーブルに、同じAZのNATゲートウェイを向けておくことで、
クロスAZ転送コストを抑えながら高可用性を確保できます。

2. ALBのマルチAZ設定

ALBはインターネット向け(internet-facing)で作成し、2つのパブリックサブネットを指定します。
ALBは指定したサブネットのAZに自動でノードを配置し、マルチAZのリクエスト分散を行います。

# ALBを作成する(2つのパブリックサブネットを指定) $ aws elbv2 create-load-balancer --name web-prod-alb --subnets subnet-0pub1a234567890ab subnet-0pub1c234567890cd --security-groups sg-0alb1234567890ef0 --scheme internet-facing --type application # 実行結果(抜粋) { "LoadBalancers": [{ "DNSName": "web-prod-alb-1234567890.ap-northeast-1.elb.amazonaws.com", "AvailabilityZones": [ {"ZoneName": "ap-northeast-1a", "SubnetId": "subnet-0pub1a234567890ab"}, {"ZoneName": "ap-northeast-1c", "SubnetId": "subnet-0pub1c234567890cd"} ], "State": {"Code": "active"} }] } # ターゲットグループを作成する(EC2のアプリポート8080に転送) $ aws elbv2 create-target-group --name web-prod-tg --protocol HTTP --port 8080 --vpc-id vpc-0a1b2c3d4e5f60001 --health-check-path /health --health-check-interval-seconds 30

ヘルスチェックパス(/health)はEC2アプリが200を返すエンドポイントを指定します。
ここで200が返らないとALBはそのEC2をターゲットから除外するため、アプリ起動後に必ず疎通確認を行ってください。
ALBのDNS名(web-prod-alb-xxx.ap-northeast-1.elb.amazonaws.com)がアプリのエンドポイントになるので、
Route 53でカスタムドメインをAliasレコードでこのDNS名に向けるのが定石です。

3. Auto ScalingグループによるEC2のマルチAZ分散

EC2をマルチAZに分散するには、Auto ScalingグループにVPCゾーンID(プライベートサブネット)を複数指定します。

# Auto Scalingグループを作成する(2つのプライベートサブネットを指定) $ aws autoscaling create-auto-scaling-group --auto-scaling-group-name web-prod-asg --launch-template LaunchTemplateId=lt-0abcdef1234567890,Version='\' --min-size 2 --max-size 6 --desired-capacity 2 --vpc-zone-identifier "subnet-0app1a234567890ef,subnet-0app1c234567890gh" --target-group-arns arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/web-prod-tg/abc --health-check-type ELB --health-check-grace-period 60 # EC2インスタンスが2つのAZに分散されているか確認する $ aws ec2 describe-instances --filters "Name=tag:aws:autoscaling:groupName,Values=web-prod-asg" --query 'Reservations[*].Instances[*].{ID:InstanceId,AZ:Placement.AvailabilityZone,State:State.Name}' --output table # 実行結果 # +-------------------+------------------+------------------+ # | AZ | ID | State | # +-------------------+------------------+------------------+ # | ap-northeast-1a | i-0abc1234ef56 | running | # | ap-northeast-1c | i-0def5678gh90 | running | # +-------------------+------------------+------------------+

--min-size 2 にすることで、ASGは常に2台以上のEC2を維持します。
2台が異なるAZに分散されるため、1AZが落ちても残りのAZのEC2がリクエストを引き続き処理できます。

4. 踏み台サーバー(Bastion Host)の配置

プライベートサブネット内のサーバーにSSHで接続する際は、「踏み台サーバー」を経由する方法が一般的です。
踏み台サーバーはパブリックサブネットに配置し、自分のPCから踏み台にSSH、踏み台からプライベートサブネット内のサーバーにSSHという2段階の接続を行います。

# 踏み台サーバー経由でプライベートEC2に接続するSSH設定例(~/.ssh/config) Host bastion HostName 203.0.113.10 # 踏み台サーバーのElastic IP User ec2-user IdentityFile ~/.ssh/mykey.pem Host private-web HostName 10.0.11.20 # プライベートサブネット内のEC2プライベートIP User ec2-user IdentityFile ~/.ssh/mykey.pem ProxyJump bastion # 使い方(自分のPCから実行) # $ ssh private-web # → 踏み台(203.0.113.10)を経由してプライベートEC2(10.0.11.20)に接続される

踏み台サーバーのセキュリティグループは、
SSH(22番ポート)のインバウンドを「自分のPCのIPアドレス/32」のみに制限してください。
0.0.0.0/0に開放することは絶対に避けてください。
なお近年は踏み台サーバーを使わずに、AWS Systems Manager Session Managerを使ってSSHなしでEC2に接続する方法も増えています。SSHポートの開放が不要なため、セキュリティをさらに高めたい場合は検討してください。

5. AZ名とAZ IDの違い(マルチアカウント運用の注意点)

AZの名前(ap-northeast-1aなど)は、AWSアカウントごとに物理的な場所が異なります。
あるアカウントの「ap-northeast-1a」と別アカウントの「ap-northeast-1a」は、実は異なる物理的なAZを指していることがあります。

複数アカウントにまたがって同じ物理AZを使いたい場合(Transit GatewayやResource Access Managerを使った共有構成など)は、AZ ID(東京リージョンの例:apne1-az1・apne1-az2・apne1-az4)を使って管理する必要があります。
AZ IDはAWSコンソールの「EC2 > Availability Zones」ページで確認できます。

VPCフローログで通信を可視化・監査する

VPCを設計して動かし始めたとき、「セキュリティグループは意図通りに動いているか」「プライベートサブネットから想定外の通信が出ていないか」を確認する手段が必要です。
そのために使うのが「VPCフローログ(VPC Flow Logs)」です。

VPCフローログは、VPC内のネットワークインターフェース(ENI: Elastic Network Interface)を通過するIPトラフィックのACCEPT/REJECTを記録するサービスです。
実際のパケットの中身(ペイロード)は記録されませんが、送信元IP・宛先IP・ポート・プロトコル・通信量・判定結果が記録されます。

フローログは「問題が起きてから有効にしても遅い」サービスです。
本番環境ではVPC設計の段階でフローログの出力先を決めておくことを強くすすめます。

1. フローログが記録する主要フィールド

フローログのレコードには以下のフィールドが含まれます。

フィールド 内容 主な活用場面
srcaddr 送信元IPアドレス 不審なアクセス元の特定
dstaddr 宛先IPアドレス 想定外の通信先の検出
srcport / dstport 送信元・宛先ポート 使用サービス・プロトコルの確認
protocol プロトコル番号(6=TCP、17=UDP、1=ICMP) 通信種別の把握
action ACCEPT または REJECT セキュリティグループ・NACLの動作確認
bytes 転送バイト数 異常な大量転送の検出
log-status OK / NODATA / SKIPDATA ログ欠損の確認

2. 出力先の設計(S3 vs CloudWatch Logs)

フローログの出力先は「S3」か「CloudWatch Logs」のどちらかを選択します。

観点 S3出力 CloudWatch Logs出力
コスト 低い(長期保存向き) 高い(リアルタイム向き)
分析ツール Athena・QuickSight CloudWatch Insights
リアルタイム性 約5分の遅延 約2分の遅延
アラート連携 Lambda経由で可能 Metric Filter + Alarmで直接可能
推奨ユースケース 監査・コスト分析・長期保存 リアルタイム異常検知

長期保存・コスト効率を重視するならS3(Parquet形式)、
REJECTスパイクをリアルタイムで検知したいならCloudWatch Logs+Metric Filter+Alarmが定石です。
本番環境では両方を組み合わせるケースもあります。

3. フローログレコードの読み方

実際のフローログのレコードはスペース区切りで記録されます。

# フローログレコードの例(v2フォーマット: version account-id interface-id srcaddr dstaddr srcport dstport protocol packets bytes start end action log-status) # 203.0.113.45からポート443へのHTTPS通信(ACCEPT) 2 123456789012 eni-0a1b2c3d4e5f 203.0.113.45 10.0.1.50 52341 443 6 15 1823 1688000000 1688000059 ACCEPT OK # 198.51.100.22からSSH(22番ポート)への接続試行(REJECT) # → SGでSSHの送信元IPが制限されているため弾かれた 2 123456789012 eni-0a1b2c3d4e5f 198.51.100.22 10.0.1.50 54321 22 6 3 180 1688000000 1688000059 REJECT OK # EC2(10.0.1.50)からRDS(10.0.2.30)の3306番への通信(ACCEPT) # → プライベートサブネット間の正常な通信 2 123456789012 eni-0a1b2c3d4e5f 10.0.1.50 10.0.2.30 49152 3306 6 8 1024 1688000000 1688000059 ACCEPT OK

・予期しないREJECT:外部から特定ポートへのREJECTが大量に記録されている場合、攻撃スキャンの可能性あり
・予期しないACCEPT:本来ブロックすべき通信がACCEPTされていた場合、SGの設定漏れを疑う
・NACLとSGの切り分け:NACLがREJECTした通信はSGに到達する前に遮断される。どちらが遮断したかをフローログのactionフィールドで確認できる

Transit Gateway接続時のCIDR重複回避

複数のVPCや拠点をTransit Gateway(TGW)で接続するとき、最も頻繁に起きるトラブルが「CIDRの重複」です。
VPCを作る前に会社・プロジェクト全体のアドレス計画を台帳にまとめておくことが重要です。

1. 重複すると何が起きるか

TGWにアタッチされた2つのVPCが同じCIDR(たとえば両方10.0.0.0/16)を持つと、ルートテーブルでどちらに転送すべきか判定できなくなり、通信が成立しません。アタッチ自体は成功することがありますが、実際にパケットを送ると届きません。

VPC Peeringでも同様で、CIDRが重複している場合はピアリング接続の作成時点でエラーになります。
また、Site-to-Site VPNやDirect Connectでオンプレミスと接続する場合は、オンプレミス側のCIDRとも重複しないよう設計する必要があります。

2. CIDR管理台帳を先に作る

VPCを作る前に、全VPC・拠点のCIDRをリスト化して重複がないことを確認する習慣をつけてください。

# CIDRブロック管理台帳(例) 環境 CIDR リージョン/拠点 -------------------------------------------------- 本番 (AWS) 10.0.0.0/16 ap-northeast-1 本番VPC ステージング 10.1.0.0/16 ap-northeast-1 ステージングVPC 開発 10.2.0.0/16 ap-northeast-1 開発VPC DR (AWS) 10.3.0.0/16 ap-northeast-3 DR用VPC オンプレ拠点A 10.100.0.0/16 東京データセンター オンプレ拠点B 10.101.0.0/16 大阪データセンター 将来予備 10.10.0.0/16 未使用(拡張用)

「192.168.0.0/16は家庭用ルーターでも使われるため避けるべき」「10.0.0.0/8を事業全体で管理して各チームに/16単位で払い出す」といった方針を、早い段階でチームとして合意しておくことが大切です。

3. Amazon VPC IPAMの活用

AWSにはAmazon VPC IPAM(IP Address Manager)というCIDR払い出しを一元管理するサービスがあります。
Terraform等のIaCと組み合わせて、VPCを作る際にIPAMから自動的にCIDRを割り当てる設計にすると、手作業ミスによる重複を防げます。

複数のAWSアカウントやリージョンをまたいで管理する場合は、IPAMプールを階層構造で設計し、「本番アカウント用プール」「開発アカウント用プール」のように管理するとスケールします。

4. CLIでVPC・サブネットのCIDR設計を確認する

VPCとサブネットのCIDR設計は、aws ec2コマンドで実際の設定値を確認・検証できます。
Terraformや CloudFormationで作成した場合も、同じコマンドで設計書通りに構築されているかを検証できます。
Transit Gatewayでの接続前に、接続先VPCとのCIDR重複を確認する際にも活用してください。

# アカウント内のVPC一覧とCIDRブロックを表示する(デフォルトVPCを除外) # requires: aws configure 設定済み・ec2:DescribeVpcs 権限が必要 $ aws ec2 describe-vpcs --filters Name=isDefault,Values=false --query 'Vpcs[*].{VpcId:VpcId,CIDR:CidrBlock,Name:Tags[?Key==]|[0].Value,State:State}' --output table # 実行結果の例 # +--------------+-------------+----------+----------------------+ # | CIDR | Name | State | VpcId | # +--------------+-------------+----------+----------------------+ # | 10.0.0.0/16 | prod-vpc | available| vpc-0a1b2c3d4e5f60001| # | 10.1.0.0/16 | stg-vpc | available| vpc-0b2c3d4e5f670002 | # | 10.2.0.0/16 | dev-vpc | available| vpc-0c3d4e5f67890003 | # +--------------+-------------+----------+----------------------+ # 環境ごとに第2オクテットが異なることをひと目で確認できる # 特定VPCのサブネット一覧(AZとCIDRをまとめて確認) $ aws ec2 describe-subnets --filters Name=vpc-id,Values=vpc-0a1b2c3d4e5f60001 --query 'Subnets[*].{AZ:AvailabilityZone,CIDR:CidrBlock,Name:Tags[?Key==]|[0].Value,Public:MapPublicIpOnLaunch}' --output table # ピアリング前のCIDR重複チェック(既存ピアリング接続のCIDRを確認) $ aws ec2 describe-vpc-peering-connections --query 'VpcPeeringConnections[*].{Status:Status.Code,Requester:RequesterVpcInfo.CidrBlock,Accepter:AccepterVpcInfo.CidrBlock}' --output table

接続したい2つのVPCのCIDRが重複していないことを確認してからピアリング申請を行います。
重複している場合は、どちらかのVPCを作り直す(またはVPC IPAMを使って別CIDRを確保する)しか解決策はありません。
設計段階で重複を防ぐためにも、CIDR管理台帳を先に整備する習慣が、Transit Gateway導入時のトラブルを防ぐ最善策です。

VPC設計でよくあるトラブルと対処法

aws vpc 設計を初めて行う際に、実際によく直面するトラブルと対処法をまとめます。
フローログが有効になっていれば、切り分け作業がより確実に進められます。

1. プライベートサブネットのEC2がインターネットに繋がらない

最も多いトラブルです。次の順番で確認してください。

# チェックリスト(上から順に確認する) # 1. NATゲートウェイが「利用可能」状態か確認 # AWSコンソール → VPC → NATゲートウェイ → ステータスを確認 # 2. プライベートサブネットのルートテーブルを確認 # 「0.0.0.0/0 → nat-xxxxxxxxxx」のルートが存在するか確認 # 3. NATゲートウェイがパブリックサブネットに配置されているか確認 # NATゲートウェイがプライベートサブネットに作られているとアウトバウンドが通らない # 4. EC2からpingで確認 # $ ping 8.8.8.8 # → 到達できれば外部通信OK。できなければルートテーブルかセキュリティグループを再確認 # 5. フローログが有効な場合:プライベートサブネットのENIのフローログを確認 # EC2からNATゲートウェイへの通信がACCEPTされているか確認する

2. セキュリティグループの設定後もSSHで繋がらない

セキュリティグループでSSHを許可したのに接続できない場合、よくある原因は以下です。
・自分のPCのグローバルIPアドレスが変わっている:プロバイダの都合でIPが変動することがある。現在のIPを確認して再設定する
・踏み台サーバー経由が必要なのに直接接続しようとしている:プライベートサブネットのEC2にはパブリックIPがない
・キーペアが間違っている:EC2作成時に指定したキーペア(.pemファイル)と一致しているか確認する

# 自分のPCの現在のグローバルIPアドレスを確認する $ curl -s https://checkip.amazonaws.com 203.0.113.50 # このIPアドレスをセキュリティグループのインバウンドルールに設定する # 送信元: 203.0.113.50/32 ポート: SSH(22) # フローログが有効な場合:踏み台サーバーのENIのフローログで # 自分のIPからSSH(22番)への通信がREJECTされていないか確認する

3. RDSにアプリケーションから繋がらない

アプリケーションサーバーからRDSへの接続が失敗する場合は、次の点を確認してください。
・RDSのセキュリティグループ:アプリケーションサーバー用SGを送信元として3306番(MySQL)や5432番(PostgreSQL)が許可されているか
・サブネットグループ:RDSのサブネットグループにアプリケーションサーバーと同じVPCのサブネットが含まれているか

「セキュリティグループは設定した」という場合でも、送信元をIPではなくSGで指定しているかを確認してください。
間違えてアプリサーバーのIPを直接指定すると、IPが変動したときに接続が切れます。

フローログを使って切り分ける場合は次の手順が有効です。
・ステップ1:EC2のENIのフローログを確認。RDSの3306番への通信がREJECTされているか確認する
・ステップ2:RDSのENIのフローログを確認。EC2からのパケットがRDS側のENIに到達しているか確認する
・ステップ3:NACLがステートレスのため、アウトバウンドのエフェメラルポート(1024~65535)の許可漏れも疑う

# RDS-SGの設定確認(UserIdGroupPairsにEC2-SGのみが入っているか) $ aws ec2 describe-security-groups --group-ids sg-0rds1234567890gh0 --query 'SecurityGroups[0].IpPermissions[?FromPort==]' # RDSのエンドポイントDNS名を名前解決して疎通確認する $ nslookup web-prod-mysql.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com # プライベートIP(10.0.21.x)が返れば名前解決は正常 # 失敗する場合はVPCのenableDnsHostnames/enableDnsSupportを確認する $ aws ec2 describe-vpc-attribute --vpc-id vpc-0a1b2c3d4e5f60001 --attribute enableDnsHostnames

4. ALBのヘルスチェックが失敗してEC2がunhealthyになる

ALBのターゲットグループでEC2が「unhealthy」になる場合、次の順で確認してください。

# 確認1: EC2-SGでALB-SGからのアクセスが許可されているか $ aws ec2 describe-security-groups --group-ids sg-0ec21234567890fg0 --query 'SecurityGroups[0].IpPermissions' # ポート8080・送信元sg-0alb1234567890ef0 のルールが存在するか確認する # 確認2: EC2上でアプリが指定ポートでlistenしているか # (AWS Systems Manager Session Managerでポート確認) $ ss -tlnp | grep 8080 # 正常時の出力例: # LISTEN 0 128 0.0.0.0:8080 0.0.0.0:* users:(("java",pid=1234,fd=42)) # 何も返らない場合はアプリが起動していないか別ポートでlistenしている # 確認3: ヘルスチェックパスが200を返すか $ curl -o /dev/null -s -w "%{http_code}" http://localhost:8080/health # 200が返れば正常。200以外ならアプリのヘルスチェック実装を確認する

まとめ:VPC設計のベストプラクティス

この記事で解説したaws vpc 設計のポイントをまとめます。

設計項目 ベストプラクティス
CIDRブロック 余裕を持って 10.0.0.0/16 を選択。作成後変更不可。/24より小さいサブネットは避ける
AWSが予約するIP 各サブネットで先頭4つ+末尾1つ(計5個)はAWSが予約。設計時に差し引いて計算する
サブネット分割 パブリック(ALB)・アプリプライベート(EC2・Lambda)・DBプライベート(RDS)の3層に分ける
環境分離 本番・ステージング・開発はVPCを分ける。第2オクテットで環境を区別して管理する
ALB パブリックサブネットのマルチAZに配置。ターゲットグループのヘルスチェックを設定する
セキュリティグループ ALB-SG→EC2-SG→RDS-SGのSG参照チェーンで3層防御。SSHは特定IPのみ。Lambda等は専用SGで
ネットワークACL セキュリティグループを主軸に。明示的なブロックが必要な場合のみ活用
NATゲートウェイ パブリックサブネットに配置。本番はAZ数分用意する。不要時は削除してEIPも解放
VPCエンドポイント S3・DynamoDBはGateway型(無料)を優先導入。SSM等はInterface型。NATコスト削減に有効
マルチAZ 本番環境は必ず複数AZにサブネットを分散。RDS・NATゲートウェイも各AZに
踏み台サーバー パブリックサブネットに配置。SSHアクセスは自分のPCのIPに限定
VPCフローログ VPC設計の段階で有効化先を決める。S3(長期保存)かCloudWatch Logs(リアルタイム)を選択
Transit Gateway 接続前に全VPC・オンプレのCIDRを管理台帳でリスト化し、重複がないことを必ず確認
VPC DNS設定 enableDnsHostnames/enableDnsSupportを有効にする(RDSエンドポイント名解決に必須)
CIDR設計の確認 aws ec2 describe-vpcs / describe-subnetsでCIDRとAZ配置を検証する

VPC設計は「最初に正しく作ると後が楽」なインフラの基盤です。
CIDRブロックの設計から環境分離・Transit Gateway接続まで、この記事の構成を参考に、まずは検証環境で一度手を動かしてみてください。
一度作ってみると、各コンポーネントの関係がぐっと分かりやすくなります。

より複雑な冗長設計(マルチリージョン・VPC Peering等)は
AWS冗長設計入門で解説しています。あわせてご覧ください。

現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
Linux無料マニュアルを受け取る >>

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。