#1.CloudFormation で環境を準備する#
入力する箇所は、次のとおりで他の内容はデフォルトとする。
キー | バリュー |
---|---|
スタックの名前 | 任意 |
MasterUserName | 任意(後でDBで使う。) |
MasterUserPassword | 任意(後でDBで使う) |
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "VPC Template For Multi-AZ",
"Parameters": {
"MasterUserName": {
"Description": "RDS master user name",
"Type": "String"
},
"MasterUserPassword": {
"Description": "RDS master user password",
"Type": "String"
}
},
"Resources": {
"VPC": {
"Type" : "AWS::EC2::VPC",
"Properties" : {
"CidrBlock" : "10.0.0.0/16",
"InstanceTenancy" : "default",
"EnableDnsSupport" : "true",
"EnableDnsHostnames" : "false",
"Tags" : [ { "Key": "Name", "Value": "SimplechatVPC" } ]
}
},
"eip": {
"Type" : "AWS::EC2::EIP",
"Properties" : { "Domain" : "vpc" }
},
"subnetPub1": {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"CidrBlock" : "10.0.0.0/24",
"AvailabilityZone" : { "Fn::Select" : [ "0", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]},
"VpcId" : { "Ref": "VPC" },
"Tags" : [ { "Key": "Name", "Value": "Public-Subnet-1" } ]
}
},
"subnetPub2": {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"CidrBlock" : "10.0.1.0/24",
"AvailabilityZone" : { "Fn::Select" : [ "1", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]},
"VpcId" : { "Ref": "VPC" },
"Tags" : [ { "Key": "Name", "Value": "Public-Subnet-2" } ]
}
},
"subnetPrv1": {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"CidrBlock" : "10.0.2.0/24",
"AvailabilityZone" : { "Fn::Select" : [ "0", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]},
"VpcId" : { "Ref": "VPC" },
"Tags" : [ { "Key": "Name", "Value": "Private-Subnet-1" } ]
}
},
"subnetPrv2": {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"CidrBlock" : "10.0.3.0/24",
"AvailabilityZone" : { "Fn::Select" : [ "1", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]},
"VpcId" : { "Ref": "VPC" },
"Tags" : [ { "Key": "Name", "Value": "Private-Subnet-2" } ]
}
},
"Nat": {
"Type" : "AWS::EC2::NatGateway",
"Properties" : {
"AllocationId" : { "Fn::GetAtt" : ["eip", "AllocationId"] },
"SubnetId" : { "Ref" : "subnetPub1" }
},
"DependsOn" : "eip"
},
"IGW": {
"Type" : "AWS::EC2::InternetGateway",
"Properties" : {
"Tags" : [ { "Key": "Name", "Value": "Simplechat-IG" } ]
}
},
"RouteTablePublic": {
"Type" : "AWS::EC2::RouteTable",
"Properties" : {
"VpcId" : { "Ref": "VPC" },
"Tags" : [ { "Key": "Name", "Value": "Public-RT" } ]
}
},
"RouteTablePrivate": {
"Type" : "AWS::EC2::RouteTable",
"Properties" : {
"VpcId" : { "Ref": "VPC" },
"Tags" : [ { "Key": "Name", "Value": "Private-RT" } ]
}
},
"gw": {
"Type" : "AWS::EC2::VPCGatewayAttachment",
"Properties" : {
"VpcId" : { "Ref": "VPC" },
"InternetGatewayId" : { "Ref": "IGW" }
}
},
"subnetRoutePub1": {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"RouteTableId" : { "Ref": "RouteTablePublic" },
"SubnetId" : { "Ref": "subnetPub1" }
}
},
"subnetRoutePub2": {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"RouteTableId" : { "Ref": "RouteTablePublic" },
"SubnetId" : { "Ref": "subnetPub2" }
}
},
"subnetRoutePrv1": {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"RouteTableId" : { "Ref": "RouteTablePrivate" },
"SubnetId" : { "Ref": "subnetPrv1" }
}
},
"subnetRoutePrv2": {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"RouteTableId" : { "Ref": "RouteTablePrivate" },
"SubnetId" : { "Ref": "subnetPrv2" }
}
},
"routePublic": {
"Type" : "AWS::EC2::Route",
"Properties" : {
"DestinationCidrBlock" : "0.0.0.0/0",
"RouteTableId" : { "Ref": "RouteTablePublic" },
"GatewayId" : { "Ref": "IGW" }
},
"DependsOn" : "gw"
},
"routePrivate": {
"Type" : "AWS::EC2::Route",
"Properties" : {
"DestinationCidrBlock" : "0.0.0.0/0",
"RouteTableId" : { "Ref": "RouteTablePrivate" },
"NatGatewayId" : { "Ref" : "Nat" }
},
"DependsOn" : [ "Nat" , "subnetRoutePrv1", "subnetRoutePrv2" ]
},
"LoadBalancerSecurityGroup": {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription": "simplechat_lb_sg",
"GroupName" : "simplechat_lb_sg",
"VpcId": { "Ref" : "VPC" },
"SecurityGroupIngress" : [
{ "IpProtocol" : "tcp",
"FromPort" : "80",
"ToPort" : "80",
"CidrIp" : "0.0.0.0/0" }
]
}
},
"WebServerSecurityGroup": {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription": "simplechat_web_sg",
"GroupName" : "simplechat_web_sg",
"VpcId": { "Ref" : "VPC" },
"SecurityGroupIngress" : [
{ "IpProtocol" : "tcp",
"FromPort" : "80",
"ToPort" : "80",
"SourceSecurityGroupId" : { "Ref" : "LoadBalancerSecurityGroup" } }
]
}
},
"RDSSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "simplechat_db_sg",
"GroupName" : "simplechat_db_sg",
"VpcId" : { "Ref" : "VPC" },
"SecurityGroupIngress" : [
{ "IpProtocol" : "tcp",
"FromPort" : "3306",
"ToPort" : "3306",
"SourceSecurityGroupId" : { "Ref" : "WebServerSecurityGroup" } }
]
}
},
"DbSubnetGroup": {
"Type": "AWS::RDS::DBSubnetGroup",
"Properties": {
"DBSubnetGroupName": "simplechat_db_subnet",
"DBSubnetGroupDescription": "simplechat_db_subnet",
"SubnetIds": [ {"Ref": "subnetPrv1"}, {"Ref": "subnetPrv2"} ]
}
},
"DBParameterGroup": {
"Type": "AWS::RDS::DBParameterGroup",
"Properties": {
"Description": "simplechat parameter group",
"Family": "mysql5.7",
"Parameters": {
"character_set_client": "utf8mb4",
"character_set_connection": "utf8mb4",
"character_set_database": "utf8mb4",
"character_set_results": "utf8mb4",
"character_set_server": "utf8mb4",
"collation_connection": "utf8mb4_bin",
"collation_server": "utf8mb4_bin"
}
}
},
"DbInstance": {
"Type": "AWS::RDS::DBInstance",
"Properties": {
"DBInstanceIdentifier": "simplechat-ecs-db",
"Engine": "MySQL",
"EngineVersion": "5.7.22",
"AllocatedStorage": "5",
"MasterUsername": { "Ref": "MasterUserName" },
"MasterUserPassword": { "Ref": "MasterUserPassword" },
"DBInstanceClass": "db.t2.micro",
"DBSubnetGroupName": { "Ref": "DbSubnetGroup" },
"DBParameterGroupName": { "Ref": "DBParameterGroup" },
"VPCSecurityGroups": [ { "Ref": "RDSSecurityGroup"} ]
}
},
"ALB" : {
"Type" : "AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties" : {
"LoadBalancerAttributes" : [
{ "Key" : "access_logs.s3.enabled", "Value" : "false" },
{ "Key" : "deletion_protection.enabled", "Value" : "false" },
{ "Key" : "idle_timeout.timeout_seconds", "Value" : "60" }
],
"Name" : "simplechat-alb",
"Scheme" : "internet-facing",
"SecurityGroups" : [
{ "Ref": "LoadBalancerSecurityGroup" }
],
"Subnets" : [ {"Ref": "subnetPub1"}, {"Ref": "subnetPub2"} ],
"Tags" : [
{"Key": "Name", "Value": "simplechat-alb" }
]
}
},
"Cloud9Env": {
"Type": "AWS::Cloud9::EnvironmentEC2",
"Properties": {
"Name": "simplechat_cloud9_env",
"Description": "simplechat_cloud9_env",
"AutomaticStopTimeMinutes": "1440",
"InstanceType": "t2.micro",
"SubnetId": { "Ref": "subnetPub1" }
}
}
}
}
#2.Dockerイメージを登録する#
##2-1.Amazon ECR にリポジトリを作成する##
適当なリポジトリ名で、リポジトリを作成する。(設定はデフォルト)
##2-2.Amazon ECR にDockerイメージを登録する##
【「1.CloudFormation で環境を準備する#」】で、cloud9でsimplechat_cloud9_env が作成されているので、「Open IDE」を選択し、次のとおりappを展開する。
wget https://ecs-for-aws-summit-online.workshop.aws/simplechat_app.tar.gz
tar zxvf simplechat_app.tar.gz
cd simplechat_ecs_app/
Amazon ECRから「プッシュコマンドの表示」をクリックし、後は手順どおり、ログイン→ビルド→タグ付け→プッシュする。
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin .dkr.ecr.us-east-1.amazonaws.com
docker build -t simplechat .
docker tag simplechat:latest .dkr.ecr.us-east-1.amazonaws.com/simplechat:latest
docker push .dkr.ecr.us-east-1.amazonaws.com/simplechat:latest
#3.Dockerコンテナの作成#
##3-1.クラスターの作成##
「AWS Fargate」を指定。(他の設定はデフォルト)
##3-2.タスク定義##
イメージは先程作成したAmazon ECRのリポジトリのURIを指定する。ポートマッピングは80にする。
環境変数を設定する。
キー | バリュー |
---|---|
DB_HOST | RDSインスタンスのURI |
DB_USER | 【1.CloudFormation で環境を準備する】で指定したもの |
DB_PASS | 【1.CloudFormation で環境を準備する】で指定したもの |
##3-3.サービス##
デプロイメントはローリングアップデート
#4.アプリケーションの確認と修正#
ALBのDNS名にアクセスして、アプリケーションを色々触ってみる。
そのあと、Cloud9を開き、アプリケーションの適当な箇所を修正し、「File」から「Save」。その内容が反映されるか確認する。
【2-2.Amazon ECR にDockerイメージを登録する】の手順と同様にログイン→ビルド→タグ付け→プッシュする。
※実際はAmazon ECRのリポジトリにおいて「タグのイミュータビリティ」を「有効にする」に設定し、イメージ更新毎に一意のタグを付けるようにする。
※「タグのイミュータビリティ」→ 有効にすると同じタグを上書きができなくなる。
今回は、ECSのサービスで「新しいデプロイの強制」のチェックボックスをオンにだけ変更し、更新する。
タスクは2つになるはずですがしばらくすると、1つになります。(ローリングアップデート)
最後にalbのDNSにアクセスし、変更が反映されたか確認する。