Search code examples
pythonamazon-web-servicesamazon-ecsaws-cdkamazon-vpc

aws python CDK ECS cluster service subnet assignment. ec2.SubnetSelection


I created a VPC

vpc = ec2.Vpc(
    self,
    VPC_CONFIG["vpc_name"],
    cidr=VPC_CONFIG["cidr"],
    nat_gateways=VPC_CONFIG["nat_gateways"],
    subnet_configuration=[],
    enable_dns_support=True,
    enable_dns_hostnames=True,
)

Next, I created some beautiful subnets

for subnet in SUBNETS:
    subnet_created = ec2.CfnSubnet(
        self,
        subnet["name"],
        vpc_id=vpc.vpc_id,
        cidr_block=subnet["cidr_block"],
        availability_zone=subnet["availability_zone"],
        tags=[{"key": "Name", "value": subnet["name"]}],
        map_public_ip_on_launch=True,
    )

Next, I created a cluster with a service. I want to allocate my service in my private subnet, so I tried

cluster = ecs.Cluster(self, "MyCluster", vpc=vpc)

task_definition = ecs.FargateTaskDefinition(
    self,
    f"{VPC_CONFIG['vpc_name']}-MyFargateTaskDefinition",
    memory_limit_mib=512,  # 512 is 0.5 GB
    cpu=256,  # 256 is 0.25 vCPU
)

task_definition.add_container(
    f"{VPC_CONFIG['vpc_name']}-MyBackendContainer",
    image=ecs.ContainerImage.from_registry(BACKEND_CONFIG["docker_image"]),
    memory_reservation_mib=256,
)

print("-"*10, ">", private_subnet, ":(")
# ----------> <aws_cdk.aws_ec2.CfnSubnet object at 0x000001DB96834890> :(
service = ecs.FargateService(
    self,
    "MyService",
    cluster=cluster,
    task_definition=task_definition,
    desired_count=1,
    assign_public_ip=False,
    vpc_subnets=ec2.SubnetSelection(subnets=[private_subnet]),
    security_groups=[private_sec_gp],
)

The trouble here is that I run cdk synth, and I checked my file and I found that vpc_subnets is empty

[![enter image description here][1]][1][1]: https://i.sstatic.net/gkTUK.png

So, after some exhausing hours of researching I found out that ec2.SubnetSelection(subnets=) expects Sequence[ISubnet] type and I have CfnSubnet. I'm not sure if that's the problem. I ommited some code here, but I assume that it's not revelant for solving this :(

I'm stuck because when I run cdk deploy cloudFormation says this

MyService/Service (MyServiceB4132EDA) Resource handler returned message: "Invalid request provided: CreateService error: subnets can not be empty. (Service: AmazonECS; Status Code: 400; Error Code: InvalidParameterException; Request ID: 1643b0eb-61dc-45c8-800a-989ce8ab6c0f; Proxy: null)" (RequestToken: 2ebb2a5c-c39e-03b1-f5e2-6f6284360b97, HandlerErrorCode: InvalidRequest)


Solution

  • Here is an example of configuring the subnets directly in the VPC construct:

    subnet_config = [
        ec2.SubnetConfiguration(
            name="PublicSubnet",
            subnet_type=ec2.SubnetType.PUBLIC,
            cidr_mask=21,
        ),
        ec2.SubnetConfiguration(
            name="PrivateSubnet",
            subnet_type=ec2.SubnetType.PRIVATE_WITH_EGRESS,
            cidr_mask=19,
        ),
        ec2.SubnetConfiguration(
            name="IsolatedSubnet",
            subnet_type=ec2.SubnetType.PRIVATE_ISOLATED,
            cidr_mask=22,
        ),
        ec2.SubnetConfiguration(
            name="VpnSubnet",
            subnet_type=ec2.SubnetType.PRIVATE_ISOLATED,
            cidr_mask=27,
        ),
    ]
    
    # Create the VPC using the L2 construct
    self.vpc = ec2.Vpc(
        scope=self,
        id="Vpc",
        max_azs=2,
        nat_gateways=0,
        subnet_configuration=subnet_config,
        ip_addresses=ec2.IpAddresses.cidr(cidr_block="10.10.0.0/16"),
    )
    

    Then you access it like this:

    ec2.SubnetSelection(subnet_group_name="PublicSubnet")
    ec2.SubnetSelection(subnet_group_name="VpnSubnet")
    ...