Error defining ALB with 2 subnets in differents AZ - amazon-web-services

I'm designing a cloudformation to deploy ALB and i got an error that says:
At least two subnets in two different Availability Zones must be specified (Service: AmazonElasticLoadBalancingV2; Status Code: 400; Error Code: ValidationError;
These network was created by other Cloudformation. And now, i go to VPC / SUbnets and i see both created.
The part of code where im defining the subnets in ELB creation is this:
"Subnets": [
{
"Fn::ImportValue": {
"Fn::Join": [
"-",
[
{
"Ref": "ParentSubnetStackName"
},
"PublicSubnet1ID"
]
]
},
"Fn::ImportValue": {
"Fn::Join": [
"-",
[
{
"Ref": "ParentSubnetStackName"
},
"PrivateSubnet2ID"
]
]
}
}
],
The only thing that i think that could be a problem is than im importing by other stack than i dont executing at the same time of this cloudformation.. I don't know if there could be a problem, because the Subnets are created at this moment for sure and they belong to differents AZ.
EDIT:
#jogold The CF is too long. I attach here a piece of the code
"PublicSubnet1": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Fn::ImportValue": {
"Fn::Join": [
"-",
[
{
"Ref": "ParentStackName"
},
"VPCID"
]
]
}
},
"CidrBlock": {
"Ref": "PublicSubnet1CIDR"
},
"AvailabilityZone": {
"Ref": "AZ1"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"-",
[
{
"Ref": "AWS::StackName"
},
"PublicSubnet1"
]
]
}
}
]
}
And after in the outputs i export it:
"PublicSubnet1": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Fn::ImportValue": {
"Fn::Join": [
"-",
[
{
"Ref": "ParentStackName"
},
"VPCID"
]
]
}
},
"CidrBlock": {
"Ref": "PublicSubnet1CIDR"
},
"AvailabilityZone": {
"Ref": "AZ1"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"-",
[
{
"Ref": "AWS::StackName"
},
"PublicSubnet1"
]
]
}
}
]
}
All the subnets are created bye the same way.

Related

AWS CDK: A load balancer cannot be attached to multiple subnets in the same Availability Zone

I'm using AWS CDK and it is failing at App-Load-Balancer level and surprisingly it works for Web-Load-balancer. Looking at generated CloudFormation, it is clear that all "Private Subnets" are getting created in separated AZ and associated Auto-Scaling Group too is creating the instance across multiple-AZs. However, when the CDK is executed, it is failing with the error message - A load balancer cannot be attached to multiple subnets in the same Availability Zone (Service: AmazonElasticLoadBalancing; Status Co
de: 400; Error Code: InvalidConfigurationRequest; Request ID: 62c554cb-34ab-43ef-bac0-be2f0d6fc742; Proxy: null)
APP Server characteristics
AUTOSCALING CF Snippet:
"InstaLendaappASGapp1appsvrASG950CF7C4": {
"Type": "AWS::AutoScaling::AutoScalingGroup",
"Properties": {
"MaxSize": "3",
"MinSize": "1",
"DesiredCapacity": "2",
"LaunchConfigurationName": {
"Ref": "InstaLendaappASGapp1appsvrLaunchConfig18DAF6BB"
},
"Tags": [
{
"Key": "Name",
"PropagateAtLaunch": true,
"Value": "webapp-dc-3-tier-ha/InstaLend-a-appASG-app-1-appsvr-"
}
],
"TargetGroupARNs": [
{
"Ref": "InstaLendaapplbInstaLendalstnrPrivate80InstaLendatgtprivateGroup8D2C8D01"
}
],
"VPCZoneIdentifier": [
{
"Ref": "InstaLendavpcInstaLendaprivateSNSubnet1Subnet35AF6769"
},
{
"Ref": "InstaLendavpcInstaLendaprivateSNSubnet2SubnetD8513C5D"
},
{
"Ref": "InstaLendavpcInstaLendaprivateSNSubnet3SubnetB7B2D12C"
}
]
}
LOADBALANCER CF Snippet:
"InstaLendaapplbCC4F6682": {
"Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties": {
"LoadBalancerAttributes": [
{
"Key": "deletion_protection.enabled",
"Value": "false"
}
],
"Name": "InstaLend-a-app-lb",
"Scheme": "internal",
"SecurityGroups": [
{
"Fn::GetAtt": [
"InstaLendasginternal8649CE7C",
"GroupId"
]
}
],
"Subnets": [
{
"Ref": "InstaLendavpcInstaLendaprivateSNSubnet1Subnet35AF6769"
},
{
"Ref": "InstaLendavpcInstaLendaprivateSNSubnet2SubnetD8513C5D"
},
{
"Ref": "InstaLendavpcInstaLendaprivateSNSubnet3SubnetB7B2D12C"
},
{
"Ref": "InstaLendavpcInstaLendaprivateSNDBSubnet1Subnet2DD722D8"
},
{
"Ref": "InstaLendavpcInstaLendaprivateSNDBSubnet2Subnet59278CD3"
},
{
"Ref": "InstaLendavpcInstaLendaprivateSNDBSubnet3SubnetCC805230"
}
],
"Type": "application"
},
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete",
"Metadata": {
"aws:cdk:path": "webapp-dc-3-tier-ha/InstaLend-a-app-lb/Resource"
}
}
While LB is selecting 6 subnets, ASG associated is selecting only 3 subnets. The details of 3 ASG Subnets (i.e. Private Subnets) had been pasted below:
1st SUBNET
"InstaLendavpcInstaLendaprivateSNSubnet1Subnet35AF6769": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.2.3.0/24",
"VpcId": {
"Ref": "InstaLendavpcE5C8A638"
},
"AvailabilityZone": "us-east-2a",
"MapPublicIpOnLaunch": false,
"Tags": [
{
"Key": "aws-cdk:subnet-name",
"Value": "InstaLend-a-privateSN"
....
2nd SUBNET
"InstaLendavpcInstaLendaprivateSNSubnet2SubnetD8513C5D": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.2.4.0/24",
"VpcId": {
"Ref": "InstaLendavpcE5C8A638"
},
"AvailabilityZone": "us-east-2b",
"MapPublicIpOnLaunch": false,
"Tags": [
{
"Key": "aws-cdk:subnet-name",
"Value": "InstaLend-a-privateSN"
},
{
"Key": "aws-cdk:subnet-type",
"Value": "Private"
},
....
3rd SUBNET
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.2.5.0/24",
"VpcId": {
"Ref": "InstaLendavpcE5C8A638"
},
"AvailabilityZone": "us-east-2c",
"MapPublicIpOnLaunch": false,
"Tags": [
{
"Key": "aws-cdk:subnet-name",
"Value": "InstaLend-a-privateSN"
},
{
"Key": "aws-cdk:subnet-type",
"Value": "Private"
},

Lambda RDS Proxy connection from different VPC

I have two AWS accounts with VPCs connected with peer connections. I have RDS Proxy on account 1 and Lambda in the private, isolated subnet on account 2.
I cannot figure out how to connect to RDS Proxy. I was trying all possible VPC endpoints and interfaces and whatnot.
The only way I managed to connect was through NAT Gateway, but it's expensive. And to be honest, weird, if I want to keep a private network.
Is it possible to have a PrivateLink or something?
How should I connect to RDS Proxy from Lambda?
I have attached the CF template (I hope I cleaned it from all sensitive data 😑):
{
"Resources": {
"vpcA2121C38": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16",
"EnableDnsHostnames": true,
"EnableDnsSupport": true,
"InstanceTenancy": "default"
},
"Metadata": {
"aws:cdk:path": "Mws/vpc/Resource"
}
},
"vpcPrivateSubnet1Subnet934893E8": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.0.0/26",
"VpcId": {
"Ref": "vpcA2121C38"
},
"AvailabilityZone": {
"Fn::Select": [
0,
{
"Fn::GetAZs": ""
}
]
},
"MapPublicIpOnLaunch": false
},
"Metadata": {
"aws:cdk:path": "Mws/vpc/PrivateSubnet1/Subnet"
}
},
"vpcPrivateSubnet1RouteTableB41A48CC": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "vpcA2121C38"
}
},
"Metadata": {
"aws:cdk:path": "Mws/vpc/PrivateSubnet1/RouteTable"
}
},
"vpcPrivateSubnet1RouteTableAssociation67945127": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": {
"Ref": "vpcPrivateSubnet1RouteTableB41A48CC"
},
"SubnetId": {
"Ref": "vpcPrivateSubnet1Subnet934893E8"
}
},
"Metadata": {
"aws:cdk:path": "Mws/vpc/PrivateSubnet1/RouteTableAssociation"
}
},
"vpcS3CB758969": {
"Type": "AWS::EC2::VPCEndpoint",
"Properties": {
"ServiceName": {
"Fn::Join": [
"",
[
"com.amazonaws.",
{
"Ref": "AWS::Region"
},
".s3"
]
]
},
"VpcId": {
"Ref": "vpcA2121C38"
},
"RouteTableIds": [
{
"Ref": "vpcPrivateSubnet1RouteTableB41A48CC"
}
],
"VpcEndpointType": "Gateway"
},
"Metadata": {
"aws:cdk:path": "Mws/vpc/S3/Resource"
}
},
"vpcPeertomainaccount833D3E2C": {
"Type": "AWS::EC2::VPCPeeringConnection",
"Properties": {
"PeerVpcId": "vpc-f04b939b",
"VpcId": {
"Ref": "vpcA2121C38"
},
"PeerOwnerId": "XXXX__ACCOINT_1__XXXXXX",
"PeerRoleArn": "arn:aws:iam::XXXX__ACCOINT_1__XXXXXX:role/VPCPeerConnection"
},
"Metadata": {
"aws:cdk:path": "Mws/vpc/Peer to main account"
}
},
"producerServiceRoleEBCB54D0": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
}
}
],
"Version": "2012-10-17"
},
"ManagedPolicyArns": [
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
]
]
},
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
]
]
}
]
},
"Metadata": {
"aws:cdk:path": "Mws/producer/producer/ServiceRole/Resource"
}
},
"producerServiceRoleDefaultPolicyEA5B80A1": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": [
"xray:PutTraceSegments",
"xray:PutTelemetryRecords"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"s3:GetObject*",
"s3:GetBucket*",
"s3:List*"
],
"Effect": "Allow",
"Resource": [
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":s3:::",
{
"Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"
}
]
]
},
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":s3:::",
{
"Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"
},
"/*"
]
]
}
]
}
],
"Version": "2012-10-17"
},
"PolicyName": "producerServiceRoleDefaultPolicyEA5B80A1",
"Roles": [
{
"Ref": "producerServiceRoleEBCB54D0"
}
]
},
"Metadata": {
"aws:cdk:path": "Mws/producer/producer/ServiceRole/DefaultPolicy/Resource"
}
},
"producerSecurityGroup9AA1BE28": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Automatic security group for Lambda Function Mwsproducer416E938A",
"SecurityGroupEgress": [
{
"CidrIp": "0.0.0.0/0",
"Description": "Allow all outbound traffic by default",
"IpProtocol": "-1"
}
],
"VpcId": {
"Ref": "vpcA2121C38"
}
},
"Metadata": {
"aws:cdk:path": "Mws/producer/producer/SecurityGroup/Resource"
}
},
"producerAD962441": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"S3Bucket": {
"Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"
},
"S3Key": "dc05df325f7034421a587e7ee47aed301c7472d001152e686053dd9d5c45c164.zip"
},
"Role": {
"Fn::GetAtt": [
"producerServiceRoleEBCB54D0",
"Arn"
]
},
"Description": "Produces MWS customer orders messages",
"Environment": {
"Variables": {
"DB_HOST": "mws-rds-proxy.proxy-XXXXXXXXX.eu-central-1.rds.amazonaws.com",
"DB_NAME": "dev"
}
},
"Handler": "lambda/mws_producer.php",
"Layers": [
"arn:aws:lambda:eu-central-1:209497400698:layer:php-80:18"
],
"MemorySize": 1024,
"Runtime": "provided.al2",
"Timeout": 900,
"TracingConfig": {
"Mode": "Active"
},
"VpcConfig": {
"SecurityGroupIds": [
{
"Fn::GetAtt": [
"producerSecurityGroup9AA1BE28",
"GroupId"
]
}
],
"SubnetIds": [
{
"Ref": "vpcPrivateSubnet1Subnet934893E8"
}
]
}
},
"DependsOn": [
"producerServiceRoleDefaultPolicyEA5B80A1",
"producerServiceRoleEBCB54D0"
]
}
}
}
Devil as we know hidden in detail. In this case, it's a Route Tables.
When we create a Peering connection between VPCs we also need to give to know our subnets how to use it. Basically, just add peering connection id (pcx-XXX) as a target for peering network.
Took me several days to realize it. Happy happy happy!

Invalid Parameter Combination when creating a new Elasticache Redis Instance using Cloudformation

I am creating a new stack which includes a Redis instance, after starting the creation, I get this error for redis:
Cannot use the given parameters when creating new replication group
in an existing global replication group. (Service: AmazonElastiCache;
Status Code: 400; Error Code: InvalidParameterCombination;
I am new to using elasticache within cloudformation and the documentation doesn't provide a lot of helpful information for the valid/correct combination.
I am using the following snippet:
cachesubnet:
Type: AWS::ElastiCache::SubnetGroup
Properties:
CacheSubnetGroupName: !Join ["-" , ["rb", !Ref Environment, "redis-subnet-group"]]
Description: subnet group for redis
SubnetIds:
- !Ref private1a
- !Ref private1b
Tags:
- Key: environment
Value: !Ref Environment
redis2:
Type: AWS::ElastiCache::ReplicationGroup
Properties:
AtRestEncryptionEnabled: True
AutomaticFailoverEnabled: True
AutoMinorVersionUpgrade: True
CacheNodeType: cache.m5.large
CacheParameterGroupName: default.redis5.0
CacheSubnetGroupName: !Ref cachesubnet
Engine: redis
EngineVersion: 5.0.6
NumNodeGroups: 1
GlobalReplicationGroupId: !Join ["-" , ["rb-horizon", !Ref Environment]]
MultiAZEnabled: True
NodeGroupConfiguration:
- PrimaryAvailabilityZone: us-east-1a
- ReplicaAvailabilityZones:
- us-east-1b
- ReplicaCount: 1
PreferredCacheClusterAZs:
- us-east-1a
- us-east-1b
PreferredMaintenanceWindow: mon:06:30-mon:07:30
ReplicationGroupDescription: Horizon for env
ReplicationGroupId: !Join ["-" , ["rb-horizon", !Ref Environment, rgi]]
SecurityGroupIds:
- !GetAtt mainSecGroup.GroupId
Tags:
- Key: environment
Value: !Ref Environment
Ran into a similar issue today and was able to solve it via some information gleaned from this thread https://old.reddit.com/r/aws/comments/rvgv15/demystifying_redis_in_cloudformation_multiaz_and/
You do not need to specify parameters such as Engine, EngineVersion, CacheNodeType, etc... because ElastiCache will know to use the same values as the ones provided in the primary replication group of the global datastore.
While it says there that the params are not needed, they actually do raise the above error message. I added a condition around those fields and then my stack went through fine.
// edited to add example below
Example redis template. I removed the mappings and snipped the security group ingress rules which are not relevant for demonstration purposes.
The GlobalReplicationGroupId param should not be set for the PRIMARY redis group. Instead, the PRIMARY is joined to the global data store while creating the GlobalReplicationGroup. You should only add the primary member in that resource.
For creating the secondary groups, first launch redis with this param empty and then update it with the param pointing to the previously created GlobalReplicationGroup to join the global store.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
"GlobalReplicationGroupId": {
"Description": "ID of the previously created Global Replication Group (optional)",
"Type": "String",
"Default": ""
}
},
"Conditions": {
"IsGlobalStore": {
"Fn::Not": [{
"Fn::Equals": [ { "Ref": "GlobalReplicationGroupId" }, "" ]
}]
}
},
"Resources": {
"RedisParameterGroup": {
"Type": "AWS::ElastiCache::ParameterGroup",
"Properties": {
"CacheParameterGroupFamily": "redis6.x",
"Description": {
"Fn::Join": [
"",
[
"Redis Parameter Group ",
{
"Ref": "EnvironmentName"
}
]
]
}
}
},
"RedisSubnetGroup": {
"Type": "AWS::ElastiCache::SubnetGroup",
"Properties": {
"CacheSubnetGroupName": {
"Fn::Join": [
"", [
"", { "Ref": "EnvironmentName" }, "-redis-subnet-group"
]
]
},
"SubnetIds": {
"Fn::FindInMap": [
"privateSubnets",
{
"Ref": "AWS::Region"
},
{
"Ref": "EnvironmentName"
}
]
},
"Description": {
"Fn::Join": [
"",
[
"Redis Subnet Group ",
{
"Ref": "EnvironmentName"
}
]
]
}
}
},
"RedisSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": {
"Fn::Join": [
"",
[
"Redis Security Group ",
{
"Ref": "EnvironmentName"
}
]
]
},
"VpcId": {
"Fn::FindInMap": [
"vpcId",
{
"Ref": "AWS::Region"
},
{
"Ref": "EnvironmentName"
}
]
},
"SecurityGroupIngress": [
],
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"Redis-",
{
"Ref": "EnvironmentName"
},
"-SecurityGroup"
]
]
}
},
{
"Key": "Product",
"Value": "Redis"
},
{
"Key": "Environment",
"Value": {
"Ref": "EnvironmentName"
}
}
]
}
},
"RedisReplicationGroup": {
"Type": "AWS::ElastiCache::ReplicationGroup",
"Properties": {
"GlobalReplicationGroupId": {
"Fn::If": [
"IsGlobalStore",
{"Ref": "GlobalReplicationGroupId"},
{"Ref": "AWS::NoValue"}
]
},
"AutomaticFailoverEnabled": "true",
"CacheNodeType": {
"Fn::If": [
"IsGlobalStore",
{
"Ref": "AWS::NoValue"
},
{
"Fn::FindInMap": [
"RedisNodeType",
{
"Ref": "AWS::Region"
},
{
"Ref": "EnvironmentName"
}
]
}
]
},
"CacheParameterGroupName": {
"Fn::If": [
"IsGlobalStore",
{
"Ref": "AWS::NoValue"
},
{
"Ref": "RedisParameterGroup"
}
]
},
"CacheSubnetGroupName": {
"Ref": "RedisSubnetGroup"
},
"Engine": {
"Fn::If": [
"IsGlobalStore",
{
"Ref": "AWS::NoValue"
},
"redis"
]
},
"EngineVersion": {
"Fn::If": [
"IsGlobalStore",
{
"Ref": "AWS::NoValue"
},
"6.2"
]
},
"NumCacheClusters": {
"Fn::FindInMap": [
"NumCacheClusters",
{
"Ref": "AWS::Region"
},
{
"Ref": "EnvironmentName"
}
]
},
"PreferredCacheClusterAZs": {
"Fn::FindInMap": [
"ZoneMap",
{
"Ref": "AWS::Region"
},
"AZ"
]
},
"ReplicationGroupDescription": {
"Fn::Join": [
"",
[
"Redis Replication Group ",
{
"Ref": "EnvironmentName"
}
]
]
},
"SecurityGroupIds": [
{
"Ref": "RedisSecurityGroup"
}
],
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"Redis-",
{
"Ref": "EnvironmentName"
}
]
]
}
},
{
"Key": "Product",
"Value": "Redis"
},
{
"Key": "Environment",
"Value": {
"Ref": "EnvironmentName"
}
}
]
}
}
},
"Outputs": {}
}

AWS Lambda + VPC Elastic IP Timeout

I'm trying to assign a static ip to multiple lambdas so that when a lambda makes a call to a specific service I can whitelist that ip.
I was able to get this working but as far as I can tell, it will randomly start either taking almost exactly 2 minutes to return where before it was 500ms or just start timing out all together.
Below is the cloudformation I used to setup this VPC and in this cloudformation I setup the following:
Public Subnet
Private Subnet
NAT Gateway
Elastic IP
2 Routes (public/private)
Internet Gateway
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "AWS CloudFormation for VPC",
"Parameters": {
"env": {
"Type": "String"
}
},
"Resources": {
"VPCStaticIP": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "11.0.0.0/16",
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
["lambavpc", "-", { "Ref": "env" }]
]
}
}
]
}
},
"SubnetPublic": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "11.0.0.0/24",
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"lambavpc",
"-",
{ "Ref": "env" },
"-",
"public-subnet"
]
]
}
}
],
"VpcId": {
"Ref": "VPCStaticIP"
}
}
},
"SubnetPrivate": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "11.0.1.0/24",
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"lambavpc",
"-",
{ "Ref": "env" },
"-",
"private-subnet"
]
]
}
}
],
"VpcId": {
"Ref": "VPCStaticIP"
}
}
},
"InternetGateway": {
"Type": "AWS::EC2::InternetGateway",
"Properties": {
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
["lambavpc", "-", { "Ref": "env" }, "-", "igw"]
]
}
}
]
}
},
"VPCGatewayAttachment": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"InternetGatewayId": {
"Ref": "InternetGateway"
},
"VpcId": {
"Ref": "VPCStaticIP"
}
}
},
"RouteTablePublic": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPCStaticIP"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"lambavpc",
"-",
{ "Ref": "env" },
"-",
"public-route"
]
]
}
}
]
}
},
"RoutePublic": {
"Type": "AWS::EC2::Route",
"Properties": {
"DestinationCidrBlock": "0.0.0.0/0",
"GatewayId": {
"Ref": "InternetGateway"
},
"RouteTableId": {
"Ref": "RouteTablePublic"
}
}
},
"SubnetRouteTableAssociationPublic": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": {
"Ref": "RouteTablePublic"
},
"SubnetId": {
"Ref": "SubnetPublic"
}
}
},
"EIP": {
"Type": "AWS::EC2::EIP",
"Properties": {
"Domain": "vpc",
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
["lambavpc", "-", { "Ref": "env" }, "-", "eip"]
]
}
}
]
}
},
"NatGateway": {
"Type": "AWS::EC2::NatGateway",
"Properties": {
"AllocationId": {
"Fn::GetAtt": ["EIP", "AllocationId"]
},
"SubnetId": {
"Ref": "SubnetPublic"
}
}
},
"RouteTablePrivate": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPCStaticIP"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"lambavpc",
"-",
{ "Ref": "env" },
"-",
"private-route"
]
]
}
}
]
}
},
"RoutePrivate": {
"Type": "AWS::EC2::Route",
"Properties": {
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": {
"Ref": "NatGateway"
},
"RouteTableId": {
"Ref": "RouteTablePrivate"
}
}
},
"SubnetRouteTableMainAssociationPrivate": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": {
"Ref": "RouteTablePrivate"
},
"SubnetId": {
"Ref": "SubnetPrivate"
}
}
}
},
"Outputs": {}
}
I've done quite a bit of research and turned up these references:
https://gist.github.com/reggi/dc5f2620b7b4f515e68e46255ac042a7
AWS Lambda: How to set up a NAT gateway for a lambda function with VPC access
but I can't seem to reason what the delta is between what I'm doing and what they are suggesting.
Any suggestions would be greatly appreciated it!
The EIP timeouts probably because you do not have DependsOn attribute on your AWS::EC2::VPCGatewayAttachment. This is required in your case:
If you define an Elastic IP address and associate it with a VPC that is defined in the same template, you must declare a dependency on the VPC-gateway attachment by using the DependsOn Attribute on this resource.
Thus, you could try the following which adds the dependency:
"EIP": {
"Type": "AWS::EC2::EIP",
"DependsOn" : "VPCGatewayAttachment",
"Properties": {
"Domain": "vpc",
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
["lambavpc", "-", { "Ref": "env" }, "-", "eip"]
]
}
}
]
}
}
Also, if possible, I would consider using a private IP range of 10.0.0.0/16 for your VPC and subnets instead of 11.0.0.0/16. The range is recommended to be used by AWS:
When you create a VPC, we recommend that you specify a CIDR block (of /16 or smaller) from the private IPv4 address ranges as specified in RFC 1918:
10.0.0.0 - 10.255.255.255 (10/8 prefix)
172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
192.168.0.0 - 192.168.255.255 (192.168/16 prefix)
You don't show how you are creating the Lambda function, is that created outside of CloudFormation? It sounds like you have the Lambda function configured to use both VPC subnets, and when it runs inside the public subnet it is getting timeouts. You need to configure the Lambda function to only use the private subnet with a route to the NAT Gateway.

AWS CloudFormation template "Launch configuration name not found"

I came across this issue with AWS CloudFormation template I'm creating. I am creating an AutoScaling group and assign LaunchConfiguration to it, but when I run the template I get the error "Launch configuration name not found - A launch configuration with the name: WebServerASLaunchConfig does not exists". Here is the exact code snippet
"WebServerASLaunchConfig": {
"Type" : "AWS::AutoScaling::LaunchConfiguration",
"Properties": {
"ImageId": {
"Ref": "BaseImageId"
},
"KeyName": {
"Ref": "KeyPairName"
},
"AssociatePublicIpAddress" : "True",
"InstanceType": "t2.small",
"SecurityGroups": [
{
"Ref": "EC2InstanceSecurityGroup"
}
]
}
},
"WebServerAutoScalingGroup": {
"Type": "AWS::AutoScaling::AutoScalingGroup",
"Properties": {
"LaunchConfigurationName": "WebServerASLaunchConfig",
"AvailabilityZones": [
{
"Ref": "AvailabilityZone1"
},
{
"Ref": "AvailabilityZone2"
}
],
"VPCZoneIdentifier": [
{
"Ref" : "PublicSubnet1"
},
{
"Ref" : "PublicSubnet2"
}
],
"MinSize" : "2",
"MaxSize" : "2",
"LoadBalancerNames": [
{
"Ref" : "ApplicationLoadBalancer"
}
],
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"-",
[
{
"Ref": "AWS::StackName"
},
"VPC"
]
]
},
"PropagateAtLaunch": "True"
}
]
}
}
Thanks for the help
To reference any parameters or resources make use of Ref.
Replace "LaunchConfigurationName": "WebServerASLaunchConfig",
with:
"LaunchConfigurationName": { "Ref": "WebServerASLaunchConfig" }