AWS 環境構築 MBC CQRS サーバーレス フレームワーク用ネットワーク環境の準備
AWSにてMBC CQRS サーバーレス フレームワークを稼働させる環境の準備を行います。
MBC CQRS サーバーレス フレームワーク で稼働させる環境を用意する上で事前に準備したおきたいサービスは以下の通りです。
- Route 53
- ドメイン名をAWSのCDKで設定出来ると環境構築・切替が楽なので必ず利用したいサービスです。(任意ですが推奨します。)
- ドメイン取得はRoute 53で行う必要はありませんが、NSレコードをRoute 53に向ける必要があります。
- ACM
- SSL証明書の更新処理を行うのは運用上の手間がかかるため、Route 53と共に必ず利用したいサービスです。
- VPC
- リージョン内にPublicネットワークとPrivateネットワークを作成し守りたいデータはPrivateネットワークからアクセスできるようにする
ドメイン名をAWSのCDKで設定出来ると環境構築・切替が楽なので必ず利用したい
Route 53の設定
ドメイン名は config
に登録するのが良いため、 config/type.ts
に zoneName
を追加します。追加後のソースは以下の通りです。
export type Env = 'dev' | 'stg' | 'prod'
export type Config = {
env: Env,
zoneName: string,
}
config/dev/index.ts
に zoneName
を追加します。
import { Config } from '../type'
const config: Config = {
env: 'dev',
zoneName: 'xxxxx.example.com',
}
export default config
続いて Stackにホストゾーン設定を追加します。追加後の lib/mbc-base-infra-stack.ts
のソースは以下の通りです。
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { Config } from '../config'
export interface MbcBaseInfraStackProps extends cdk.StackProps {
config: Config
}
export class MbcBaseInfraStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: MbcBaseInfraStackProps) {
super(scope, id, props);
const config = props?.config
if (config) {
// Route 53の設定
const hostedZone = new cdk.aws_route53.HostedZone(this, 'HostedZone', {
zoneName: config.zoneName
})
}
}
}
ホストゾーンを作成するためSSO Profileのログインを実行します。(IAM をProfileに設定している場合は不要)
aws sso login --profile profile_name
次のコマンドでCDK をデプロイします。
cdk deploy --profile profile_name
実行が完了するとCloudFormation画面では以下のように表示されます。
Route53のホストゾーン設定を参照すると以下のような表示を確認出来ます。
ドメイン名のNSレコードをRoute53で表示されているネームサーバーに変更します。
例えば お名前.com であれば「ネームサーバー設定」-「ネームサーバー設定」より以下のように行います。
※ ネームサーバーの切替が完了するまでしばらく時間がかかります。
ACMの設定
SSL証明書の管理をACMにて行いたいと思います。
普段使用するリージョンは ap-northeast-1
(東京) ですが、グローバルで使用するケースもありますので us-east-1
(バージニア北部)についても作成します。
まずは、通常使用するリージョン分(ap-northeast-1
)のみACMを作成しましょう。
lib/mbc-base-infra-stack.ts
のRoute53の次の行に以下のように追加します。
// ACMの設定
const acm = new cdk.aws_certificatemanager.Certificate(this, 'acm', {
domainName: config.zoneName,
subjectAlternativeNames: [`*.${config.zoneName}`],
validation: CertificateValidation.fromDns(hostedZone),
})
上記追加し、cdk deploy --profile profile_name
を実行後にAWS Certificate Manager (ACM)のコンソール画面を見るとSSL証明書が発行されたことを確認出来ます。
VPCの設定
VPCはPublicサブネットとPrivateサブネットを作成します。Publicサブネットにはインターネットゲートウェイを接続し、PriateサブネットにはNATゲートウェイを設置します。
本来であれば、3つのAZを作成しそれぞれにInternet gateway → Publicサブネット→NAT Gateway→Private Subnetを作成すべきです。
ただし、NAT gateway は稼働時間に応じて課金となるため、使用頻度がそれほど高くないサーバーレス構成では3台分のNAT gateway の固定費用が相対的に高くなってしまう傾向があります。
その場合はNAT gawayを1つのAZのみ作成し共有することが出来ます。(これはベストプラクティスではないです。サービスが軌道に乗りミッションクリティカルになったらそれぞれのAZ毎にNATGatewayを作成するようにしましょう。)
ちなみにサブネットのIPアドレスは何でも構いませんが、弊社では10台〜90台はPublicサブネット、110台〜190台はPrivateサブネットにしています。
仮に 172.23.0.0 のVPCを作成した場合は以下のようなサブネットを割り当てます。
- Publicサブネット: 172.23.0.10/24(1a), 172.23.0.20/24(1c), 172.23.0.30/24(1d)
- Privateサブネット: 172.23.0.110/24(1a), 172.23.0.120/24(1c), 172.23.0.130/24(1d)
config/constant.ts
に以下を追加します。
// Vpc のIPアドレス
export const VpcAddress = '172.23.0.0/16'
// サブネットのIPアドレスリスト
export const VpcCIDRs = {
vpc: '172.23.0.0/16',
subnets: [
{public: '172.23.11.0/24', private: '172.23.111.0/24', availabilityZone: 'ap-northeast-1a'},
{public: '172.23.12.0/24', private: '172.23.112.0/24', availabilityZone: 'ap-northeast-1c'},
{public: '172.23.13.0/24', private: '172.23.113.0/24', availabilityZone: 'ap-northeast-1d'},
],
lib/mbc-base-infra-stack.ts
のACMの次の行に以下のように追加します。
// VPC を作成
const vpc = new cdk.aws_ec2.Vpc(this, 'Vpc-Network', {
ipAddresses: cdk.aws_ec2.IpAddresses.cidr(VpcAddress),
vpcName: 'Vpc-Network',
natGateways: 0,
subnetConfiguration: [],
})
// Public Subnet を作成
const publicSubnets = VpcCIDRs.subnets.map((subnet, index) => new cdk.aws_ec2.Subnet(this, `Vpc-Network-Public-${index + 1}`, {
vpcId: vpc.vpcId,
cidrBlock: subnet.public,
availabilityZone: subnet.availabilityZone,
mapPublicIpOnLaunch: false,
}))
// Private Subnet を作成
const privateSubnets = VpcCIDRs.subnets.map((subnet, index) => new cdk.aws_ec2.Subnet(this, `Vpc-Network-Private-${index + 1}`, {
vpcId: vpc.vpcId,
cidrBlock: subnet.private,
availabilityZone: subnet.availabilityZone,
mapPublicIpOnLaunch: false,
}))
// Internet Gateway を作成
const igw = new cdk.aws_ec2.CfnInternetGateway(this, 'Vpc-Network-IGW', {
tags: [{key: 'Name', value: 'Vpc-Network-IGW'}]
})
const igwAttach = new cdk.aws_ec2.CfnVPCGatewayAttachment(this, 'Vpc-Network-IGW-Attach', {
vpcId: vpc.vpcId,
internetGatewayId: igw.ref
})
// Public RouteTables を作成
const publicRouteTables = VpcCIDRs.subnets.map((subnet, index) => new cdk.aws_ec2.CfnRouteTable(this, `Vpc-Network-Public-Route-${index + 1}`, {
vpcId: vpc.vpcId
}))
// Private RouteTables を作成
const privateRouteTables = VpcCIDRs.subnets.map((subnet, index) => new cdk.aws_ec2.CfnRouteTable(this, `Vpc-Network-Private-Route-${index + 1}`, {
vpcId: vpc.vpcId
}))
// Subnet の紐付け
VpcCIDRs.subnets.map((_, index) => {
// Public Subnet に Route Tableを紐付ける
new cdk.aws_ec2.CfnSubnetRouteTableAssociation(this, `Vpc-Network-Public-Subnet-Association-${index + 1}`, {
routeTableId: publicRouteTables[index].ref,
subnetId: publicSubnets[index].subnetId,
})
// Private Subnet に Route Tableを紐付ける
new cdk.aws_ec2.CfnSubnetRouteTableAssociation(this, `Vpc-Network-Private-Subnet-Association-${index + 1}`, {
routeTableId: privateRouteTables[index].ref,
subnetId: privateSubnets[index].subnetId,
})
// デフォルト RouteはInternetに紐付ける
new cdk.aws_ec2.CfnRoute(this, `Vpc-Network-PublicRouteToIGW-${index + 1}`, {
routeTableId: publicRouteTables[index].ref,
destinationCidrBlock: '0.0.0.0/0',
gatewayId: igw.ref,
})
})
// 1サブネットに NAT Gatewayを作成する。 IPアドレスをnat.example.com で Route53に登録する
const eip = new cdk.aws_ec2.CfnEIP(this, 'Vpc-Network-EIP', {
tags: [{key: 'Name', value: `nat.${config.zoneName}`}],
})
const natGateway = new cdk.aws_ec2.CfnNatGateway(this, 'Vpc-Network-Nat-Gateway', {
allocationId: eip.attrAllocationId,
subnetId: publicSubnets[0].subnetId,
tags: [{key: 'Name', value: `Vpc-Network-Nat-Gateway`}],
})
VpcCIDRs.subnets.map((_, index) => {
new cdk.aws_ec2.CfnRoute(this, `Vpc-Route-to-Nat-Gateway-${index + 1}`, {
routeTableId: privateRouteTables[index].ref,
destinationCidrBlock: '0.0.0.0/0',
natGatewayId: natGateway.ref,
})
})
// セキュリティグループ設定
const securityGroup = new cdk.aws_ec2.SecurityGroup(this, `Vpc-Security-Group`, {
description: 'Security Group',
securityGroupName: `Vpc-Security-Group`,
vpc: vpc,
})
上記追加し、cdk deploy --profile profile_name
を実行後にVPCのリソースマップを見るとVPC、サブネット、NATゲートウェイ、インターネットゲートウェイ、ルートテーブルを確認する事が出来ます。