I have a fairly simple task that I am unable to complete with AWS CDK: Create a subnet and launch an instance in it using an existing VPC.
The existing VPC is a CfnVpc that I obtained using the cdk migrate
command. Here it is:
class Lab(Stack):
@property
def vpc(self) -> ec2.CfnVPC:
return self._vpc
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(
scope, construct_id, description="Nat instance with two subnets", **kwargs
)
self._vpc = ec2.CfnVPC(
self,
"VPC",
enable_dns_support=True,
enable_dns_hostnames=True,
cidr_block=subnetConfig["VPC"]["CIDR"],
tags=[
{
"key": "Application",
"value": self.stack_name,
},
{
"key": "Network",
"value": "PublicA",
},
],
)
Here are my new resources:
class MyResources(Lab):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
vpc = ec2.Vpc.from_lookup(
self, "L2VPC", tags={"aws:cloudformation:logical-id": "VPC"}
)
publicSubnetB = ec2.Subnet(
self,
"PublicSubnetB",
availability_zone="us-east-1b",
cidr_block="10.0.2.0/24",
vpc_id=vpc.vpc_id,
)
cdk.Tags.of(publicSubnetB).add("Application", self.stack_name)
cdk.Tags.of(publicSubnetB).add("Network", "PublicB")
# These are also exposed from the cdk migrate command via properties.
ec2.CfnSubnetRouteTableAssociation(
self,
"PublicSubnetBRouteTableAssociation",
subnet_id=publicSubnetB.subnet_id,
route_table_id=self.publicRouteTable.ref,
)
ec2.CfnSubnetNetworkAclAssociation(
self,
"PublicSubnetBNetworkAclAssociation",
subnet_id=publicSubnetB.subnet_id,
network_acl_id=self.publicNetworkAcl.ref,
)
And finally, here’s the failing instance:
instanceB = ec2.Instance(
self,
"InstanceB",
instance_type=ec2.InstanceType.of(
instance_class=ec2.InstanceClass.BURSTABLE3,
instance_size=ec2.InstanceSize.MICRO,
),
machine_image=ec2.AmazonLinuxImage(
generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX_2
),
vpc=vpc,
vpc_subnets=ec2.SubnetSelection(
subnet_type=ec2.SubnetType.PUBLIC, availability_zones=["us-east-1b"]
),
user_data=ec2.UserData.custom(userDataB),
private_ip_address="10.0.2.119",
associate_public_ip_address=True,
security_group=sg,
user_data_causes_replacement=True,
)
AWS CDK says that there is no public subnet in az us-east-1b – even though I created it just prior. The only way this works is if I comment out the instance code, run it, clear the context, run it again, and comment back in the instance code. There has got to be a better way!
2
Answers
The solution was very tricky and not well documented in my opinion.
Since I was creating the subnet in the same stack as I used to look up the VPC, I had to use the
ec2.Vpc.from_vpc_attributes()
class method instead of theec2.Vpc.from_lookup()
class method.Does not work:
Error Logs
Works:
It sounds like you need to make it clear to CFN that the instance is dependent upon the subnet being created. You can do something like,
if they are in the same stack or
if the instance and the subnet are in different stacks.