Lamdaからboto3でFargateのコンテナを起動する際の手順です。
ググると簡単にできそうなのですが、私はなぜか盛大にハマってかなり時間がかかったので注意点を記載します。
serverless.ymlの設定
まず、IAMでECSアクセスのポリシーを付与します。
provider:
iamManagedPolicies: # Optional IAM Managed Policies, which allows to include the policies into IAM Role
- arn:aws:iam::aws:policy/AmazonECS_FullAccess
なお、上記のポリシーが付与されていないと以下のようなエラーが出力されます。
翻訳すると「実行が許可されていません。」ということらしいです。
An error occurred (AccessDeniedException) when calling the PutRule operation: User: arn:aws:sts::999999999999:assumed-role/demo-service-lambda-dev-ap-northeast-1-lambdaRole/demo-service-lambda-dev-fargate is not authorized to perform: events:PutRule on resource: arn:aws:events:ap-northeast-1:999999999999:rule/fargate-run
呼び出し側のlambdaの設定
ecs = boto3.client('ecs')
response = ecs.run_task(
cluster='selenium',
taskDefinition='fargate-shell',
launchType='FARGATE',
overrides={
'containerOverrides': [
{
'name': 'far',
'command': ["./test.sh",
"aaa"],
'memory': 64
}
]
}
)
当初こんな感じでLambdaを起動したところ、以下のようなエラーが出ました。
翻訳すると「networkMode 'awsvpc' が指定されている場合は、ネットワーク設定を提供する必要があります。」
An error occurred (InvalidParameterException) when calling the RunTask operation: Network Configuration must be provided when networkMode 'awsvpc' is specified.
そこで思い出したのが、ecs-cliでFargateを起動した時のパラメータファイルです。
version: 1
task_definition:
ecs_network_mode: awsvpc
task_execution_role: ecsTaskExecutionRole
task_size:
cpu_limit: 256
mem_limit: 512
services:
fargate:
secrets:
- value_from: AAA
name: TOKEN
run_params:
network_configuration:
awsvpc_configuration:
subnets:
- subnet-12345678901234567
- subnet-12345678901234568
security_groups:
- sg-12345678901234567
assign_public_ip: ENABLED
ecs-cliでは、問題なく呼び出せたのでserverless.ymlにawsvpcの設定を追加しました。
ここが大ハマリする分かれ目でした。。
provider:
iamManagedPolicies: # Optional IAM Managed Policies, which allows to include the policies into IAM Role
- arn:aws:iam::aws:policy/AmazonECS_FullAccess
〜〜〜〜〜省略〜〜〜〜
functions:
hello:
handler: handler.hello
### ↓追加 ###
vpc:
securityGroupIds:
- sg-12345678901234567
subnetIds:
- subnet-12345678901234567
- subnet-12345678901234568
### ↑追加 ###
events:
- http:
path: /test
method: post
さっきのエラーは解消した!!!
実行してみると、「networkMode 'awsvpc' が指定されている場合は、ネットワーク設定を提供する必要があります。」のエラーは解消していました。
ただ、timeoutoのエラーが発生しています。
2020-06-09T11:19:13.298Z ec5e6182-10f7-494a-b781-f108a3789387 Task timed out after 6.01 seconds
まずやったのは、lambdaのtimeoutの設定変更です。Fargateの起動が1分弱くらいなので、それが関係ある??とりあえず余裕をみて120秒を設定。
functions:
hello:
handler: handler.hello
### ↓追加 ###
timeout: 120
### ↑追加 ###
vpc:
securityGroupIds:
- sg-12345678901234567
subnetIds:
- subnet-12345678901234567
- subnet-12345678901234568
events:
- http:
path: /test
method: post
当初APIGatewayからLambdaを起動していましたが、APIGatewayは30秒でtimeoutしてしまうので、S3から起動するように修正。
〜〜〜省略〜〜〜
functions:
hello:
handler: handler.hello
timeout: 120
vpc:
securityGroupIds:
- sg-12345678901234567
subnetIds:
- subnet-12345678901234567
- subnet-12345678901234568
events:
- http:
path: /test
method: post
### ↓追加 ###
- s3:
bucket: "s3test-fargate"
event: s3:ObjectCreated:*
rules:
- prefix: test/
existing: true
### ↑追加 ###
S3をトリガにしてLambdaを実行してみたが120秒でtimeout・・。
2020-06-09T11:31:12.118Z 0e01d9c6-1b62-4a5e-9fd2-c1ae84f80b98 Task timed out after 120.01 seconds
Lambdaの設定も追加してみる
ecs = boto3.client('ecs')
response = ecs.run_task(
cluster='selenium',
taskDefinition='fargate-shell',
launchType='FARGATE',
################# 追加 #################
networkConfiguration={
'awsvpcConfiguration': {
'subnets': [
'subnet-12345678901234567',
'subnet-12345678901234568'
],
'securityGroups': [
'sg-12345678901234567'
],
'assignPublicIp': 'ENABLED'
}
},
################# 追加 #################
overrides={
'containerOverrides': [
{
'name': 'far',
'command': ["./test.sh",
"aaa"],
'memory': 64
}
]
}
)
boto3のecsにnetworkConfiguration
の設定項目があったので、lambdaの設定と全く同じ内容で追加してみました。そして再度実行しましたが、、やはりtimeout。
あとは↓こんなことをやってみましたが、常にtimeoutで進展なし。。
・セキュリティグループIDとVPCIDを間違えていたので修正。
・timeoutを5分まで延長
・LambdaにAdministratorAccessのポリシーを割り当てる
・セキュリティグループのインバウント、アウトバウンドの設定を全て開放する
結論
serverless.ymlでLambda関数にvpcの設定を入れていたことがtimeoutの原因だったようです。
この設定を外すとうまく行きました。
なぜ、ダメなのかはっきりとは理解できていませんが、みなさん気をつけてください。。
〜〜〜省略〜〜〜
functions:
hello:
handler: handler.hello
timeout: 120
###### この設定が原因だった ######
# vpc:
# securityGroupIds:
# - sg-12345678901234567
# subnetIds:
# - subnet-12345678901234567
# - subnet-12345678901234568
events:
- http:
path: /test
method: post
- s3:
bucket: "s3test-fargate"
event: s3:ObjectCreated:*
rules:
- prefix: test/
existing: true