業務でLambdaの実行時間に引っかかる処理を切り分けるためにLambda->ECSTask実行を行いました。
ServerlessFlameWorkを使用したNode.js/TypeScript環境でECSのTaskを実行する手順です。
Python3&boto3を使用した記事はこちらです。
環境
Node v14.7.0
"typescript": "^4.1.3"
"serverless": "^2.23.0",
"serverless-esbuild": "^1.17.1",
結論
import { ECSClient, RunTaskCommand, RunTaskCommandInput } from '@aws-sdk/client-ecs';
const client = new ECSClient({
region: 'ap-northeast-1',
});
const { TASK_DEFINITION, CLUSTER, SUBNETS, SECURITY_GROUP } = process.env;
const runTask = async () => {
const input: RunTaskCommandInput = {
cluster: CLUSTER,
taskDefinition: TASK_DEFINITION,
launchType: 'FARGATE',
networkConfiguration: {
awsvpcConfiguration: {
subnets: SUBNETS.split(','),
securityGroups: SECURITY_GROUP.split(','),
assignPublicIp: 'DISABLED',
},
},
overrides: {
containerOverrides: [
{
name: 'app',
command: ['npm', 'start'],
},
],
},
count: 1,
};
const command = new RunTaskCommand(input);
await client.send(command);
};
export { runTask };
provider:
iamManagedPolicies:
- arn:aws:iam::aws:policy/AmazonECS_FullAccess
解説
ハマりポイントはIAMRoleとRunTaskCommandInputでした。
IAMRole
下記でいけるかなと思いましたが、AccessDeniedされました。
provider:
iam:
role:
statements:
- Effect: Allow
Action:
- ecs:RunTask
Resource:
- '*'
期待しているRoleも含まれてしまうので、FullAccess系は使用したくないのですが、一旦これで行います。
必要なActionが分かり次第、更新します。
RunTaskCommandInput
公式を見ると、TaskDefinitionだけ必須っぽいのですが、他のプロパティも必要です。
最初に記載したプロパティを指定して動きました。
ecsTask側のnetworkmodeが"aws-vpc"でなければ、networkConfigurationは必要ではないかもです。
const { TASK_DEFINITION, CLUSTER, SUBNETS, SECURITY_GROUP } = process.env;
const input: RunTaskCommandInput = {
cluster: CLUSTER,
taskDefinition: TASK_DEFINITION,
launchType: 'FARGATE',
networkConfiguration: {
awsvpcConfiguration: {
subnets: SUBNETS.split(','),
securityGroups: SECURITY_GROUP.split(','),
assignPublicIp: 'DISABLED',
},
},
overrides: {
containerOverrides: [
{
name: 'app',
command: ['npm', 'start'],
},
],
},
count: 1,
};
const input = {
subnets: SUBNETS.split(','),
securityGroups: SECURITY_GROUP.split(','),
}
上記は環境変数(string)を配列に変更しています。
自分はServerlessFlameWorkでの環境変数の設定にこちらのclassmethodさんの記事を参考にしています。
あとはoverrides.containerOverrides
のname
は必須です。
あとがき
ここまで読んでいただきありがとうございます。
疑問点等あれば、質問していただければ答えます!
最近見た映画の主題歌がマカロニえんぴつだったからか、またハマり出しました。
好きな音楽を聞きながらコードを書くのが好きな今日この頃です。
ノリノリでコード書いているので周りはちょっと引いているみたいですが。。笑