Cloud Native BuildpacksでビルドしたOCIイメージ(making/hello-cnb)をAWS Fargateにデプロイします。
目次
CLIのインストール
brew install awscli
brew install amazon-ecs-cli
IAM ロールの作成
export AWS_ACCESS_KEY_ID=****
export AWS_SECRET_ACCESS_KEY=****
cat <<'EOF' > task-execution-assume-role.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
aws iam --region ap-northeast-1 create-role --role-name ecsTaskExecutionRole --assume-role-policy-document file://task-execution-assume-role.json
aws iam --region ap-northeast-1 attach-role-policy --role-name ecsTaskExecutionRole --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
ECSクラスタの作成
ecs-cli configure \
--cluster hello-cnb \
--config-name hello-cnb \
--default-launch-type FARGATE \
--region ap-northeast-1
ecs-cli up
INFO[0001] Created cluster cluster=hello-cnb region=ap-northeast-1
INFO[0001] Waiting for your cluster resources to be created...
INFO[0002] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
INFO[0062] Cloudformation stack status stackStatus=CREATE_IN_PROGRESS
VPC created: vpc-0c917aa72745f9cb6
Subnet created: subnet-0530ccfcfe68c28ef
Subnet created: subnet-0f153ee20359f90ef
Cluster creation succeeded.
出力結果に含まれるVPC IDと二つのSubnet IDを次のように変数に設定します。
export VPC_ID=vpc-0c917aa72745f9cb6
export SUBNET_ID_1=subnet-0530ccfcfe68c28ef
export SUBNET_ID_2=subnet-0f153ee20359f90ef
デフォルトのセキュリティグループルールを追加し、8080ポートでインバウンドアクセスを許可します。
export SECURITY_GROUP_ID=$(aws ec2 describe-security-groups \
--filters Name=vpc-id,Values=${VPC_ID} \
--region ap-northeast-1 | \
jq -r ".SecurityGroups[0].GroupId")
aws ec2 authorize-security-group-ingress --group-id ${SECURITY_GROUP_ID} \
--protocol tcp \
--port 8080 \
--cidr 0.0.0.0/0 \
--region ap-northeast-1
アプリケーションのデプロイ
次のコマンドでdocker-compose.ymlを作成します。
mkdir deploy-to-fargate
cd deploy-to-fargate
cat <<'EOF' > docker-compose.yml
version: '2'
services:
hello-cnb:
ports:
- 8080:8080
mem_limit: 768m
image: making/hello-cnb:latest
environment:
INFO_MESSAGE: Hello World!
logging:
driver: awslogs
options:
awslogs-group: hello-cnb
awslogs-region: ap-northeast-1
awslogs-stream-prefix: web
EOF
次のコマンドでecs-params.ymlを作成します。
cat <<EOF > ecs-params.yml
version: 1
task_definition:
task_execution_role: ecsTaskExecutionRole
ecs_network_mode: awsvpc
task_size:
mem_limit: 1024
cpu_limit: 256
run_params:
network_configuration:
awsvpc_configuration:
subnets:
- ${SUBNET_ID_1}
- ${SUBNET_ID_2}
security_groups:
- ${SECURITY_GROUP_ID}
assign_public_ip: ENABLED
EOF
次のコマンドでアプリケーションをデプロイします。
ecs-cli compose \
--project-name hello-cnb \
--file docker-compose.yml \
--ecs-params ecs-params.yml \
service up \
--create-log-groups
次のようなログが出力されます。
INFO[0000] Using ECS task definition TaskDefinition="hello-cnb:1"
INFO[0000] Created Log Group hello-cnb in ap-northeast-1
INFO[0016] (service hello-cnb) has started 1 tasks: (task 90947d26-027a-4ea2-bd30-44231bf90c06). timestamp="2020-04-29 06:24:01 +0000 UTC"
INFO[0046] Service status desiredCount=1 runningCount=1 serviceName=hello-cnb
INFO[0046] (service hello-cnb) has reached a steady state. timestamp="2020-04-29 06:24:41 +0000 UTC"
INFO[0046] ECS Service has reached a stable state desiredCount=1 runningCount=1 serviceName=hello-cnb
INFO[0046] Created an ECS service service=hello-cnb taskDefinition="hello-cnb:1"
次のコマンドでTaskのログを確認します。
TASK_ID=$(ecs-cli compose --project-name hello-cnb --cluster hello-cnb service ps | grep hello-cnb | awk -F '/' '{print $1}')
ecs-cli logs --task-id ${TASK_ID}
次のようなログが出力されます。
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -XX:MaxMetaspaceSize=88833K -XX:ReservedCodeCacheSize=240M -Xss1M -Xmx185598K (Head Room: 0%, Loaded Class Count: 13270, Thread Count: 250, Total Memory: 805306368)
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.6.RELEASE)
2020-04-29 06:24:49.000 INFO 1 --- [ main] hello.HelloCnbApplication : Starting HelloCnbApplication on ip-10-0-0-105.ap-northeast-1.compute.internal with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace)
2020-04-29 06:24:49.096 INFO 1 --- [ main] hello.HelloCnbApplication : No active profile set, falling back to default profiles: default
2020-04-29 06:25:02.797 INFO 1 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 3 endpoint(s) beneath base path '/actuator'
2020-04-29 06:25:08.108 INFO 1 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2020-04-29 06:25:08.197 INFO 1 --- [ main] hello.HelloCnbApplication : Started HelloCnbApplication in 24.7 seconds (JVM running for 28.791)
指定したコンテナのメモリに合わせて、JVMのメモリが自動で設定されていることに注目してください。
Public IPを変数に設定します。
PUBLIC_IP=$(ecs-cli compose --project-name hello-cnb --cluster hello-cnb service ps | grep hello-cnb | awk '{print $3}' | awk -F ':' '{print $1}')
アプリケーションにアクセスします。
$ curl http://${PUBLIC_IP}:8080/actuator/health -w '\n'
{"status":"UP"}
$ curl http://${PUBLIC_IP}:8080/actuator/info -w '\n'
{"message":"Hello World!"}
メモリの調整
Buildpackに含まれるJava Buildpack Memory Calculatorの機能を使って、
自動設定されるJVMのメモリを調整し、少ないメモリ量(256MiB)で起動できるようにします。
次のコマンドでmanifestをアップデートします。
cat <<'EOF' > docker-compose.yml
version: '2'
services:
hello-cnb:
ports:
- 8080:8080
mem_limit: 256m # <--
image: making/hello-cnb:latest
environment:
INFO_MESSAGE: Hello World!
JAVA_OPTS: "-XX:ReservedCodeCacheSize=32M -Xss512k" # <--
BPL_JVM_THREAD_COUNT: "20" # <--
BPL_JVM_HEAD_ROOM: "5" # <--
logging:
driver: awslogs
options:
awslogs-group: hello-cnb
awslogs-region: ap-northeast-1
awslogs-stream-prefix: web
EOF
cat <<EOF > ecs-params.yml
version: 1
task_definition:
task_execution_role: ecsTaskExecutionRole
ecs_network_mode: awsvpc
task_size:
mem_limit: 512 # <--
cpu_limit: 256
run_params:
network_configuration:
awsvpc_configuration:
subnets:
- ${SUBNET_ID_1}
- ${SUBNET_ID_2}
security_groups:
- ${SECURITY_GROUP_ID}
assign_public_ip: ENABLED
EOF
次のコマンドでアプリケーションを更新します。
ecs-cli compose \
--project-name hello-cnb \
--file docker-compose.yml \
--ecs-params ecs-params.yml \
service up
次のコマンドでTaskのログを確認します。
TASK_ID=$(ecs-cli compose --project-name hello-cnb --cluster hello-cnb service ps | grep hello-cnb | awk -F '/' '{print $1}')
ecs-cli logs --task-id ${TASK_ID}
メモリの設定が次のように出力されていることを確認してください。
Calculated JVM Memory Configuration: (Head Room: 5%, Loaded Class Count: 13270, Thread Count: 25, Total Memory: 268435456)
アプリケーションの削除
次のコマンドでアプリを削除します。
ecs-cli compose --project-name hello-cnb service down
aws logs delete-log-group --log-group-name hello-cnb --region ap-northeast-1
ecs-cli down --force