--- title: Cloud Native Buildpacks Tutorial - 8.6. ┗ Cloud Native BuildpacksでビルドしたOCIイメージをAWS Fargateへデプロイ tags: ["Cloud Native Buildpacks Tutorial", "Cloud Native Buildpacks", "Spring Boot", "AWS Fargate", "Series"] categories: ["Dev", "Infrastructure", "CloudNativeBuildpacks", "AWSFargate"] date: 2020-04-29T07:13:17Z updated: 2020-05-11T09:06:12Z --- Cloud Native BuildpacksでビルドしたOCIイメージ([`making/hello-cnb`](https://hub.docker.com/r/making/hello-cnb))を[AWS Fargate](https://aws.amazon.com/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 < 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 ``` 次のコマンドでアプリケーションをデプロイします。 ```yaml 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](https://github.com/cloudfoundry/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 < 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 ``` 次のコマンドでアプリケーションを更新します。 ```yaml 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 ```