AWS CDKを使ってFargateからAWSのリソースにつなげる設定をする
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