CloudFormation で構築済みの VPC に S3 Express One Zone 用の Gateway 型の VPC エンドポイントを追加する機会がありました。CloudFormation で構築するテンプレートのサンプルを紹介します。
S3 Express One Zone とは
re:Invent 2023 において、Amazon S3 の新機能として、低レイテンシとハイパフォーマンスを実現する新しいストレージクラスが発表されました。このストレージクラスは、特に S3 におけるデータアクセスの速度を重視するユースケースに適しています。詳細については下記のブログをご覧ください。
S3 Express One Zone の VPC エンドポイントは別
通常の S3 用の VPC エンドポイントとは異なる VPC エンドポイントが別途必要になります。S3 Express One Zone のディレクトリバケットへの通信を VPC エンドポイント経由するには S3 Express One Zone 用の VPC エンドポイントも必要です。
検討背景
今回はゲノム解析のワークロードで Mountpoint for Amazon S3 を利用して、インプットファイルを S3 に保存しています。シーケンシャルなリードアクセスは良しとして、リード時にランダムアクセスが走るものは相性が悪かったです。
ランダムなデータアクセスリクエストを行うファイルベースのアプリケーションを S3 Standard と比較して最大で 6 倍高速化できます。 Mountpoint for Amazon S3 が S3 Express One Zone ストレージクラスのサポートを開始
そこで S3 Express One Zone で実用的な速度で運用可能か試す準備として EC2 から S3 Express One Zone の通信経路を VPC エンドポイント経由にして経路を最適化します。なにより EC2 と S3 間の通信コストがかからなくなるのは大きいです。
VPC エンドポイントを作成するテンプレート
CloudFormation で S3 Express One Zone 用の VPC エンドポイント Gateway 型を作成するには以下の様に記述します。
# S3 Express Gateway Type
GatewayS3ExpressEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
RouteTableIds: # ルートテーブルに紐づけが必要
- !Ref PublicRouteTable1
- !Ref PrivateRouteTable1
- !Ref IsolatedRouteTable1
ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3express" # ここを S3 Expreess 指定する
VpcEndpointType: Gateway
VpcId: !Ref VPC # VPC の ID を指定
下記は通常の S3 用の VPC エンドポイント Gateway 型の記述です。差分はServiceName:
の箇所だけです。
# S3 Gateway Type
GatewayS3Endpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
RouteTableIds:
- !Ref PublicRouteTable1
- !Ref PrivateRouteTable1
- !Ref IsolatedRouteTable1
ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3" # ここが S3 指定になってる違いがある
VpcEndpointType: Gateway
VpcId: !Ref VPC
VPC 作成テンプレート全文
3 AZ 構成の VPC に S3 と S3 Exreppss One Zone の 2 つ Gateway 型の VPC エンドポイントをアタッチした構成 + α のサンプルテンプレートを参考までに記載します。
折りたたみ
---
AWSTemplateFormatVersion: "2010-09-09"
Description: 3AZ Network 3 layers and VPC Endpoint with switching single Nat Gateway
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: NAT Gateway Setting
Parameters:
- EnableNatGateway
Parameters:
EnableNatGateway:
Description: Enable NAT Gateway
Type: String
Default: false
AllowedValues: [true, false]
Mappings:
Constant:
EnvName:
ProjectName: hpc
Environment: dev
Network:
Cidrs:
VPCCidr: 10.0.0.0/16
PublicSubnetCidr1: 10.0.1.0/24
PublicSubnetCidr2: 10.0.2.0/24
PublicSubnetCidr3: 10.0.3.0/24
PrivateSubnetCidr1: 10.0.17.0/24
PrivateSubnetCidr2: 10.0.18.0/24
PrivateSubnetCidr3: 10.0.19.0/24
IsolatedSubnetCidr1: 10.0.33.0/24
IsolatedSubnetCidr2: 10.0.34.0/24
IsolatedSubnetCidr3: 10.0.35.0/24
Conditions:
EnableNatGateway: !Equals [true, !Ref EnableNatGateway]
Resources:
# ----------------------------------------------------------------------------------------
# VPC
# ----------------------------------------------------------------------------------------
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !FindInMap [ Network, Cidrs, VPCCidr]
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub
- "${ProjectName}-${Environment}-vpc"
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
- Key: Environment
Value: !FindInMap [ Constant, EnvName, Environment]
# ----------------------------------------------------------------------------------------
# Internet Gateway
# ----------------------------------------------------------------------------------------
# Create InternetGateway & VPC Attach
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-igw
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
- Key: Environment
Value: !FindInMap [ Constant, EnvName, Environment]
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
# ----------------------------------------------------------------------------------------
# NAT Gateway
# ----------------------------------------------------------------------------------------
# Create NatGateway
NatGateway1:
Type: AWS::EC2::NatGateway
Condition: EnableNatGateway
Properties:
AllocationId: !GetAtt NatGatewayEIP1.AllocationId
SubnetId: !Ref PublicSubnet1
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-natgw1
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
- Key: Environment
Value: !FindInMap [ Constant, EnvName, Environment]
NatGatewayEIP1:
Type: AWS::EC2::EIP
Condition: EnableNatGateway
Properties:
Domain: vpc
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-natgw-eip1
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
- Key: Environment
Value: !FindInMap [ Constant, EnvName, Environment]
# ----------------------------------------------------------------------------------------
# Route Table
# ----------------------------------------------------------------------------------------
# Create Public RouteTable & Setting Routing
PublicRouteTable1:
Type: AWS::EC2::RouteTable
DependsOn: AttachGateway
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-public-rtb1
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
- Key: Environment
Value: !FindInMap [ Constant, EnvName, Environment]
PublicRoute1:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref PublicRouteTable1
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
# Create Private RouteTable & Setting Routing
PrivateRouteTable1:
Type: AWS::EC2::RouteTable
DependsOn: AttachGateway
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-private-rtb1
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
- Key: Environment
Value: !FindInMap [ Constant, EnvName, Environment]
PrivateRouteNatGW1:
Type: AWS::EC2::Route
Condition: EnableNatGateway
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref PrivateRouteTable1
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway1
# Create Isolated RouteTable & Setting Routing
IsolatedRouteTable1:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-isolated-rtb1
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
- Key: Environment
Value: !FindInMap [ Constant, EnvName, Environment]
# ----------------------------------------------------------------------------------------
# Public Subnet
# ----------------------------------------------------------------------------------------
# Public 1
PublicSubnet1:
Type: AWS::EC2::Subnet
DependsOn: AttachGateway
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [0, !GetAZs ""]
CidrBlock: !FindInMap [ Network, Cidrs, PublicSubnetCidr1]
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-public-subnet1
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
- Key: Environment
Value: !FindInMap [ Constant, EnvName, Environment]
PublicSubnetRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable1
# Public 2
PublicSubnet2:
Type: AWS::EC2::Subnet
DependsOn: AttachGateway
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [1, !GetAZs ""]
CidrBlock: !FindInMap [ Network, Cidrs, PublicSubnetCidr2]
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-public-subnet2
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
- Key: Environment
Value: !FindInMap [ Constant, EnvName, Environment]
PublicSubnetRouteTableAssociation2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicRouteTable1
# Public 3
PublicSubnet3:
Type: AWS::EC2::Subnet
DependsOn: AttachGateway
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [2, !GetAZs ""]
CidrBlock: !FindInMap [ Network, Cidrs, PublicSubnetCidr3]
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-public-subnet3
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
- Key: Environment
Value: !FindInMap [ Constant, EnvName, Environment]
PublicSubnetRouteTableAssociation3:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet3
RouteTableId: !Ref PublicRouteTable1
# ----------------------------------------------------------------------------------------
# Private Subnet
# ----------------------------------------------------------------------------------------
# Private 1
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [0, !GetAZs ""]
CidrBlock: !FindInMap [ Network, Cidrs, PrivateSubnetCidr1]
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-private-subnet1
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
PrivateSubnetRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
RouteTableId: !Ref PrivateRouteTable1
# Private 2
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [1, !GetAZs ""]
CidrBlock: !FindInMap [ Network, Cidrs, PrivateSubnetCidr2]
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-private-subnet2
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
PrivateSubnetRouteTableAssociation2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet2
RouteTableId: !Ref PrivateRouteTable1
# Private 3
PrivateSubnet3:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [2, !GetAZs ""]
CidrBlock: !FindInMap [ Network, Cidrs, PrivateSubnetCidr3]
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-private-subnet3
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
PrivateSubnetRouteTableAssociation3:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet3
RouteTableId: !Ref PrivateRouteTable1
# ----------------------------------------------------------------------------------------
# Isolated Subnet
# ----------------------------------------------------------------------------------------
# Isolated 1
IsolatedSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [0, !GetAZs ""]
CidrBlock: !FindInMap [ Network, Cidrs, IsolatedSubnetCidr1]
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-isolated-subnet1
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
- Key: Environment
Value: !FindInMap [ Constant, EnvName, Environment]
IsolatedSubnetRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref IsolatedSubnet1
RouteTableId: !Ref IsolatedRouteTable1
# Isolated 2
IsolatedSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [1, !GetAZs ""]
CidrBlock: !FindInMap [ Network, Cidrs, IsolatedSubnetCidr2]
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-isolated-subnet2
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
- Key: Environment
Value: !FindInMap [ Constant, EnvName, Environment]
IsolatedSubnetRouteTableAssociation2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref IsolatedSubnet2
RouteTableId: !Ref IsolatedRouteTable1
# Isolated 3
IsolatedSubnet3:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [2, !GetAZs ""]
CidrBlock: !FindInMap [ Network, Cidrs, IsolatedSubnetCidr3]
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-isolated-subnet3
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
- Key: Environment
Value: !FindInMap [ Constant, EnvName, Environment]
IsolatedSubnetRouteTableAssociation3:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref IsolatedSubnet3
RouteTableId: !Ref IsolatedRouteTable1
# ----------------------------------------------------------------------------------------
# Network ACL
# ----------------------------------------------------------------------------------------
# Public NACL
PublicNetworkACL1:
Type: AWS::EC2::NetworkAcl
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-public-nacl1
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
NetworkACLEntryPublicIngress1:
Type: AWS::EC2::NetworkAclEntry
Properties:
CidrBlock: "0.0.0.0/0"
Egress: false
NetworkAclId: !Ref PublicNetworkACL1
Protocol: -1
RuleAction: "allow"
RuleNumber: 100
NetworkACLEntryPublicEgress1:
Type: "AWS::EC2::NetworkAclEntry"
Properties:
CidrBlock: "0.0.0.0/0"
Egress: true
NetworkAclId: !Ref PublicNetworkACL1
Protocol: -1
RuleAction: "allow"
RuleNumber: 100
# Private NACL
PrivateNetworkACL1:
Type: AWS::EC2::NetworkAcl
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-private-nacl1
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
NetworkACLEntryPrivateIngress1:
Type: AWS::EC2::NetworkAclEntry
Properties:
CidrBlock: "0.0.0.0/0"
Egress: false
NetworkAclId: !Ref PrivateNetworkACL1
Protocol: -1
RuleAction: "allow"
RuleNumber: 100
NetworkACLEntryPrivateEgress1:
Type: "AWS::EC2::NetworkAclEntry"
Properties:
CidrBlock: "0.0.0.0/0"
Egress: true
NetworkAclId: !Ref PrivateNetworkACL1
Protocol: -1
RuleAction: "allow"
RuleNumber: 100
# Isolated NACL
IsolatedNetworkACL1:
Type: AWS::EC2::NetworkAcl
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub
- ${ProjectName}-${Environment}-isolated-nacl1
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
NetworkACLEntryIsolatedIngress1:
Type: AWS::EC2::NetworkAclEntry
Properties:
CidrBlock: "0.0.0.0/0"
Egress: false
NetworkAclId: !Ref IsolatedNetworkACL1
Protocol: -1
RuleAction: "allow"
RuleNumber: 100
NetworkACLEntryIsolatedEgress1:
Type: "AWS::EC2::NetworkAclEntry"
Properties:
CidrBlock: "0.0.0.0/0"
Egress: true
NetworkAclId: !Ref IsolatedNetworkACL1
Protocol: -1
RuleAction: "allow"
RuleNumber: 100
# NetworkACL Association
PublicNetworkACLAssocation1:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PublicSubnet1
NetworkAclId: !Ref PublicNetworkACL1
PublicNetworkACLAssocation2:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PublicSubnet2
NetworkAclId: !Ref PublicNetworkACL1
PublicNetworkACLAssocation3:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PublicSubnet3
NetworkAclId: !Ref PublicNetworkACL1
PrivateNetworkACLAssocation1:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
NetworkAclId: !Ref PrivateNetworkACL1
PrivateNetworkACLAssocation2:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PrivateSubnet2
NetworkAclId: !Ref PrivateNetworkACL1
PrivateNetworkACLAssocation3:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PrivateSubnet3
NetworkAclId: !Ref PrivateNetworkACL1
IsolatedNetworkACLAssocation1:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref IsolatedSubnet1
NetworkAclId: !Ref IsolatedNetworkACL1
IsolatedNetworkACLAssocation2:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref IsolatedSubnet2
NetworkAclId: !Ref IsolatedNetworkACL1
IsolatedNetworkACLAssocation3:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref IsolatedSubnet3
NetworkAclId: !Ref IsolatedNetworkACL1
# ----------------------------------------------------------------------------------------
# VPC Endpoints
# ----------------------------------------------------------------------------------------
# S3 Gateway Type
GatewayS3Endpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
RouteTableIds:
- !Ref PublicRouteTable1
- !Ref PrivateRouteTable1
- !Ref IsolatedRouteTable1
ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3"
VpcEndpointType: Gateway
VpcId: !Ref VPC
# S3 Express Gateway Type
GatewayS3ExpressEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
RouteTableIds:
- !Ref PublicRouteTable1
- !Ref PrivateRouteTable1
- !Ref IsolatedRouteTable1
ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3express"
VpcEndpointType: Gateway
VpcId: !Ref VPC
# ------------------------------------------------------------#
# S3 Bucket for VPC Flow Logs
# ------------------------------------------------------------#
S3Bucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
BucketName: !Sub
- ${ProjectName}-${Environment}-vpc-flowlogs-${AWS::AccountId}
- ProjectName: !FindInMap [ Constant, EnvName, ProjectName]
Environment: !FindInMap [ Constant, EnvName, Environment]
OwnershipControls:
Rules:
- ObjectOwnership: "BucketOwnerEnforced"
PublicAccessBlockConfiguration:
BlockPublicAcls: True
BlockPublicPolicy: True
IgnorePublicAcls: True
RestrictPublicBuckets: True
VersioningConfiguration:
Status: Enabled
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: "AES256"
BucketKeyEnabled: false
LifecycleConfiguration:
Rules:
- Id: AbortIncompleteMultipartUpload
AbortIncompleteMultipartUpload:
DaysAfterInitiation: 7
Status: "Enabled"
- Id: CurrentVersionExpiration
ExpirationInDays: 365
Status: "Enabled"
- Id: NoncurrentVersionExpiration
NoncurrentVersionExpiration:
NoncurrentDays: 7
Status: "Enabled"
# ------------------------------------------------------------#
# VPC Flow Logs
# ------------------------------------------------------------#
VPCFlowLogs:
Type: "AWS::EC2::FlowLog"
Properties:
LogDestinationType: s3
LogDestination: !GetAtt S3Bucket.Arn
ResourceType: "VPC"
ResourceId: !Ref VPC
TrafficType: ALL
DestinationOptions:
{
"FileFormat": "plain-text",
"HiveCompatiblePartitions": false,
"PerHourPartition": true,
}
# ----------------------------------------------------------------------------------------
# Exports
# ----------------------------------------------------------------------------------------
Outputs:
ExportVPC:
Value: !Ref VPC
Export:
Name: !Sub ${AWS::StackName}-VPC
ExportPublicSubnet1:
Value: !Ref PublicSubnet1
Export:
Name: !Sub ${AWS::StackName}-PublicSubnet1
ExportPublicSubnet2:
Value: !Ref PublicSubnet2
Export:
Name: !Sub ${AWS::StackName}-PublicSubnet2
ExportPublicSubnet3:
Value: !Ref PublicSubnet3
Export:
Name: !Sub ${AWS::StackName}-PublicSubnet3
ExportPublicRoutetable1:
Value: !Ref PublicRouteTable1
Export:
Name: !Sub ${AWS::StackName}-PublicRouteTable1
ExportPrivateSubnet1:
Value: !Ref PrivateSubnet1
Export:
Name: !Sub ${AWS::StackName}-PrivateSubnet1
ExportPrivateSubnet2:
Value: !Ref PrivateSubnet2
Export:
Name: !Sub ${AWS::StackName}-PrivateSubnet2
ExportPrivateSubnet3:
Value: !Ref PrivateSubnet3
Export:
Name: !Sub ${AWS::StackName}-PrivateSubnet3
ExportPrivateRoutetable1:
Value: !Ref PrivateRouteTable1
Export:
Name: !Sub ${AWS::StackName}-PrivateRouteTable1
ExportIsolatedSubnet1:
Value: !Ref IsolatedSubnet1
Export:
Name: !Sub ${AWS::StackName}-IsolatedSubnet1
ExportIsolatedSubnet2:
Value: !Ref IsolatedSubnet2
Export:
Name: !Sub ${AWS::StackName}-IsolatedSubnet2
ExportIsolatedSubnet3:
Value: !Ref IsolatedSubnet2
Export:
Name: !Sub ${AWS::StackName}-IsolatedSubnet3
ExportIsolatedRoutetable1:
Value: !Ref IsolatedRouteTable1
Export:
Name: !Sub ${AWS::StackName}-IsolatedRouteTable1
S3 Express One Zone の IAM ポリシー
EC2 から S3 Express One Zone のディレクトリバケットへアクセスするには新たな IAM ポリシーが必要になります。詳細は以下のブログを参照ください。
おわりに
S3 Express One Zone は通常の S3 の VPC エンドポイントを別であること、S3 Express One Zone 用の VPC エンドポイントの作成 CloudFormation テンプレートの例をお客様へご案内したかったです。ですが、ちょうど良いサンプルがなかったので作成しました。最近は CloudFormation 以外で IaC のコードを書くことが多いような気もしますが、CloudFormation ユーザーの方々の参考になれば幸いです。