インフラ

CDK ecs-service-extensionsを使用してお手軽にAppMeshを有効化したECSサービスを作成する

cdk

こんにちは、ちゃりおです。

最近AWS CDKのAmazon ECS拡張機能(ecs-service-extensions)を使ってみたのですが、簡単にApp Meshを使ったECSの構成を作れて便利でした。
ECS拡張機能について紹介します。

Contents

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など記述が長くなってしまいがちですが、こちらの機能を使うことでかなりシンプルに書くことができます。

Amzonで「AWS」の本を見てみる

楽天で「AWS」の本をみてみる!!

cdk
CDKでNATGatewayのEIPをOutput・Prefixlistに登録するこんにちは、ちゃりおです。 CDKで作成したVPCのNAT GatewayのEIPを他のスタックで使ったり、プレフィックスリストに登録...
ssm
Systems Managerステートマネージャーで定期実行をやってみるこんにちは、ちゃりおです。 cronで各サーバのスクリプトを実行しているのですが、他にいい方法がないかと思いステートマネージャー使って...
ECR
CDKで作成したECRをスタック削除時に同時に削除されるようにするこんにちは、ちゃりおです。 デフォルトではCDKでECRを作成して、「cdk destroy」で削除したときにECRのリポジトリが残り...