Open3
ECS に Spring Boot アプリケーションをデプロイする
AWS のアカウントIDをローカルマシンの環境変数にセットしておく
コマンドラインで何回も使うので、勉強用としては環境変数に AWS アカウント ID をセットしておくと楽。
export AWS_ACCOUNT_ID=<your-aws-account-id>
ECR にリポジトリを作る
aws ecr create-repository --repository-name spring-app-repo --region ap-northeast-1
ECR にログインする
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com
イメージを作る
./gradlew bootBuildImage
作成されたイメージの確認
docker images | grep api
イメージにタグを付ける
docker tag api:0.0.1-SNAPSHOT $AWS_ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/spring-app-repo:0.0.1-SNAPSHOT
補足:間違ったときは...
docker rmi $AWS_ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/<repo-name>:0.0.1-SNAPSHOT
イメージを ECR に push する
docker push $AWS_ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/spring-app-repo:0.0.1-SNAPSHOT
aws ecr describe-images --repository-name spring-app-repo --region ap-northeast-1
VPC を作る
VPC を作成
aws ec2 create-vpc --cidr-block 10.0.0.0/16
名前は作成時につけられないので、上のコマンドで出力された vpc-id を指定して tag 付けする
export CURRENT_VPC_ID=<your-id>
aws ec2 create-tags --resources $CURRENT_VPC_ID --tags Key=Name,Value=my-spring-vpc
パブリックサブネットの作成
aws ec2 create-subnet --vpc-id $CURRENT_VPC_ID --cidr-block 10.0.1.0/24 --availability-zone ap-northeast-1a
export CURRENT_PUBLIC_SUBNET_ID=subnet-<your-id>
aws ec2 create-tags --resources $CURRENT_PUBLIC_SUBNET_ID --tags Key=Name,Value=my-spring-public-subnet
TODO 別 az にも。lb で2つ必要
プライベートサブネットの作成
aws ec2 create-subnet --vpc-id $CURRENT_VPC_ID --cidr-block 10.0.2.0/24 --availability-zone ap-northeast-1a
export CURRENT_PRIVATE_SUBNET_ID=subnet-<your-id>
aws ec2 create-tags --resources $CURRENT_PRIVATE_SUBNET_ID --tags Key=Name,Value=my-spring-private-subnet
インターネットゲートウェイの作成とアタッチ
aws ec2 create-internet-gateway
export CURRENT_IGW_ID=igw-<your-id>
aws ec2 create-tags --resources $CURRENT_IGW_ID --tags Key=Name,Value=my-spring-igw
aws ec2 attach-internet-gateway --vpc-id $CURRENT_VPC_ID --internet-gateway-id $CURRENT_IGW_ID
ルートテーブルの作成
aws ec2 create-route-table --vpc-id $CURRENT_VPC_ID
export CURRENT_ROUTE_TABLE_ID=rtb-<your-id>
aws ec2 create-tags --resources $CURRENT_ROUTE_TABLE_ID --tags Key=Name,Value=my-spring-rtb
ルートの作成
aws ec2 create-route --route-table-id $CURRENT_ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --gateway-id $CURRENT_IGW_ID
ルートテーブルをパブリックサブネットに関連付ける
aws ec2 associate-route-table --route-table-id $CURRENT_ROUTE_TABLE_ID --subnet-id $CURRENT_PUBLIC_SUBNET_ID
TODO 別 az の public subnet にも
NAT ゲートウェイの作成
Elastic IP アドレスの作成
aws ec2 allocate-address
export CURRENT_EIP_ALLOC_ID=eipalloc-<your-id>
NAT ゲートウェイの作成
aws ec2 create-nat-gateway --subnet-id $CURRENT_PUBLIC_SUBNET_ID --allocation-id $CURRENT_EIP_ALLOC_ID
export CURRENT_NAT_GW_ID=nat-<your-id>
プライベートサブネットのルートテーブル作成
aws ec2 create-route-table --vpc-id $CURRENT_VPC_ID
export CURRENT_SUBNET_ROUTE_TABLE_ID=rtb-<your-id>
aws ec2 create-tags --resources $CURRENT_SUBNET_ROUTE_TABLE_ID --tags Key=Name,Value=my-spring-private-subnet-rtb
ルートの作成
NAT ゲートウェイのデフォルトルートを追加する
aws ec2 create-route --route-table-id $CURRENT_SUBNET_ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --nat-gateway-id $CURRENT_NAT_GW_ID
ルートテーブルをプライベートサブネットに関連付ける
aws ec2 associate-route-table --route-table-id $CURRENT_SUBNET_ROUTE_TABLE_ID --subnet-id $CURRENT_PRIVATE_SUBNET_ID
ECS クラスターの作成
export CURRENT_ECS_CLUSTER_NAME=my-spring-cluster
aws ecs create-cluster --cluster-name $CURRENT_ECS_CLUSTER_NAME
ロールを作成する
ECS タスクが ECR からイメージを取得できるようにするため。
TODO assume role
trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
aws iam create-role --role-name ecsTaskExecutionRole --assume-role-policy-document file://trust-policy.json
作成したロールに ECR からイメージをプルするためのポリシーをアタッチ
aws iam attach-role-policy --role-name ecsTaskExecutionRole --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
タスク定義の作成
task-definition.json
{
"family": "my-spring-task-definition",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"executionRoleArn": "arn:aws:iam::<your-account-id>:role/ecsTaskExecutionRole",
"cpu": "256",
"memory": "512",
"containerDefinitions": [
{
"name": "<container-name>",
"image": "<aws-account-id>.dkr.ecr.ap-northeast-1.amazonaws.com/spring-app-repo:0.0.1-SNAPSHOT",
"essential": true,
"portMappings": [
{
"containerPort": 8080,
"hostPort": 8080,
"protocol": "tcp"
}
]
}
]
}
aws ecs register-task-definition --cli-input-json file://task-definition.json
ALB 用のセキュリティグループを作成する
後に設定する ECS のセキュリティグループで、source security group に指定したい
aws ec2 create-security-group --group-name my-spring-alb-sg --description "ALB Security Group" --vpc-id $CURRENT_VPC_ID
export CURRENT_ALB_SG_ID=sg-<your-id>
80番ポートへのすべてのアクセスを許可
aws ec2 authorize-security-group-ingress --group-id $CURRENT_ALB_SG_ID --protocol tcp --port 80 --cidr 0.0.0.0/0
ECS のセキュリティグループの作成
aws ec2 create-security-group --group-name my-spring-ecs-sg --description "ECS Service Security Group" --vpc-id $CURRENT_VPC_ID
export CURRENT_ECS_SG_ID=sg-<your-id>
インバウンドルールを追加(ALB からポート8080への通信のみ許可)
aws ec2 authorize-security-group-ingress --group-id $CURRENT_ECS_SG_ID --protocol tcp --port 8080 --source-group $CURRENT_ALB_SG_ID
ALB のターゲットグループを作成
aws elbv2 create-target-group \
--name my-spring-alb-tg \
--protocol HTTP \
--port 8080 \
--vpc-id $CURRENT_VPC_ID \
--target-type ip
export CURRENT_ALB_TG_ECS_ARN=<your-arn>
ALB を作成
aws elbv2 create-load-balancer \
--name my-spring-lb \
--subnets $CURRENT_PUBLIC_SUBNET_ID $CURRENT_PUBLIC_SUBNET_ID_AZ2 \
--security-groups $CURRENT_ALB_SG_ID
export CURRENT_LB_ARN=<your-arn>
ALB のリスナーを設定
aws elbv2 create-listener \
--load-balancer-arn $CURRENT_LB_ARN \
--protocol HTTP \
--port 80 \
--default-actions Type=forward,TargetGroupArn=$CURRENT_ALB_TG_ECS_ARN
ECS サービスの作成
export CURRENT_ECS_SERVICE_NAME=my-spring-service
aws ecs create-service \
--cluster $CURRENT_ECS_CLUSTER_NAME \
--service-name my-spring-service \
--task-definition my-spring-task-definition \
--desired-count 3 \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[$CURRENT_PRIVATE_SUBNET_ID],securityGroups=[$CURRENT_ECS_SG_ID],assignPublicIp=DISABLED}" \
--load-balancers "targetGroupArn=$CURRENT_ALB_TG_ECS_ARN,containerName=my-spring-container,containerPort=8080"
サービスの状態確認
aws ecs describe-services --cluster $CURRENT_ECS_CLUSTER_NAME --services $CURRENT_ECS_SERVICE_NAME