📦

AWS CDKを使ってFargateからAWSのリソースにつなげる設定をする

2022/08/15に公開

AWS CDKを最近使い始め、それでFargateを使ったアプリケーションを構築してました。

そして、DynamoDBをつなごうと思って普通にアクセスキーを用意して環境変数に入れようと考えたのですが、いろいろ調べているとFargateでもLambdaのようにIAMロールを設定すればアクセスキーを用意しなくても簡単に接続できることがわかりました。

しかもCDKを使えばそのロールの設定をコードで定義できるので、AWSのマネジメントコンソールで操作する必要がなくなります。

というわけで、今回はCDKを使ってFargateからAWSのリソースにつなげる方法をDynamoDBを例に紹介します。

なお使うCDKは2系(2.37.1)です。

Fargateのタスク

まずは、今回使用するFargateのタスク定義です。 aws-cdk-lib/aws-ecs-patternsはECSでよく使われる複数のAWSのリソースをパターン化したものです。

以下の数行だけでALBとそれに紐付けるFargateのサービスとタスク定義が簡単に作成されるので超便利です。

import { ApplicationLoadBalancedFargateService } from 'aws-cdk-lib/aws-ecs-patterns';

export class CdkTestStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // ECS Fargate Task
    const fargate = new ApplicationLoadBalancedFargateService(this, 'Fargate', {
      cluster: cluster,
      cpu: 256,
      desiredCount: 1,
      publicLoadBalancer: false,
      assignPublicIp: true,
      taskImageOptions: {
        image: ContainerImage.fromAsset('./src'),
        enableLogging: true,
        logDriver: LogDriver.awsLogs({
          streamPrefix: 'task-log',
          logRetention: RetentionDays.ONE_DAY,
        }),
      },
      memoryLimitMiB: 512,
    });
  }
}

DynamoDBの設定

続いて、DynamoDBのリソースを作成します。

これはテーブル名とパーティションキーを指定しているだけなので至ってシンプルですね。

import { Table, BillingMode, AttributeType } from 'aws-cdk-lib/aws-dynamodb';

export class CdkTestStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    // 中略
    // DynamoDB Table
    const dynamoTable = new Table(this, 'DynamoTable', {
      tableName: 'UserInfo',
      partitionKey: {name:'user_id', type: AttributeType.STRING},
      billingMode: BillingMode.PAY_PER_REQUEST,
      removalPolicy: RemovalPolicy.DESTROY
    });
  }
}

IAMロールの設定

最後にFargateタスクからDynamoDBにアクセスするためのIAMロールを作成します。

設定するのはDynamoDBでCRUDするために最低限必要なロールです。

import { Effect, PolicyStatement } from 'aws-cdk-lib/aws-iam';

export class CdkTestStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    // 中略
    // Attach DynamoDB policy to Fargate Task
    fargate.taskDefinition.addToTaskRolePolicy(
      new PolicyStatement({
        effect: Effect.ALLOW,
        actions: [
          'dynamodb:BatchWriteItem',
          'dynamodb:PutItem',
          'dynamodb:DeleteItem',
          'dynamodb:DescribeTable',
          'dynamodb:GetItem',
          'dynamodb:UpdateItem',
        ],
        resources: [`${dynamoTable.tableArn}`],
      })
    );
  }
}

Fargateに設定するポリシーには2種類あり、タスクロールとタスク実行ロールです。

タスクロールは、簡単に言うとコンテナで使用するロールです。

一方でタスク実行ロールはタスクを実行するときに使用するロールです。例えばコンテナから出力されるログをCloudWatchLogsで出力させたり、コンテナイメージをECRからPullするときに使われるロールです。

今回はコンテナからDynamoDBに接続するためのロールを設定するため前者で設定をします。

そのタスクロールは、fargate.taskDefinition.addToTaskRolePolicyを使ってロールを設定するだけです(今回のポイント!)。

これでコンテナにアクセスキーを含めなくてもタスクロールを設定すれば簡単に安全にAWSのリソースにアクセスできるようになります。

割と小ネタ的な話でしたが、これだけでもCDKとFargateを使いこなせる気がしました。

Discussion