CloudFormation Template Error when placing EC2 Instance in particular subnet - amazon-web-services

Working on a CF example template and am attempting to place an EC2 instance into a subnet created from the same template. When doing things as is, I get this error:
The parameter groupName cannot be used with the parameter subnet
Here's a subset of the template:
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 172.34.0.0/16
EnableDnsHostnames: False
Tags:
Subnet1:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: us-west-1a
CidrBlock: 172.34.0.0/24
VpcId:
Ref: VPC
MapPublicIpOnLaunch: False
WebServer1:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", AMI]
InstanceType: t2.micro
SubnetId:
Ref: Subnet1
SecurityGroups:
- Ref: ServerSecurityGroup
Tags:
- Key: "Name"
Value: "Tyler-Cloudformation"
How can I refer to Subnet 1 when creating WebServer1 and place it within that subnet? What am I missing here? Thanks in advance!

The error is probably because you are using SecurityGroups rather then SecurityGroupIds. The former parameter is only used for default-VPCs, while for non-default ones, the latter must be used.
Thus, instead of SecurityGroups you should have:
SecurityGroupIds:
- !GetAtt ServerSecurityGroup.GroupId

Related

Serverless error - Value of property DBSubnetGroupName must be of type String

I am attempting to geneate an Aurora serverless database for an application using Serverless to build it.
I copied a CloudFormation template I found online for this portion of my setup. I reference the below resource from my Serverless.yml file (which I've excluded because it's very large).
Serverless fails with the message:
An error occurred: AuroraCluster - Value of property DBSubnetGroupName
must be of type String.
I am confused about this because, to my observation, DBSubnetGroupName is a string (which as you can see is set to the value of 'db-subnet-group').
I am new to both Serverless and CloudFormation, and am doing my best to piece a solution together for a product I am building. Any suggestion as to how to fix this problem would be much appreciated.
Below is my Serverless file. Many thanks in advance for any assistance!
Resources:
ServerlessSecurityGroup:
DependsOn: VPC
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: SecurityGroup for Serverless Functions
VpcId:
Ref: VPC
PrivateSubnetA:
DependsOn: VPC
Type: AWS::EC2::Subnet
Properties:
VpcId:
Ref: VPC
AvailabilityZone: "eu-west-1a"
CidrBlock: "10.0.1.0/24"
PrivateSubnetB:
DependsOn: VPC
Type: AWS::EC2::Subnet
Properties:
VpcId:
Ref: VPC
AvailabilityZone: "eu-west-1b"
CidrBlock: "10.0.64.0/19"
AuroraSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: Subnet group for Aurora Database
DBSubnetGroupName: "db-subnet-group"
SubnetIds:
- Ref: PrivateSubnetA
- Ref: PrivateSubnetB
AuroraCluster:
Type: AWS::RDS::DBCluster
DeletionPolicy: ${self:custom.deletion_policy}
Properties:
DBClusterIdentifier: ${self:custom.aurora_db_name}
MasterUsername: !Sub ${self:custom.aurora_db_name}
MasterUserPassword: asdfasdfasdf223
DatabaseName: "somename"
Engine: aurora
EngineMode: serverless
DBSubnetGroupName:
- Ref: AuroraSubnetGroup
VpcSecurityGroupIds:
- Ref: ServerlessSecurityGroup
EnableHttpEndpoint: true
ScalingConfiguration:
AutoPause: true
MinCapacity: 1
MaxCapacity: 2
SecondsUntilAutoPause: 3600
Outputs:
AuroraCluster:
Value:
Ref: AuroraCluster
In your AWS::RDS::DBCluster it should be:
DBSubnetGroupName: !Ref AuroraSubnetGroup
In your example, you're passing DBSubnetGroupName as an array, not a string:
DBSubnetGroupName:
- Ref: AuroraSubnetGroup
In order to pass it as a string, you should use this notation:
DBSubnetGroupName: Ref: AuroraSubnetGroup

Cannot See Running instances on EC2 Dashboard after launching EC2 Fleet Via CFN Template

I am using following CFN template to create EC2 Infra stack. The stack gets created but I cannot see EC2 Running instances. It says 0 running instances.
---
AWSTemplateFormatVersion: "2010-09-09"
Description: ""
Resources:
WebServerVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: false
EnableDnsHostnames: false
InstanceTenancy: dedicated
Tags:
- Key: stack
Value: production
WebServerSubnet:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 10.0.1.0/24
MapPublicIpOnLaunch: true
VpcId:
Ref: WebServerVPC
WebServerInternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: stack
Value: production
WebserverIGWandVPCAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId:
Ref: WebServerInternetGateway
VpcId:
Ref: WebServerVPC
WebServerRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId:
Ref: WebServerVPC
Tags:
- Key: stack
Value: production
WebServerSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId:
Ref: WebServerRouteTable
SubnetId:
Ref: WebServerSubnet
WebServerRoute:
Type: AWS::EC2::Route
DependsOn: WebServerInternetGateway
Properties:
RouteTableId:
Ref: WebServerRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId:
Ref: WebServerInternetGateway
WebServerEC2LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateData:
ImageId: ami-083ac7c7ecf9bb9b0
InstanceType: t3.micro
KeyName: test_key_pair
NetworkInterfaces:
- SubnetId:
Ref: WebServerSubnet
LaunchTemplateName: WebServerEC2LaunchTemplate
WebServerEC2Fleet:
Type: AWS::EC2::EC2Fleet
DependsOn: WebServerEC2LaunchTemplate
Properties:
LaunchTemplateConfigs:
- LaunchTemplateSpecification:
LaunchTemplateName: WebServerEC2LaunchTemplate
Version: !GetAtt WebServerEC2LaunchTemplate.LatestVersionNumber
TargetCapacitySpecification:
TotalTargetCapacity: 5
OnDemandTargetCapacity: 5
SpotTargetCapacity: 0
DefaultTargetCapacityType: on-demand
Where do we see Instances launched via EC2 Fleet? Is it on EC2 Dashboard or somewhere else? In the above template I am also creating VPC and other routing objects.

Use Qa, Dev and Prod as an environement in Cloudformation

I have created this nested stack. I want to implement the same stack with {prod, dev, qa} environment. Like I want to up the same stack but it doesn't have any name conflicts with each other. I want to deploy the same stack in three different environment, What changes do I have to make to achieve it
Root:
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
bucketname:
Type: String
Description: Path to the bucket
Default: webserver
bucketpath:
Type: String
Description: Path to the bucket
Default: /env #/mysql
Env:
Type: String
Description: Select the appropriate environment
AllowedValues:
- dev
- test
- uat
- prod
Cidr:
Type: String
Description: Cidr for vpc
Publicsubnet1:
Type: String
Description: public subnet 1
Publicsubnet2:
Type: String
Description: public subnet 2
Privatesubnet1:
Type: String
Description: Private subnet 1
Privatesubnet2:
Type: String
Description: Private subnet 2
Resources:
Vpcstack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: !Sub "https://${bucketname}.s3.us-east-2.amazonaws.com${bucketpath}/vpc.yml"
Parameters:
Env: Ref: Env
Cidr: !Ref Cidr
Publicsubnet1: !Ref Publicsubnet1
Publicsubnet2: !Ref Publicsubnet2
Privatesubnet1: !Ref Privatesubnet1
Privatesubnet2: !Ref Privatesubnet2
Vpc:
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
Cidr:
Type: String
Description: Cidr for vpc
Publicsubnet1:
Type: String
Description: public subnet 1
Publicsubnet2:
Type: String
Description: public subnet 2
Privatesubnet1:
Type: String
Description: Private subnet 1
Privatesubnet2:
Type: String
Description: Private subnet 2
Env:
Type: String
Description: Select the appropriate environment
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref Cidr
EnableDnsSupport: true
EnableDnsHostnames: true
InstanceTenancy: default
InternetGateway:
Type: AWS::EC2::InternetGateway
VPCGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
SubnetA:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: us-east-2a
VpcId: !Ref VPC
CidrBlock: !Ref Publicsubnet1
MapPublicIpOnLaunch: true
SubnetB:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: us-east-2b
VpcId: !Ref VPC
CidrBlock: !Ref Publicsubnet2
MapPublicIpOnLaunch: true
SubnetC:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: us-east-2a
VpcId: !Ref VPC
CidrBlock: !Ref Privatesubnet1
MapPublicIpOnLaunch: false
SubnetD:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: us-east-2b
VpcId: !Ref VPC
CidrBlock: !Ref Privatesubnet2
MapPublicIpOnLaunch: false
RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
RouteTable2:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
InternetRoute:
Type: AWS::EC2::Route
DependsOn: VPCGatewayAttachment
Properties:
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
RouteTableId: !Ref RouteTable
SubnetARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTable
SubnetId: !Ref SubnetA
SubnetBRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTable
SubnetId: !Ref SubnetB
SubnetCRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTable2
SubnetId: !Ref SubnetC
SubnetDRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTable2
SubnetId: !Ref SubnetD
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: "Internet Group"
GroupDescription: "SSH traffic in, all traffic out."
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: "22"
ToPort: "22"
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
NAT:
Type: AWS::EC2::NatGateway
Properties:
AllocationId:
Fn::GetAtt:
- EIP
- AllocationId
SubnetId:
Ref: SubnetA
Tags:
- Key: Name
Value: !Sub "nat-${Env}"
EIP:
DependsOn: VPCGatewayAttachment
Type: AWS::EC2::EIP
Properties:
Domain: VPC
Route:
Type: AWS::EC2::Route
Properties:
RouteTableId:
Ref: RouteTable2
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId:
Ref: NAT
Outputs:
VpcID:
Description: VPC id
Value: !Ref VPC
Export:
Name: "VpcID"
SubnetA:
Description: public subnet
Value: !Ref SubnetA
Export:
Name: "SubnetA"
SubnetB:
Description: public subnet 2
Value: !Ref SubnetB
Export:
Name: "SubnetB"
SubnetC:
Description: priavte subnet
Value: !Ref SubnetC
Export:
Name: "SubnetC"
SubnetD:
Description: private subnet 2
Value: !Ref SubnetD
Export:
Name: "SubnetD"
You can specify different names for your top-level stacks by adding the environment to the top-level stack name. You do this at the time of stack creation, via the console or programmatically.
Then when each top-level environment-specific stack runs it will create the necessary nested stacks without name conflicts. You won't be able to control the stack names for the nested stacks, but you can get the name using outputs.
See the following:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stack.html
You can add output values from a nested stack within the containing
template. You use the GetAtt function with the nested stack's logical
name and the name of the output value in the nested stack in the
format Outputs.NestedStackOutputName.
CloudFormation nested stack name
If you need to use different resource values for the different environments, then you can use mappings to specify the settings that correspond to the selected environment. Here is an example of mappings:
Mappings:
EnvTypeMap:
prod:
vpc: vpc-a6842gb0
subnet: subnet-hjk23553
dev:
vpc: vpc-b7742gb0
subnet: subnet-abc23553
qa:
vpc: vpc-c2542gb0
subnet: subnet-uio23553
Then to reference one of these mapping values you would do so like this:
VpcId:
Fn::FindInMap:
- EnvTypeMap
- Ref: Env
- vpc
CF stack is identified by a stack-name. All you have to do is to specify this stack-name when you are deploying the CF template.
aws cloudformation deploy --stack-name <value> --template-file <value> ...
If you specify the name of an existing stack, that stack will be updated. If you specify a new name, you will create a new stack from a given template.
You can create as many stacks as you want from a singe template by choosing new stack name each time. You do not need to worry about naming conflicts because each resource's name in a given stack is uniquely identified based on the stack name which will be different.
aws cloudformation deploy --stack-name dev --template-file the-same-template.yaml ...
aws cloudformation deploy --stack-name test --template-file the-same-template.yaml ...
aws cloudformation deploy --stack-name uat --template-file the-same-template.yaml ...
aws cloudformation deploy --stack-name prod --template-file the-same-template.yaml ...
This will create 4 separate stacks (dev, test, uat, prod).
Note that since you are hardcoding IP address ranges, resources in these stacks will not be able to communicate between each other because of overlapping networks (which probably is what you want anyway) but if for some reason you need these to communicate, you will need to create Parameters for CIDR blocks (VPC, subnets) as well.

AWS CloudFormation: how do I refer to the default/main route table (that is created when a VPC is created) in a cloudformation template?

I have a CloudFormation template that creates a custom VPC.
The template creates the following resources - a VPC, an Internet Gateway, attaches the IGW to the VPC, and creates a Public Subnet.
I want to add a route (destination 0.0.0.0/0, target IGW) to the Route Table that gets created as part of the VPC.
I have read through the cloudformation documentation for routes, route tables to figure out how to do this, but to no avail.
I can use the Fn::Ref function to refer to resources or parameters that are explicitly created as part of the template, but how do I refer to resources that get created inherently with the VPC?
Any insights on how to re-use the existing route table, NACL and Security Group are much appreciated.
Thanks,
Good job so far - you have your internet gateway, route table, and a public subnet. Now you need to create the route and attach the route table to the subnet if you haven't already done so. If you're using YAML it might look something like this:
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Ref EnvironmentName
InternetGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [ 0, !GetAZs '' ]
CidrBlock: !Ref PublicSubnet1CIDR
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Public Subnet (AZ1)
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Public Routes
DefaultPublicRoute:
Type: AWS::EC2::Route
DependsOn: InternetGatewayAttachment
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicRouteTable
SubnetId: !Ref PublicSubnet1
Don't use the default route table (see https://serverfault.com/questions/588904/aws-vpc-default-route-table-in-cloudformation)
You can get default security group as per https://serverfault.com/questions/544439/aws-cloudformation-vpc-default-security-group
And finally you can also get the DefaultNetworkAcl in the same as DefaultSecurityGroup above. See also https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html)

AWS CloudFormation Errors with Internet Gateway

CloudFormation beginner here. I've been researching and working on developing a CloudFormation template that will eventually be used as the starting point for a development environment for my team.
I've been picking at bits and pieces through some courses and examples online and have been relatively successful in my small attempt... Until tonight.
I am now trying to attach an Internet Gateway to my VPC and it is causing the Stack creation job to fail and rollback. The Internet Gateway will not attach and for the life of me I just cannot determine why.
My full template is here. The plan is to create a VPC with 2 public and 2 private subnets. There will be an Internet Gateway attached to the 2 public subnets. This is where the failure comes in. If I comment out the Internet Gateway creation, the template is successful. Thanks in advance for your help.
AWSTemplateFormatVersion: '2010-09-09'
Resources:
DevVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
InstanceTenancy: default
Tags:
- Key: Name
Value: dev-vpc
DevRoute53HostedZone:
Type: "AWS::Route53::HostedZone"
Properties:
HostedZoneConfig:
Comment: "aws hosted dev environment"
Name: "mydomain.oregon-dev.local"
VPCs:
-
VPCId: !Ref DevVPC
VPCRegion: "us-west-2"
DevPublicSubnetA:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref DevVPC
CidrBlock: 10.0.8.0/25
AvailabilityZone: "us-west-2a"
Tags:
- Key: Name
Value: DevPublicSubnetA
DevPublicSubnetB:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref DevVPC
CidrBlock: 10.0.8.128/25
AvailabilityZone: "us-west-2b"
Tags:
- Key: Name
Value: DevPublicSubnetB
DevPrivateSubnetA:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref DevVPC
CidrBlock: 10.0.9.0/25
AvailabilityZone: "us-west-2a"
Tags:
- Key: Name
Value: DevPrivateSubnetA
DevPrivateSubnetB:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref DevVPC
CidrBlock: 10.0.9.128/25
AvailabilityZone: "us-west-2b"
Tags:
- Key: Name
Value: DevPrivateSubnetB
RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId:
Ref: DevVPC
Tags:
- Key: Name
Value: DevRouteTable
DevRoute:
Type: AWS::EC2::Route
DependsOn: NonProdNATGateway
Properties:
RouteTableId:
Ref: RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId:
Ref: NonProdNATGateway
NonProdNATEIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
NonProdNATGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt NonProdNATEIP.AllocationId
SubnetId: !Ref DevPublicSubnetA
SubnetId: !Ref DevPublicSubnetB
DependsOn:
- NonProdNATEIP
- DevPublicSubnetA
- DevPublicSubnetB
NonProdGWVPCAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref NonProdNATGateway
VpcId: !Ref DevVPC
DependsOn:
- NonProdNATGateway
Route:
Type: AWS::EC2::Route
Properties:
RouteTableId:
Ref: RouteTable
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId:
Ref: NonProdNATGateway
PrivateRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTable
SubnetId: !Ref DevPrivateSubnetA
SubnetId: !Ref DevPrivateSubnetB
PublicRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTable
SubnetId: !Ref DevPublicSubnetA
SubnetId: !Ref DevPublicSubnetB
Mappings:
R53EnvironmentMapping:
dev:
oregonawslocal: mydomain.oregon-dev.local
Outputs:
DevPublicSubnetA:
Description: ID for dev subnet A
Value: !Ref DevPublicSubnetA
Export:
Name: DevPublicSubnetA
DevPublicSubnetB:
Description: ID for dev subnet B
Value: !Ref DevPublicSubnetB
Export:
Name: DevPublicSubnetB
DevPrivateSubnetA:
Description: ID for dev subnet A
Value: !Ref DevPrivateSubnetA
Export:
Name: DevPrivateSubnetA
DevPrivateSubnetB:
Description: ID for dev subnet B
Value: !Ref DevPrivateSubnetB
Export:
Name: DevPrivateSubnetB
DevRoute53OregonAWSLocalHostedZone:
Description: Hosted zone ID for hosted zone
Value: !Ref DevRoute53HostedZone
Export:
Name: DevRoute53OregonAWSLocalHostedZone
DevRoute53OregonAWSLocalHostedZoneName:
Description: Hosted zone name for hosted zone
Value: !FindInMap [R53EnvironmentMapping, dev, oregonawslocal]
Export:
Name: DevRoute53OregonAWSLocalHostedZoneName
As Michael - sqlbot mentioned in a comment, one issue is that you're referencing an AWS::EC2::NATGateway resource in the AWS::EC2::VPCGatewayAttachment resource's InternetGatewayId property, which requires an AWS::EC2::InternetGateway resource.
NAT Gateways and Internet Gateways are two different types of AWS resources - a NAT Gateway provides outbound-only Internet access to a private Subnet, while an Internet Gateway provides two-way Internet access to a public Subnet.
Another issue is that you need two separate sets of AWS::EC2::RouteTable and AWS::EC2::Route Resources, one set for your public Subnet and another for your private Subnet. The public Route should have GatewayId referencing the Internet Gateway, and the private Route should have NatGatewayId referencing the NAT Gateway.
Finally, you have some invalid duplicate SubnetId properties in several resources (NatGateway, SubnetRouteTableAssociation)- each of these Resources only points accepts a single Subnet ID.
Since you're a CloudFormation beginner, I strongly recommend leveraging AWS Quick Start's Amazon VPC Architecture template to get started quickly with a reference VPC architecture. This AWS-supported template creates a single VPC containing both public and private subnets within each specified Availability Zone (you provide 2-4 Availability Zones as Parameters). You can later customize this template to better fit your specific needs if necessary, or use it as a reference for configuring your own template's resources.