streampack の Tana です。
ECS(Fargate) 環境を手動セットアップするには、画面からぽちぽちすればある程度できるものの、
ALB を作成したり、Service, Task Definition などを設定するのが複雑です。
また、コンセプトを理解するのにも時間がかかります。
Dynamic Port Mapping を使う場合は、Security Group に inbound を登録しないといけなかったり、トライ&エラーの繰り返しです。
構築だけで疲れちゃいます。
そこで、AWS Cloud Template Kit(CDK) を使えば、20行ぐらいのコードと数回のコマンド実行で
下記のリソースと共にベストプラクティスなECS(Fargate)環境を構築してくれる方法です。
ネットワーク
- VPC
- Subnets
- Internet Gateway
- NAT gateway(EIP)
- Route Tables
- Security Group
ECS(Fargate)
- ALB(Target Group, Security Group込み)
- Cluster
- Service
- Task Definition(Container)
CDK の installや初期手順などはこちらで記載あるので割愛します。
https://github.com/awslabs/aws-cdk#getting-started
cdk init で作成されたテンプレートを元に、下記が実際に書いたコードです。
Dockerhub を使って例は他にもあるので、今回は ECR を使用します。
import cdk = require('@aws-cdk/cdk');
import ecs = require("@aws-cdk/aws-ecs");
import ec2 = require("@aws-cdk/aws-ec2");
import ecr = require("@aws-cdk/aws-ecr");
export class DemoStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// ------------- ここを記載 --------------
// ベストプラクティスなネットワーク環境の構築
const vpc = new ec2.VpcNetwork(this, 'MyCdkVpc', {maxAZs: 2});
const cluster = new ecs.Cluster(this, 'Cluster', {vpc});
// ECSクラスタ設定(t2.medium指定)
cluster.addDefaultAutoScalingGroupCapacity({instanceType: new ec2.InstanceType("t2.medium"), instanceCount: 1});
// ECRを使用
const repository = new ecr.Repository(this, 'myRepoName');
// ECS(ALB/Service/Task Defintion/Container) 関連をまとめて構築
new ecs.LoadBalancedEc2Service(this, 'Service', {
cluster,
memoryLimitMiB: 512,
image: ecs.ContainerImage.fromEcrRepository(repository),
containerPort: 8080, // コンテナポート番号
environment: {
ENV: 'production'
}
});
// ------------- ここまで --------------
}
}
synth で typescript 書いたコードから CloudFormation Template(Yaml)で事前確認できます。
CloudFormationの400行ぐらいのコードを書く必要が無くなります。
$ cdk synth
$ cdk deploy
deploy は IAM Policy や Security Group のプレビューが表示され、AWSアカウントに構築開始されます。
ECRを使う場合はレポジトリまで作成してくれますが、アプリケーションの Docker Image を push してあげる必要があります。
よって、作成されたレポジトリを取得し、Image を push します。
# リポジトリ名を取得
$ aws ecr describe-repositories | jq -r '.repositories[].repositoryName'
----
demos-demoa-xxxxxx
下記のようなコマンド(shell)を実行して build&push します。
ECRID=xxxxxxxxx
ECRNAME=demos-demoa-xxxxxx
# build an your docker app
docker build -t ${ECRNAME} .
docker tag ${ECRNAME}:latest ${ECRID}.dkr.ecr.ap-northeast-1.amazonaws.com/${ECRNAME}:latest
# push
$(aws ecr get-login --no-include-email --region ap-northeast-1)
docker push ${ECRID}.dkr.ecr.ap-northeast-1.amazonaws.com/${ECRNAME}:latest
成功すると、ALBのURLが払い出されますので、アクセスして確認し、結果が返ってくれば完了です!
結果が正しく表示されなければ、Cluster の EventのログやTaskをAWSコンソールや ecs-cli などを使って再度確認します。
ecs-cli ps --cluster DemoStack-Clusterxxxx-xxxxx
たいてい、container port が正しくなかったり、環境変数、ECRリポジトリに登録されているかなどを確認します。
削除したい場合は、destory を実行します。(事前に ECRに登録した Image の削除の必要あり)
$ cdk destory
CDKデメリットとしては細かな指定や調整したい場合は、別途それぞれコードを書く必要がありそうです。
例えば、
- コスト削減のためにも NAT Gateway(EIP) を省きたい
- コンテナの log driver や ulimits を設定したい
下記はコンテナに log driver などを追加する場合です。
const demoContainer = demoTaskDefinition.addContainer('demo-container', {
image: ecs.ContainerImage.fromEcrRepository(repository),
logging: new ecs.AwsLogDriver(this, 'demo-logging', { streamPrefix: 'demo-app' })
});
demoContainer.addUlimits(
{
name : ecs.UlimitName.Fsize,
hardLimit : 10240000,
softLimit : 10240000
}
)
細かな引数の指定や props の指定は CDK doc にてブラウザにてドキュメントを開いてくれて、検索・確認できます。
$ cdk docs
まだ、プレビューで今後改善さらに改善されそうですが、ECS(Fargate) 環境を頻繁に作ってはテストして削除するケースには最適です。
CDK workshop もあるようなので、一度見て試してみるとイメージが湧くかと思います。
https://cdkworkshop.com/