[小ネタ] 既存のタスク定義を取得してFargateを更新しようとしたらCDKのバグを踏んだのでワークアラウンドで解決した

fromFargateTaskDefinitionArn関数が使えなかったので別の方法で解決しました。
2020.06.28

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWS CDK を使って日々楽しく開発をしていたところ、こちらの Issue を踏んだので、Fix されるまでの暫定的な解決方法を色々模索しました。

もっとスマートな解決方法があるかもしれないのですが、一応解決できたので備忘録として残しておこうと思います。

ケースシナリオ

AWS CDK でタスク定義 ARN からタスク定義を取得して、Fargate を更新したい。

Issueの内容

既存のタスク定義の ARN からタスク定義を取得するには、Fargate の場合は@aws-cdk/aws-ecsモジュールのFargateTaskDefinition.fromFargateTaskDefinitionArn()、EC2 の場合はEc2TaskDefinition。fromEc2TaskDefinitionArn()関数を利用しますが、この関数が想定通りに動作しませんでした。

具体的な内容はIssueを参照してください。

ワークアラウンド

AWS CDK を利用してリソースをデプロイする際、CDK のコードは一旦 CloudFormation に書き起こされてデプロイされます。

CDK が CloudFormation に変換されてデプロイされる前のタイミングでCfnService.addPropertyOverride()関数を使って CloudFormation を直接書き換えることで ARN から既存のタスク定義を取得して Fargate を更新する際に指定することができました。

実際のコード

Issue にサンプルコードのGistが貼られていたので参考に実装しました。 SSM からタスク定義の ARN を取得してそれをそのままaddPropertyOverride()に渡して上書いています。

以下では Fargate のタスク定義とバッチ用に作成した Scheduled Task のタスク定義の ARN をそれぞれ更新しています。 addPropertyOverride(propertyPath)に上書きするプロパティのパスを渡すのですが、この部分はcdk synthで CloudFormation を出力してパスを特定しました。

cdk-stack.ts

// Get SSM parameter
const taskDefinitionArn = StringParameter.valueForStringParameter(scope, 'task_definition_arn')
const scheduledTaskDefinitionArn = StringParameter.valueForStringParameter(scope, 'scheduled_task_definition_arn')

const loadBalancedFargateService = new ApplicationLoadBalancedFargateService(scope, 'fargate-alb-service', {
      cluster,
      certificate: certificate,
      domainName,
      domainZone: domainZone,
      taskImageOptions: {
        image: ContainerImage.fromEcrRepository(repository),
        logDriver,
      },
      desiredCount: 2,
    })

// Overwrite Task Definition
const cfnService = loadBalancedFargateService.service.node.tryFindChild('Service') as CfnService
cfnService.addPropertyOverride('TaskDefinition', taskDefinitionArn)

// Scheduled Task
const scheduledTask = new ScheduledFargateTask(scope, 'sample-batch-scheduled-task', {
      schedule: Schedule.cron({ minute: '0/1' }),
      cluster: loadBalancedFargateService.cluster,
      scheduledFargateTaskImageOptions: {
        image: ContainerImage.fromEcrRepository(repository),
        command: ['echo', 'Hello,', 'World!'],
      },
    })

// Overwrite Task Definition for Scheduled Task
const cfnScheduledService = scheduledTask.eventRule.node.tryFindChild('Resource') as CfnService
cfnScheduledService.addPropertyOverride('Targets.0.EcsParameters.TaskDefinitionArn', scheduledTaskDefinitionArn)

最後に

Issue が Fix されたら忘れずにコードを書き換えましょう。

Reference