こんにちは、ちゃりおです。
最近AWS CDKのAmazon ECS拡張機能(ecs-service-extensions)を使ってみたのですが、簡単にApp Meshを使ったECSの構成を作れて便利でした。
ECS拡張機能について紹介します。
Amazon ECS 拡張機能とは
コンテナ化されたサービスに AWS App Mesh や FireLens などの追加機能を自動的に追加する拡張機能をサポートします。
App MeshやFirelens,X-RAYなどをECSにシンプルに追加することができます。
AWS CDK の Amazon ECS 拡張機能が一般提供開始
ECS拡張機能を使ってApp Meshを有効化したFargateを作ってみる
L2,L3で作る場合
App Meshを作成するには、タスク定義に以下のような記述を追加する必要があります。(envoyサイドカー・proxy設定の追加など)
AWS Fargate 用ユーザーガイド
タスク定義の例
{
"family": "appmesh-gateway",
"proxyConfiguration":{
"type": "APPMESH",
"containerName": "envoy",
"properties": [
{
"name": "IgnoredUID",
"value": "1337"
},
{
"name": "ProxyIngressPort",
"value": "15000"
},
{
"name": "ProxyEgressPort",
"value": "15001"
},
{
"name": "AppPorts",
"value": "9080"
},
{
"name": "EgressIgnoredIPs",
"value": "169.254.170.2,169.254.169.254"
}
]
},
"containerDefinitions": [
{
"name": "app",
"image": "application_image",
"portMappings": [
{
"containerPort": 9080,
"hostPort": 9080,
"protocol": "tcp"
}
],
"essential": true,
"dependsOn": [
{
"containerName": "envoy",
"condition": "HEALTHY"
}
]
},
{
"name": "envoy",
"image": "840364872350.dkr.ecr.region-code.amazonaws.com/aws-appmesh-envoy:v1.15.1.0-prod",
"essential": true,
"environment": [
{
"name": "APPMESH_VIRTUAL_NODE_NAME",
"value": "mesh/meshName/virtualNode/virtualNodeName"
},
{
"name": "ENVOY_LOG_LEVEL",
"value": "info"
}
],
"healthCheck": {
"command": [
"CMD-SHELL",
"echo hello"
],
"interval": 5,
"timeout": 2,
"retries": 3
}
}
],
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"networkMode": "awsvpc"
}
CDKでタスク定義を書けばできますが、なかなか面倒です。
他にも仮想ノード・仮想サービス・仮想ルーター・サービスディスカバリの定義などやる必要があります。
ecs-patternsを参考にして、独自でAppMesh用のクラスを作る方法もあると思います。
もっと楽な方法はないかと探していたらECS拡張機能が良さそうでした。
ECS拡張機能
サンプルです。
ECSサービス、App Meshに必要なリソース及びタスク定義など作成してくれます。
「environment」にVPCを渡してVPC内で作成することも可能です。
import * as cdk from "@aws-cdk/core"
import * as appmesh from "@aws-cdk/aws-appmesh"
import * as ecs from "@aws-cdk/aws-ecs";
import * as ec2 from "@aws-cdk/aws-ec2";
import { AppMeshExtension, Container, Environment, HttpLoadBalancerExtension, CloudwatchAgentExtension, Service, ServiceDescription } from '@aws-cdk-containers/ecs-service-extensions';
export class EcsExtensionsTest extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const vpc = ec2.Vpc.fromLookup(this, "vpc", {
vpcId: "vpc-XXXXX"
})
const cluster = new ecs.Cluster(this, "cluster", {
vpc: vpc,
clusterName: "ecs-extensiton-cluster"
})
const environment = new Environment(this, 'inspection', { vpc, cluster })
const mesh = new appmesh.Mesh(this, 'my-mesh')
const webFrontendDescription = new ServiceDescription()
webFrontendDescription.add(new Container({
cpu: 1024,
memoryMiB: 2048,
trafficPort: 80,
image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"),
}))
webFrontendDescription.add(new AppMeshExtension({ mesh }))
webFrontendDescription.add(new HttpLoadBalancerExtension())
webFrontendDescription.add(new CloudwatchAgentExtension())
const webService = new Service(this, 'web', {
environment: environment,
serviceDescription: webFrontendDescription,
})
}
}
実際に実行してみると、AppMeshが有効化されたECSサービスが作成されました。
ALBのエンドポイントにcurlしてみると、envoyを経由しているのがわかりました。
$ curl -v hogehoge.ap-northeast-1.elb.amazonaws.com
* Trying 54.95.244.187...
* TCP_NODELAY set
* Connected to ecs-e-weblo-1119EFIE5VQMS-347300674.ap-northeast-1.elb.amazonaws.com (54.95.244.187) port 80 (#0)
> GET / HTTP/1.1
> Host: ecs-e-weblo-1119EFIE5VQMS-347300674.ap-northeast-1.elb.amazonaws.com
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Mon, 14 Jun 2021 08:02:32 GMT
< Content-Type: text/html; charset=UTF-8
< Content-Length: 941
< Connection: keep-alive
< server: envoy
< x-powered-by: PHP/5.4.16
< x-envoy-upstream-service-time: 0
まとめ
ECS拡張機能を使ってみました。
App Meshなど記述が長くなってしまいがちですが、こちらの機能を使うことでかなりシンプルに書くことができます。


