第13章:仮想ネットワークの設計と実装
13.1 はじめに:物理的制約からの解放
従来のデータセンターでは、ネットワークケーブルを物理的に配線し、スイッチやルーターを設置する必要がありました。新しいネットワークセグメントを追加するには、機器の購入、ラックへの設置、ケーブリング作業が必要で、数週間かかることも珍しくありませんでした。
クラウドの仮想ネットワークは、この物理的制約から私たちを解放しました。数クリック、あるいは数行のコードで、完全に隔離されたネットワーク環境を作成できる。この革命的な変化が、どのような技術によって実現されているのか、本章で詳しく見ていきましょう。
13.2 物理的制約からの解放
従来のネットワーク構築の課題
物理ネットワークの制約
【従来のネットワーク拡張プロセス】
1. 要件定義(2週間)
- 必要なポート数、帯域幅の計算
- セキュリティ要件の確認
2. 機器調達(4週間)
- スイッチ、ルーター、ファイアウォールの選定
- 見積もり、承認、発注
3. 物理作業(1週間)
- ラックスペースの確保
- 機器の設置
- ケーブリング
4. 設定作業(1週間)
- VLAN設定
- ルーティング設定
- セキュリティ設定
合計:約2ヶ月
仮想ネットワークの革新
Software Defined Network(SDN)の概念
AWSにおける実装:VPC
5分で構築できる企業ネットワーク
# 1. VPCの作成(仮想データセンター)
aws ec2 create-vpc --cidr-block 10.0.0.0/16
# 2. サブネットの作成(ネットワークセグメント)
aws ec2 create-subnet --vpc-id vpc-12345 --cidr-block 10.0.1.0/24
aws ec2 create-subnet --vpc-id vpc-12345 --cidr-block 10.0.2.0/24
# 3. インターネットゲートウェイの接続
aws ec2 create-internet-gateway
aws ec2 attach-internet-gateway --vpc-id vpc-12345 --internet-gateway-id igw-12345
# 4. ルーティング設定
aws ec2 create-route-table --vpc-id vpc-12345
aws ec2 create-route --route-table-id rtb-12345 --destination-cidr-block 0.0.0.0/0 --gateway-id igw-12345
# 完了!企業グレードのネットワークが稼働
13.3 SDNとVPCの仕組み
VPC(Virtual Private Cloud)の構造
論理的な隔離
ネットワーク仮想化の技術
VXLAN(Virtual Extensible LAN)
実践的なVPC設計
マルチティアアーキテクチャ
# vpc-architecture.yaml - CloudFormationテンプレート
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Multi-tier VPC architecture'
Parameters:
EnvironmentName:
Type: String
Default: Production
Resources:
# VPC本体
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-VPC
# パブリックサブネット(Web層)
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [0, !GetAZs '']
CidrBlock: 10.0.1.0/24
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-Public-Subnet-AZ1
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [1, !GetAZs '']
CidrBlock: 10.0.2.0/24
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-Public-Subnet-AZ2
# プライベートサブネット(アプリケーション層)
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [0, !GetAZs '']
CidrBlock: 10.0.11.0/24
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-Private-Subnet-AZ1
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [1, !GetAZs '']
CidrBlock: 10.0.12.0/24
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-Private-Subnet-AZ2
# データベースサブネット(データ層)
DatabaseSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [0, !GetAZs '']
CidrBlock: 10.0.21.0/24
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-Database-Subnet-AZ1
DatabaseSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [1, !GetAZs '']
CidrBlock: 10.0.22.0/24
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-Database-Subnet-AZ2
# インターネットゲートウェイ
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-IGW
InternetGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC
# NATゲートウェイ用のElastic IP
NatGateway1EIP:
Type: AWS::EC2::EIP
DependsOn: InternetGatewayAttachment
Properties:
Domain: vpc
NatGateway2EIP:
Type: AWS::EC2::EIP
DependsOn: InternetGatewayAttachment
Properties:
Domain: vpc
# NATゲートウェイ
NatGateway1:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt NatGateway1EIP.AllocationId
SubnetId: !Ref PublicSubnet1
NatGateway2:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt NatGateway2EIP.AllocationId
SubnetId: !Ref PublicSubnet2
# ルートテーブル
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-Public-Routes
DefaultPublicRoute:
Type: AWS::EC2::Route
DependsOn: InternetGatewayAttachment
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicRouteTable
SubnetId: !Ref PublicSubnet1
PublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicRouteTable
SubnetId: !Ref PublicSubnet2
# プライベートルートテーブル
PrivateRouteTable1:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-Private-Routes-AZ1
DefaultPrivateRoute1:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable1
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway1
PrivateSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateRouteTable1
SubnetId: !Ref PrivateSubnet1
DatabaseSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateRouteTable1
SubnetId: !Ref DatabaseSubnet1
13.4 セキュアで柔軟なネットワーク設計
ゼロトラストネットワークの実装
セキュリティグループによるマイクロセグメンテーション
# Web層のセキュリティグループ
aws ec2 create-security-group \
--group-name web-sg \
--description "Security group for web servers" \
--vpc-id vpc-12345
# インターネットからのHTTP/HTTPSのみ許可
aws ec2 authorize-security-group-ingress \
--group-id sg-web \
--protocol tcp \
--port 80 \
--cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress \
--group-id sg-web \
--protocol tcp \
--port 443 \
--cidr 0.0.0.0/0
# アプリケーション層のセキュリティグループ
aws ec2 create-security-group \
--group-name app-sg \
--description "Security group for application servers" \
--vpc-id vpc-12345
# Web層からのみアクセス許可
aws ec2 authorize-security-group-ingress \
--group-id sg-app \
--protocol tcp \
--port 8080 \
--source-group sg-web
# データベース層のセキュリティグループ
aws ec2 create-security-group \
--group-name db-sg \
--description "Security group for database servers" \
--vpc-id vpc-12345
# アプリケーション層からのみアクセス許可
aws ec2 authorize-security-group-ingress \
--group-id sg-db \
--protocol tcp \
--port 3306 \
--source-group sg-app
ネットワークACLによる追加の防御層
# network_acl_setup.sh - サブネットレベルのファイアウォール
cat > network_acl_setup.sh << 'EOF'
#!/bin/bash
VPC_ID="vpc-12345"
PUBLIC_SUBNET_ID="subnet-public"
PRIVATE_SUBNET_ID="subnet-private"
# パブリックサブネット用NACL
PUBLIC_NACL=$(aws ec2 create-network-acl \
--vpc-id $VPC_ID \
--query 'NetworkAcl.NetworkAclId' \
--output text)
# インバウンドルール
# HTTP許可
aws ec2 create-network-acl-entry \
--network-acl-id $PUBLIC_NACL \
--rule-number 100 \
--protocol tcp \
--rule-action allow \
--ingress \
--port-range From=80,To=80 \
--cidr-block 0.0.0.0/0
# HTTPS許可
aws ec2 create-network-acl-entry \
--network-acl-id $PUBLIC_NACL \
--rule-number 110 \
--protocol tcp \
--rule-action allow \
--ingress \
--port-range From=443,To=443 \
--cidr-block 0.0.0.0/0
# エフェメラルポート(戻りトラフィック用)
aws ec2 create-network-acl-entry \
--network-acl-id $PUBLIC_NACL \
--rule-number 200 \
--protocol tcp \
--rule-action allow \
--ingress \
--port-range From=1024,To=65535 \
--cidr-block 0.0.0.0/0
# アウトバウンドルール
# すべて許可(簡略化のため)
aws ec2 create-network-acl-entry \
--network-acl-id $PUBLIC_NACL \
--rule-number 100 \
--protocol -1 \
--rule-action allow \
--egress \
--cidr-block 0.0.0.0/0
# NACLをサブネットに関連付け
aws ec2 associate-network-acl \
--network-acl-id $PUBLIC_NACL \
--subnet-id $PUBLIC_SUBNET_ID
EOF
VPCピアリングとTransit Gateway
複数VPC間の接続
# VPCピアリング接続の作成
aws ec2 create-vpc-peering-connection \
--vpc-id vpc-11111 \
--peer-vpc-id vpc-22222 \
--peer-region ap-northeast-1
# ピアリング接続の承認
aws ec2 accept-vpc-peering-connection \
--vpc-peering-connection-id pcx-12345
# ルーティングの追加
aws ec2 create-route \
--route-table-id rtb-11111 \
--destination-cidr-block 10.1.0.0/16 \
--vpc-peering-connection-id pcx-12345
Transit Gatewayによるハブ&スポーク構成
# transit_gateway_setup.py
import boto3
ec2 = boto3.client('ec2')
# Transit Gatewayの作成
tgw_response = ec2.create_transit_gateway(
Description='Central hub for VPC connectivity',
Options={
'AmazonSideAsn': 64512,
'DefaultRouteTableAssociation': 'enable',
'DefaultRouteTablePropagation': 'enable',
'DnsSupport': 'enable',
'VpnEcmpSupport': 'enable'
},
TagSpecifications=[{
'ResourceType': 'transit-gateway',
'Tags': [{'Key': 'Name', 'Value': 'CentralHub-TGW'}]
}]
)
tgw_id = tgw_response['TransitGateway']['TransitGatewayId']
# 各VPCをTransit Gatewayに接続
vpcs = ['vpc-11111', 'vpc-22222', 'vpc-33333']
for vpc_id in vpcs:
# サブネット情報を取得
subnets = ec2.describe_subnets(
Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}]
)['Subnets']
subnet_ids = [s['SubnetId'] for s in subnets[:2]] # 2つのAZを使用
# アタッチメントの作成
attachment = ec2.create_transit_gateway_vpc_attachment(
TransitGatewayId=tgw_id,
VpcId=vpc_id,
SubnetIds=subnet_ids,
TagSpecifications=[{
'ResourceType': 'transit-gateway-attachment',
'Tags': [{'Key': 'Name', 'Value': f'{vpc_id}-attachment'}]
}]
)
print(f"Created attachment for {vpc_id}: {attachment['TransitGatewayVpcAttachment']['TransitGatewayAttachmentId']}")
13.5 演習:マルチティアアーキテクチャの構築
演習1:基本的なVPC構築
# basic_vpc_setup.sh
cat > basic_vpc_setup.sh << 'EOF'
#!/bin/bash
echo "=== Basic VPC Setup ==="
# 変数定義
REGION="ap-northeast-1"
VPC_CIDR="10.0.0.0/16"
PUBLIC_SUBNET_CIDR="10.0.1.0/24"
PRIVATE_SUBNET_CIDR="10.0.2.0/24"
# 1. VPCの作成
echo "Creating VPC..."
VPC_ID=$(aws ec2 create-vpc \
--cidr-block $VPC_CIDR \
--tag-specifications "ResourceType=vpc,Tags=[{Key=Name,Value=Demo-VPC}]" \
--query 'Vpc.VpcId' \
--output text)
echo "Created VPC: $VPC_ID"
# DNSサポートを有効化
aws ec2 modify-vpc-attribute \
--vpc-id $VPC_ID \
--enable-dns-hostnames
# 2. サブネットの作成
echo "Creating subnets..."
# パブリックサブネット
PUBLIC_SUBNET_ID=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block $PUBLIC_SUBNET_CIDR \
--availability-zone ${REGION}a \
--tag-specifications "ResourceType=subnet,Tags=[{Key=Name,Value=Public-Subnet}]" \
--query 'Subnet.SubnetId' \
--output text)
# プライベートサブネット
PRIVATE_SUBNET_ID=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block $PRIVATE_SUBNET_CIDR \
--availability-zone ${REGION}a \
--tag-specifications "ResourceType=subnet,Tags=[{Key=Name,Value=Private-Subnet}]" \
--query 'Subnet.SubnetId' \
--output text)
# 3. インターネットゲートウェイ
echo "Creating Internet Gateway..."
IGW_ID=$(aws ec2 create-internet-gateway \
--tag-specifications "ResourceType=internet-gateway,Tags=[{Key=Name,Value=Demo-IGW}]" \
--query 'InternetGateway.InternetGatewayId' \
--output text)
aws ec2 attach-internet-gateway \
--vpc-id $VPC_ID \
--internet-gateway-id $IGW_ID
# 4. ルートテーブルの設定
echo "Configuring route tables..."
# パブリックルートテーブル
PUBLIC_RT_ID=$(aws ec2 create-route-table \
--vpc-id $VPC_ID \
--tag-specifications "ResourceType=route-table,Tags=[{Key=Name,Value=Public-RT}]" \
--query 'RouteTable.RouteTableId' \
--output text)
# デフォルトルートの追加
aws ec2 create-route \
--route-table-id $PUBLIC_RT_ID \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id $IGW_ID
# サブネットとの関連付け
aws ec2 associate-route-table \
--subnet-id $PUBLIC_SUBNET_ID \
--route-table-id $PUBLIC_RT_ID
# 5. セキュリティグループの作成
echo "Creating security groups..."
# Webサーバー用セキュリティグループ
WEB_SG_ID=$(aws ec2 create-security-group \
--group-name web-sg \
--description "Security group for web servers" \
--vpc-id $VPC_ID \
--tag-specifications "ResourceType=security-group,Tags=[{Key=Name,Value=Web-SG}]" \
--query 'GroupId' \
--output text)
# ルールの追加
aws ec2 authorize-security-group-ingress \
--group-id $WEB_SG_ID \
--protocol tcp \
--port 80 \
--cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress \
--group-id $WEB_SG_ID \
--protocol tcp \
--port 443 \
--cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress \
--group-id $WEB_SG_ID \
--protocol tcp \
--port 22 \
--cidr $(curl -s https://checkip.amazonaws.com)/32
echo "VPC setup completed!"
echo "VPC ID: $VPC_ID"
echo "Public Subnet: $PUBLIC_SUBNET_ID"
echo "Private Subnet: $PRIVATE_SUBNET_ID"
echo "Web Security Group: $WEB_SG_ID"
EOF
chmod +x basic_vpc_setup.sh
演習2:高可用性ネットワーク設計
# ha_network_setup.sh
cat > ha_network_setup.sh << 'EOF'
#!/bin/bash
echo "=== High Availability Network Setup ==="
# マルチAZ構成の自動構築
create_ha_network() {
local vpc_cidr="10.0.0.0/16"
local region=$(aws ec2 describe-availability-zones --query 'AvailabilityZones[0].RegionName' --output text)
# VPCの作成
vpc_id=$(aws ec2 create-vpc \
--cidr-block $vpc_cidr \
--query 'Vpc.VpcId' \
--output text)
echo "Created VPC: $vpc_id"
# 利用可能なAZを取得
azs=($(aws ec2 describe-availability-zones \
--filters "Name=state,Values=available" \
--query 'AvailabilityZones[*].ZoneName' \
--output text))
# 各AZにサブネットを作成
for i in {0..1}; do
az=${azs[$i]}
# パブリックサブネット
public_cidr="10.0.$((i+1)).0/24"
public_subnet=$(aws ec2 create-subnet \
--vpc-id $vpc_id \
--cidr-block $public_cidr \
--availability-zone $az \
--tag-specifications "ResourceType=subnet,Tags=[{Key=Name,Value=Public-$az}]" \
--query 'Subnet.SubnetId' \
--output text)
# プライベートサブネット
private_cidr="10.0.$((i+11)).0/24"
private_subnet=$(aws ec2 create-subnet \
--vpc-id $vpc_id \
--cidr-block $private_cidr \
--availability-zone $az \
--tag-specifications "ResourceType=subnet,Tags=[{Key=Name,Value=Private-$az}]" \
--query 'Subnet.SubnetId' \
--output text)
# データベースサブネット
db_cidr="10.0.$((i+21)).0/24"
db_subnet=$(aws ec2 create-subnet \
--vpc-id $vpc_id \
--cidr-block $db_cidr \
--availability-zone $az \
--tag-specifications "ResourceType=subnet,Tags=[{Key=Name,Value=Database-$az}]" \
--query 'Subnet.SubnetId' \
--output text)
echo "Created subnets in $az"
# Elastic IPとNATゲートウェイ
eip_alloc=$(aws ec2 allocate-address \
--domain vpc \
--query 'AllocationId' \
--output text)
nat_gw=$(aws ec2 create-nat-gateway \
--subnet-id $public_subnet \
--allocation-id $eip_alloc \
--tag-specifications "ResourceType=nat-gateway,Tags=[{Key=Name,Value=NAT-$az}]" \
--query 'NatGateway.NatGatewayId' \
--output text)
echo "Created NAT Gateway in $az: $nat_gw"
done
}
# フェイルオーバーテスト
test_failover() {
echo "Testing network failover..."
# プライマリNATゲートウェイを無効化
primary_nat=$(aws ec2 describe-nat-gateways \
--filter "Name=tag:Name,Values=NAT-*a" \
--query 'NatGateways[0].NatGatewayId' \
--output text)
echo "Simulating failure of primary NAT Gateway: $primary_nat"
# ルートテーブルの更新
# (実際の障害時は自動的に切り替わるが、ここでは手動でシミュレート)
}
# メイン処理
create_ha_network
EOF
chmod +x ha_network_setup.sh
演習3:ネットワークセキュリティの実装
# network_security.sh
cat > network_security.sh << 'EOF'
#!/bin/bash
echo "=== Network Security Implementation ==="
# WAFの設定
setup_waf() {
echo "Setting up Web Application Firewall..."
# IPセットの作成(ブロックリスト)
ipset_id=$(aws wafv2 create-ip-set \
--name blocked-ips \
--scope REGIONAL \
--ip-address-version IPV4 \
--addresses 192.0.2.0/24 198.51.100.0/24 \
--query 'Summary.Id' \
--output text)
# ルールグループの作成
cat > waf-rules.json << 'JSON'
{
"Name": "CustomRuleGroup",
"Scope": "REGIONAL",
"Capacity": 100,
"Rules": [
{
"Name": "RateLimitRule",
"Priority": 1,
"Statement": {
"RateBasedStatement": {
"Limit": 1000,
"AggregateKeyType": "IP"
}
},
"Action": {
"Block": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "RateLimitRule"
}
},
{
"Name": "SQLInjectionRule",
"Priority": 2,
"Statement": {
"SqliMatchStatement": {
"FieldToMatch": {
"AllQueryArguments": {}
},
"TextTransformations": [
{
"Priority": 0,
"Type": "URL_DECODE"
},
{
"Priority": 1,
"Type": "HTML_ENTITY_DECODE"
}
]
}
},
"Action": {
"Block": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "SQLInjectionRule"
}
}
]
}
JSON
aws wafv2 create-rule-group --cli-input-json file://waf-rules.json
}
# VPCフローログの設定
setup_flow_logs() {
echo "Setting up VPC Flow Logs..."
vpc_id=$1
# S3バケットの作成
bucket_name="vpc-flow-logs-$(date +%s)"
aws s3 mb s3://$bucket_name
# フローログの作成
aws ec2 create-flow-logs \
--resource-type VPC \
--resource-ids $vpc_id \
--traffic-type ALL \
--log-destination-type s3 \
--log-destination s3://$bucket_name/flow-logs/ \
--log-format '${srcaddr} ${dstaddr} ${srcport} ${dstport} ${protocol} ${packets} ${bytes} ${action}'
# 分析用のAthenaテーブル作成
cat > create_athena_table.sql << 'SQL'
CREATE EXTERNAL TABLE IF NOT EXISTS vpc_flow_logs (
srcaddr string,
dstaddr string,
srcport int,
dstport int,
protocol int,
packets bigint,
bytes bigint,
action string
)
PARTITIONED BY (dt string)
STORED AS PARQUET
LOCATION 's3://BUCKET_NAME/flow-logs/'
SQL
}
# プライベートリンクの設定
setup_privatelink() {
echo "Setting up VPC PrivateLink..."
# S3用のVPCエンドポイント
aws ec2 create-vpc-endpoint \
--vpc-id $VPC_ID \
--service-name com.amazonaws.${REGION}.s3 \
--route-table-ids $PRIVATE_RT_ID
# EC2用のインターフェースエンドポイント
aws ec2 create-vpc-endpoint \
--vpc-id $VPC_ID \
--service-name com.amazonaws.${REGION}.ec2 \
--vpc-endpoint-type Interface \
--subnet-ids $PRIVATE_SUBNET_ID \
--security-group-ids $ENDPOINT_SG_ID
}
# セキュリティグループの自動監査
audit_security_groups() {
echo "Auditing Security Groups..."
# 過度に緩いルールを検出
aws ec2 describe-security-groups \
--query 'SecurityGroups[?IpPermissions[?IpProtocol==`-1` && contains(IpRanges[].CidrIp, `0.0.0.0/0`)]].[GroupId,GroupName]' \
--output table
echo "Security groups with overly permissive rules detected above"
}
# メイン処理
setup_waf
setup_flow_logs "vpc-12345"
setup_privatelink
audit_security_groups
EOF
chmod +x network_security.sh
演習4:ハイブリッドクラウドネットワーク
# hybrid_cloud_network.sh
cat > hybrid_cloud_network.sh << 'EOF'
#!/bin/bash
echo "=== Hybrid Cloud Network Setup ==="
# Site-to-Site VPNの設定
setup_vpn() {
local vpc_id=$1
local on_premise_cidr="192.168.0.0/16"
local customer_gateway_ip="203.0.113.1" # オンプレミスのパブリックIP
# カスタマーゲートウェイの作成
cgw_id=$(aws ec2 create-customer-gateway \
--type ipsec.1 \
--public-ip $customer_gateway_ip \
--bgp-asn 65000 \
--tag-specifications "ResourceType=customer-gateway,Tags=[{Key=Name,Value=OnPremise-CGW}]" \
--query 'CustomerGateway.CustomerGatewayId' \
--output text)
# 仮想プライベートゲートウェイの作成
vgw_id=$(aws ec2 create-vpn-gateway \
--type ipsec.1 \
--amazon-side-asn 64512 \
--tag-specifications "ResourceType=vpn-gateway,Tags=[{Key=Name,Value=AWS-VGW}]" \
--query 'VpnGateway.VpnGatewayId' \
--output text)
# VPCにアタッチ
aws ec2 attach-vpn-gateway \
--vpc-id $vpc_id \
--vpn-gateway-id $vgw_id
# VPN接続の作成
vpn_id=$(aws ec2 create-vpn-connection \
--type ipsec.1 \
--customer-gateway-id $cgw_id \
--vpn-gateway-id $vgw_id \
--options "{\"StaticRoutesOnly\":false}" \
--tag-specifications "ResourceType=vpn-connection,Tags=[{Key=Name,Value=OnPremise-VPN}]" \
--query 'VpnConnection.VpnConnectionId' \
--output text)
echo "VPN Connection created: $vpn_id"
# VPN設定のダウンロード
aws ec2 describe-vpn-connections \
--vpn-connection-ids $vpn_id \
--query 'VpnConnections[0].CustomerGatewayConfiguration' \
--output text > vpn-config.xml
echo "VPN configuration saved to vpn-config.xml"
}
# Direct Connectの仮想インターフェース設定
setup_direct_connect_vif() {
echo "Setting up Direct Connect Virtual Interface..."
# 仮想インターフェースの作成(実際にはDirect Connect接続が必要)
cat > vif-config.json << 'JSON'
{
"connectionId": "dxcon-12345678",
"vlan": 100,
"customerAddress": "192.168.1.1/30",
"amazonAddress": "192.168.1.2/30",
"addressFamily": "ipv4",
"customerAsn": 65000,
"mtu": 1500,
"virtualInterfaceName": "Production-VIF"
}
JSON
# aws directconnect create-private-virtual-interface --cli-input-json file://vif-config.json
}
# Transit VPNによる複数サイト接続
setup_transit_vpn() {
echo "Setting up Transit VPN for multiple sites..."
# Transit Gatewayの作成
tgw_id=$(aws ec2 create-transit-gateway \
--description "Central hub for hybrid connectivity" \
--options '{
"AmazonSideAsn": 64512,
"DefaultRouteTableAssociation": "enable",
"DefaultRouteTablePropagation": "enable",
"VpnEcmpSupport": "enable"
}' \
--tag-specifications "ResourceType=transit-gateway,Tags=[{Key=Name,Value=Hybrid-TGW}]" \
--query 'TransitGateway.TransitGatewayId' \
--output text)
# 各サイトのVPN接続をTransit Gatewayに接続
sites=("Tokyo" "Osaka" "Nagoya")
for site in "${sites[@]}"; do
echo "Connecting $site site to Transit Gateway..."
# VPN接続の作成(省略)
done
}
# メイン処理
VPC_ID="vpc-12345"
setup_vpn $VPC_ID
# setup_direct_connect_vif
setup_transit_vpn
EOF
chmod +x hybrid_cloud_network.sh
演習5:ネットワークパフォーマンス最適化
# network_optimization.sh
cat > network_optimization.sh << 'EOF'
#!/bin/bash
echo "=== Network Performance Optimization ==="
# Enhanced Networkingの有効化
enable_enhanced_networking() {
instance_id=$1
# SR-IOVの有効化
aws ec2 modify-instance-attribute \
--instance-id $instance_id \
--sriov-net-support simple
# Elastic Network Adapter (ENA)の確認
ena_support=$(aws ec2 describe-instances \
--instance-ids $instance_id \
--query 'Reservations[0].Instances[0].EnaSupport' \
--output text)
if [ "$ena_support" != "True" ]; then
echo "Enabling ENA support..."
aws ec2 modify-instance-attribute \
--instance-id $instance_id \
--ena-support
fi
}
# Placement Groupの設定
setup_placement_group() {
# クラスタープレイスメントグループの作成
aws ec2 create-placement-group \
--group-name high-performance-cluster \
--strategy cluster
# パーティションプレイスメントグループの作成
aws ec2 create-placement-group \
--group-name distributed-workload \
--strategy partition \
--partition-count 7
}
# ネットワークパフォーマンステスト
network_performance_test() {
echo "Running network performance tests..."
# iperf3サーバーの起動
cat > iperf-server-userdata.sh << 'USERDATA'
#!/bin/bash
yum install -y iperf3
iperf3 -s -D
USERDATA
# テスト用インスタンスの起動
server_id=$(aws ec2 run-instances \
--image-id ami-12345678 \
--instance-type c5n.large \
--placement GroupName=high-performance-cluster \
--user-data file://iperf-server-userdata.sh \
--query 'Instances[0].InstanceId' \
--output text)
client_id=$(aws ec2 run-instances \
--image-id ami-12345678 \
--instance-type c5n.large \
--placement GroupName=high-performance-cluster \
--query 'Instances[0].InstanceId' \
--output text)
# テスト結果の収集
echo "Instances launched. Run iperf3 tests after they're ready."
}
# VPCピアリング最適化
optimize_vpc_peering() {
# Jumbo Framesの有効化
aws ec2 modify-vpc-attribute \
--vpc-id vpc-12345 \
--enable-dns-hostnames
# ルーティングの最適化
echo "Optimizing routing tables for VPC peering..."
# 最短経路の設定
aws ec2 create-route \
--route-table-id rtb-12345 \
--destination-cidr-block 10.1.0.0/16 \
--vpc-peering-connection-id pcx-12345
}
# CloudFrontとの統合
setup_cloudfront_integration() {
echo "Setting up CloudFront for static content delivery..."
# オリジンアクセスアイデンティティの作成
oai=$(aws cloudfront create-cloud-front-origin-access-identity \
--cloud-front-origin-access-identity-config '{
"CallerReference": "my-oai",
"Comment": "OAI for S3 bucket"
}' \
--query 'CloudFrontOriginAccessIdentity.Id' \
--output text)
# CloudFrontディストリビューションの作成
cat > cloudfront-config.json << 'JSON'
{
"CallerReference": "my-distribution",
"Comment": "CDN for web application",
"DefaultRootObject": "index.html",
"Origins": {
"Quantity": 1,
"Items": [
{
"Id": "S3-my-bucket",
"DomainName": "my-bucket.s3.amazonaws.com",
"S3OriginConfig": {
"OriginAccessIdentity": "origin-access-identity/cloudfront/OAI_ID"
}
}
]
},
"DefaultCacheBehavior": {
"TargetOriginId": "S3-my-bucket",
"ViewerProtocolPolicy": "redirect-to-https",
"TrustedSigners": {
"Enabled": false,
"Quantity": 0
},
"ForwardedValues": {
"QueryString": false,
"Cookies": {
"Forward": "none"
}
},
"MinTTL": 0,
"DefaultTTL": 86400,
"MaxTTL": 31536000
},
"Enabled": true
}
JSON
}
# メイン処理
enable_enhanced_networking "i-1234567890"
setup_placement_group
network_performance_test
optimize_vpc_peering
setup_cloudfront_integration
EOF
chmod +x network_optimization.sh
13.6 ネットワーク監視とトラブルシューティング
VPCフローログの分析
# analyze_flow_logs.py
import boto3
import pandas as pd
from datetime import datetime, timedelta
def analyze_vpc_flow_logs(bucket_name, vpc_id):
"""VPCフローログを分析して異常なトラフィックを検出"""
s3 = boto3.client('s3')
# フローログの読み込み
response = s3.select_object_content(
Bucket=bucket_name,
Key=f'flow-logs/{vpc_id}/2024/03/15/flow-log.gz',
ExpressionType='SQL',
Expression="""
SELECT srcaddr, dstaddr, srcport, dstport,
protocol, packets, bytes, action
FROM s3object s
WHERE cast(bytes as int) > 1000000
""",
InputSerialization={'CompressionType': 'GZIP', 'CSV': {}},
OutputSerialization={'CSV': {}}
)
# 結果の処理
records = []
for event in response['Payload']:
if 'Records' in event:
records.append(event['Records']['Payload'].decode())
# 異常検出
df = pd.DataFrame(records)
# 大量のデータ転送を検出
high_volume = df[df['bytes'] > 10000000]
# 拒否されたトラフィック
rejected = df[df['action'] == 'REJECT']
# ポートスキャンの可能性
port_scan = df.groupby('srcaddr')['dstport'].nunique()
suspicious_ips = port_scan[port_scan > 100].index
return {
'high_volume_transfers': high_volume,
'rejected_traffic': rejected,
'potential_port_scans': suspicious_ips
}
リアルタイムネットワーク監視
# realtime_monitoring.sh
#!/bin/bash
# CloudWatchメトリクスの設定
setup_cloudwatch_metrics() {
# カスタムメトリクスの送信
aws cloudwatch put-metric-data \
--namespace "NetworkMonitoring" \
--metric-name "PacketLoss" \
--value 0.5 \
--unit Percent \
--dimensions Interface=eth0
# アラームの作成
aws cloudwatch put-metric-alarm \
--alarm-name "HighPacketLoss" \
--alarm-description "Alert when packet loss exceeds 1%" \
--metric-name PacketLoss \
--namespace NetworkMonitoring \
--statistic Average \
--period 300 \
--threshold 1.0 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 2
}
13.7 まとめ:ソフトウェア定義ネットワークの威力
仮想ネットワークがもたらした革新
本章で学んだ仮想ネットワーク技術は、以下の革新をもたらしました:
- 即座の構築:数分で企業規模のネットワークを構築
- 完全な隔離:マルチテナント環境での安全な分離
- 柔軟な変更:ダウンタイムなしでネットワーク構成を変更
- グローバル接続:世界中のリソースをシームレスに接続
設計の重要性
仮想だからこそ:
- セキュリティ設計:多層防御の実装
- 可用性設計:マルチAZ、冗長性の確保
- 拡張性設計:将来の成長を見据えた設計
- コスト最適化:必要なリソースのみを使用
次章への展望
これまでの章で、Linux、コンテナ、クラウドの基礎を学んできました。次章では、これらすべてを統合して「監視とログ」について学びます。
システムの可観測性(Observability)をどのように実現し、問題を予防的に発見し、迅速に対処するか。現代のインフラ運用に欠かせない技術を探求していきましょう。
第13章 演習問題
問題1:基本理解の確認
以下の空欄を埋めてください。
-
VPC(Virtual Private Cloud)は、AWS内に作成する論理的に( )されたネットワーク空間で、( )ブロックを指定して作成します。
-
セキュリティグループは( )レベルのファイアウォールで、ネットワークACLは( )レベルのファイアウォールです。
-
NATゲートウェイは、( )サブネット内のインスタンスがインターネットへ( )通信を行うために使用されます。
問題2:概念の理解
次の質問に答えてください。
-
SDN(Software Defined Network)の利点を3つ挙げ、従来の物理ネットワークとの違いを説明してください。
-
VPCにおけるパブリックサブネットとプライベートサブネットの違いと、それぞれの用途を説明してください。
-
Transit GatewayとVPCピアリングの違いと、それぞれの適切な使用場面を説明してください。
問題3:実践的な課題
以下の要件を満たすVPCネットワークを設計してください:
要件:
- 3層アーキテクチャ(Web、App、DB)
- 2つのアベイラビリティゾーンで高可用性
- インターネットからはWeb層のみアクセス可能
- App層とDB層はインターネットへのアウトバウンド通信が可能
- 各層間は必要最小限の通信のみ許可
必要なサブネット、ルートテーブル、セキュリティグループの設定を記述してください。
問題4:セキュリティ設計
次のセキュリティグループルールの問題点を指摘し、改善案を提示してください:
# Webサーバー用セキュリティグループ
Inbound:
- Type: All Traffic, Source: 0.0.0.0/0
- Type: SSH, Source: 0.0.0.0/0
# データベース用セキュリティグループ
Inbound:
- Type: MySQL/Aurora, Source: 0.0.0.0/0
問題5:ネットワークトラブルシューティング
プライベートサブネット内のEC2インスタンスからインターネットへの通信ができません。確認すべき項目を優先順位付きで5つ挙げてください。
問題6:コスト最適化
以下のネットワーク構成のコストを削減する方法を3つ提案してください:
- 各AZに1つずつ、計2つのNATゲートウェイ
- 10個のElastic IP(うち3個は未使用)
- VPCピアリング5本(異なるVPC間)
- 未使用のVPCエンドポイント3つ
問題7:高可用性設計
マルチリージョンでの災害復旧を考慮したネットワーク設計を作成してください。以下の要件を満たすこと:
- プライマリリージョン:東京
- DRリージョン:大阪
- RPO:1時間
- RTO:30分
問題8:発展的課題
-
ハイブリッドクラウドネットワークを設計する際の考慮事項を5つ挙げ、それぞれの解決策を提案してください。
-
VPCフローログを使用した異常検知システムの設計を行ってください。検知すべき異常パターンと、その検知方法を含めて説明してください。