Aws-cdk: efsVolumeConfiguration is unsupported in ecs.CfnTaskDefinition

Created on 21 Mar 2020  路  7Comments  路  Source: aws/aws-cdk

I'm trying to use the newish EFS mounts in an EC2 ECS cluster and the resources are refusing to include the extra parameters even if I try to use the raw resources.

https://aws.amazon.com/about-aws/whats-new/2020/01/amazon-ecs-preview-support-for-efs-file-systems-now-available/

Reproduction Steps

import * as ec2 from "@aws-cdk/aws-ec2";
import * as ecs from "@aws-cdk/aws-ecs";
import * as efs from "@aws-cdk/aws-efs";
import * as elbv2 from "@aws-cdk/aws-elasticloadbalancingv2";
import * as logs from "@aws-cdk/aws-logs";
import * as cdk from "@aws-cdk/core";

export interface WebserverProps {
    filesystem: efs.IEfsFileSystem;
}

export class Webserver extends cdk.Construct {
    public constructor(scope: cdk.Construct, id: string, props: WebserverProps) {
        super(scope, id);

        // https://github.com/aws/containers-roadmap/issues/53 - EFS + Fargate
        const taskDefinition = new ecs.TaskDefinition(this, "TaskDefinition", {
            compatibility: ecs.Compatibility.EC2,
        });

        // Patch in the EFS support.
        const rawTask = taskDefinition.node.findChild("Resource") as ecs.CfnTaskDefinition;
        rawTask.volumes = [
            {
                name: "invision",
                efsVolumeConfiguration: {
                    fileSystemId: props.filesystem.fileSystemId,
                    rootDirectory: "/",
                },
            } as ecs.CfnTaskDefinition.VolumeProperty,
        ];
    }
}

Error Log

None, the resource just refuses to include the efsVolumeConfiguration options.

Environment

  • CLI Version : 1.30.0
  • Framework Version: 1.30.0
  • OS : Windows 10
  • Language : Typescript

Other


This is :bug: Bug Report

@aws-cdaws-ecs efformedium feature-request in-progress needs-cfn p2

Most helpful comment

I managed to devise a fairly consistent workaround to handle EFS volume configurations (as well as EFS access points and filesystem policies) while I wait for CFN+CDK support.

Full repo with the examples is https://github.com/aws-samples/amazon-efs-integrations/ if you want to give it a try separately before trying this workaround on your real code.

Basically, I let the ApplicationLoadBalanced(Ec2|Fargate)Service construct from ECS Patterns create the initial task definition, then I use an AwsCustomResource construct to execute a registerTaskDefinition call against that same task definition and pass it the actual task definition configuration I need in order to configure my EFS volume mounts. This ends up creating a new revision, which I then use a CDK escape hatch to apply to the ECS service. This does result in a longer first-time deployment (since CDK will wait for the ECS service to stabilize before goes and changes everything), but subsequent deployments are fine.

The reason this all works is because, while there's no CFN support yet for EFS volume configurations in ECS, there is support for it in the SDK, which does not reject a task definition using efsVolumeConfiguration like the CDK TaskDefinition derivatives would.

I like this approach over the other workarounds I've seen because (a) it lets me do everything in CDK with no additional commands or manual console instructions required, (b) it lets me take advantage of all the conveniences that the ApplicationLoadBalanced(Ec2|Fargate)Service constructs provide, and (c) once CDK support for these capabilities is enabled, it should make refactoring very easy since all of the task definition configuration is already there alongside where I initially create the service.

Hope this helps somebody!

All 7 comments

I am afraid efsVolumeConfiguration is not supported in cloudformation yet.

Pending on this issue https://github.com/aws/containers-roadmap/issues/825

Ah, I guess that would explain why it's not in CDK yet either then. I followed a few links from that one and saw it's recently been released to EC2 ECS and Fargate as general release now though so good to see some progress on this. Thanks for the update.

Anyone found a good workaround for this? I'm afraid a custom resource might involve redoing the whole ECS creation using the AWS API.

For now I'm using EC2 ECS, mounting the EFS partitions manually on boot via user data and using bind mounts in the task description.

If you're using EC2 ECS you can just get docker to mount your File System:

  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Volumes:
        - Name: jenkins_home
          DockerVolumeConfiguration:
            Driver: local
            DriverOpts:
              type: nfs
              device: !Sub "${ClusterFileSystem}.efs.${AWS::Region}.amazonaws.com:/"
              o: !Sub "addr=${ClusterFileSystem}.efs.${AWS::Region}.amazonaws.com,nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2"
            Labels:
              foo: bar
            Scope: shared
            # Autoprovision: true
      Family: jenkins-frontend
      ContainerDefinitions:
        - Name: jenkins-frontend
          Essential: true
          Image: jenkins/jenkins:lts
          MemoryReservation: 512
          Environment:
            - Name: JENKINS_OPTS
              Value: --prefix=/jenkins
          PortMappings:
            - ContainerPort: 8080
          MountPoints:
            - containerPath: /var/jenkins_home/
              sourceVolume: jenkins_home

I managed to devise a fairly consistent workaround to handle EFS volume configurations (as well as EFS access points and filesystem policies) while I wait for CFN+CDK support.

Full repo with the examples is https://github.com/aws-samples/amazon-efs-integrations/ if you want to give it a try separately before trying this workaround on your real code.

Basically, I let the ApplicationLoadBalanced(Ec2|Fargate)Service construct from ECS Patterns create the initial task definition, then I use an AwsCustomResource construct to execute a registerTaskDefinition call against that same task definition and pass it the actual task definition configuration I need in order to configure my EFS volume mounts. This ends up creating a new revision, which I then use a CDK escape hatch to apply to the ECS service. This does result in a longer first-time deployment (since CDK will wait for the ECS service to stabilize before goes and changes everything), but subsequent deployments are fine.

The reason this all works is because, while there's no CFN support yet for EFS volume configurations in ECS, there is support for it in the SDK, which does not reject a task definition using efsVolumeConfiguration like the CDK TaskDefinition derivatives would.

I like this approach over the other workarounds I've seen because (a) it lets me do everything in CDK with no additional commands or manual console instructions required, (b) it lets me take advantage of all the conveniences that the ApplicationLoadBalanced(Ec2|Fargate)Service constructs provide, and (c) once CDK support for these capabilities is enabled, it should make refactoring very easy since all of the task definition configuration is already there alongside where I initially create the service.

Hope this helps somebody!

Now you can add mount point much easier:

task = FargateTaskDefinition(self, "Task",...)

container = task.add_container("container", ...)

container_volume_mount_point = ecs.MountPoint(
            read_only=False,
            container_path="/bitnami/wordpress",
            source_volume=efs_volume.name
        )
container.add_mount_points(container_volume_mount_point)
Was this page helpful?
0 / 5 - 0 ratings