CloudFormation: simple example - amazon-web-services

I would like to build EC2 behind ELB(Elastic Load Balancer).
What would be the yaml/json code of doing this?

If you are looking for sample templates in json/yaml with Cloud Formation designer, you can use this sample templates provided by AWS.
Below is a sample CF template for simple 1 EC2/1 ELB stack
AWSTemplateFormatVersion: '2010-09-09'
Description: '1 EC2 Instance and 1 ELB'
Parameters:
AppServer:
Description: Hostname of Server
Type: String
Default: ec2instance01
MinLength: '1'
MaxLength: '16'
AllowedPattern: '[0-9a-zA-Z-]*'
ConstraintDescription: 'Must contain valid DNS characters, AD length limit.'
AMI:
Description: AMI to deploy AWSLinux Instances
Type: String
Default: ami-xxxxxxxx
InstanceType:
Description: Application EC2 instance type
Type: String
Default: t2.micro
AllowedValues:
- t2.micro
- t2.2xlarge
- m4.2xlarge
ConstraintDescription: Must be a valid EC2 instance type.
VPCID:
Description: Name of the VPC
Type: 'AWS::EC2::VPC::Id'
Default: vpc-xxxxxxxx
ConstraintDescription: Must be a valid VPC.
KeyName:
Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
Type: 'AWS::EC2::KeyPair::KeyName'
Default: XXXX-key
MinLength: '1'
MaxLength: '255'
AllowedPattern: '[\x20-\x7E]*'
ConstraintDescription: Must contain only ASCII characters.
SubnetIdPrivateEastC:
Description: Private subnet for confidential apps in us-east-1c
Type: 'AWS::EC2::Subnet::Id'
Default: subnet-xxxxxxxx
MinLength: '1'
MaxLength: '255'
ConstraintDescription: Must be a valid Private Subnet.
SubnetIdPrivateEastD:
Description: Private subnet for confidential apps in us-east-1d
Type: 'AWS::EC2::Subnet::Id'
Default: subnet-xxxxxxxx
MinLength: '1'
MaxLength: '255'
ConstraintDescription: Must be a valid Private Subnet.
InstanceProfile:
Description: Instance Profile Name
Type: String
Default: xxxx-role
MinLength: '0'
MaxLength: '255'
AllowedPattern: '[\x20-\x7E]*'
ConstraintDescription: Must contain a vailed instance profile name
RootVolumeSize:
Description: Size (GB) of root EBS volume for application instance
Type: Number
Default: '10'
MinValue: '10'
MaxValue: '1024'
SwapDisk:
Description: Size (GB) of application EBS volume for instance
Type: Number
Default: '2'
MinValue: '2'
MaxValue: '128'
SubnetAvailabilityZone:
Description: Availability Zone for subnet
Type: String
Default: us-east-1d
AllowedValues:
- us-east-1c
- us-east-1d
ConstraintDescription: Must be a valid Availability zone.
PrivateSubnets:
Type: List<AWS::EC2::Subnet::Id>
Description: 'Private subnet for the ELB in us-east-1c and us-east-1d'
Default: "subnet-xxxxxxxx,subnet-xxxxxxxx"
Resources:
ec2instance01:
Type: 'AWS::EC2::Instance'
Properties:
DisableApiTermination: 'true'
AvailabilityZone: us-east-1d
ImageId:
Ref: AMI
InstanceType:
Ref: InstanceType
KeyName:
Ref: KeyName
SecurityGroupIds:
- Ref: WebSG
IamInstanceProfile:
Ref: InstanceProfile
SubnetId:
Ref: SubnetIdPrivateEastD
#EbsOptimized: true
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeSize:
Ref: RootVolumeSize
VolumeType: gp2
- DeviceName: /dev/sds
Ebs:
VolumeSize:
Ref: SwapDisk
VolumeType: gp2
Tags:
- Key: Name
Value:
Ref: AppServer
UserData:
'Fn::Base64': !Sub |-
#!/bin/bash -v
yum update -y aws-cfn-bootstrap
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
date > /home/ec2-user/starttime
date > /home/ec2-user/stoptime
echo END
WebSG:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: Web SG
VpcId:
Ref: VPCID
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: 10.0.0.0/8
Tags:
- Key: Name
Value: web_sg
ElbSG:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: ELB SG
VpcId:
Ref: VPCID
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '443'
ToPort: '443'
CidrIp: '0.0.0.0/0'
Tags:
- Key: Name
Value: elb_sg
ElasticLoadBalancer:
Type: AWS::ElasticLoadBalancing::LoadBalancer
DependsOn:
- ec2instance01
Properties:
LoadBalancerName: elb_01
SecurityGroups:
- Ref: ElbSG
Subnets: !Ref PrivateSubnets
Scheme: internal
Instances:
- Ref: ec2instance01
Listeners:
- LoadBalancerPort: '80'
InstancePort: '8080'
InstanceProtocol: HTTP
Protocol: HTTP
AccessLoggingPolicy:
EmitInterval: '60'
Enabled: 'False'
S3BucketName: elb-logs
S3BucketPrefix: ELB
HealthCheck:
Target: TCP:8080
HealthyThreshold: '5'
UnhealthyThreshold: '10'
Interval: '30'
Timeout: '5'
ConnectionDrainingPolicy:
Enabled: true
Timeout: '60'
Tags:
- Key: Name
Value: ELB_Name
Outputs:
ElbDNS:
Description: ELB DNS
Value:
'Fn::GetAtt':
- ElasticLoadBalancer
- DNSName
AppServerPrivateIP:
Description: Private IP address of instance ec2instance01
Value:
'Fn::GetAtt':
- ec2instance01
- PrivateIp

It looks like you are using the CloudFormation template designer. When you use the designer, it generates a CloudFormation template for you. You can see this by selecting the Template tab towards the bottom-left of the screen. You are also given the choice of JSON or YAML.

Related

Cannot connect to EC2 via SSH | AWS Cloudformation Template

I have the following CloudFormation template that I use to create an EC2 instance in a single public subnet in a single availability zone. I have attach the internet gateway to the VPC and created ingress and egress routes to allow SSH connection to the EC2 instance.
Below is my CF template
AWSTemplateFormatVersion: "2010-09-09"
Description: "CF template for test website. v1.0.0. DEV Env"
Metadata:
Instances:
Description: "This is the dev environment architecture. Use the dev settings when setting up this environment"
Parameters:
ECommKeyPair:
Type: AWS::EC2::KeyPair::KeyName
Description: Select the dev key pair for the region
Resources:
DevEnvInternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Environment
Value: Dev
- Key: WebsiteName
Value: test
DevEnvVpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.1.1/16
EnableDnsHostnames: 'true'
EnableDnsSupport: 'true'
Tags:
- Key: Environment
Value: Dev
- Key: WebsiteName
Value: test
DevEnvVpcIgwAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId:
Ref: DevEnvVpc
InternetGatewayId:
Ref: DevEnvInternetGateway
DevEnvPublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId:
Ref: DevEnvVpc
CidrBlock: 10.0.1.1/16
AvailabilityZone: "us-west-2a"
MapPublicIpOnLaunch: 'true'
Tags:
- Key: Environment
Value: Dev
- Key: WebsiteName
Value: test
DevEnvSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow all inbound (ingress) and outbound (egress) traffic for port 22
GroupName: test-website-sec-group
VpcId:
Ref: DevEnvVpc
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
Description: allow all inbound traffic
IpProtocol: tcp
FromPort: 22
ToPort: 22
SecurityGroupEgress:
- CidrIp: 0.0.0.0/0
Description: allow all outbound traffic
IpProtocol: tcp
FromPort: 22
ToPort: 22
Tags:
- Key: Environment
Value: Dev
- Key: WebsiteName
Value: test
DevEnvRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId:
Ref: DevEnvVpc
Tags:
- Key: Environment
Value: Dev
- Key: WebsiteName
Value: test
DevEnvRoute:
Type: AWS::EC2::Route
Properties:
DestinationCidrBlock: 0.0.0.0/0
GatewayId:
Ref: DevEnvInternetGateway
RouteTableId:
Ref: DevEnvRouteTable
DevEnvEc2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
ImageId: ami-00f7e5c52c0f43726
AvailabilityZone: "us-west-2a"
KeyName:
Ref: ECommKeyPair
SecurityGroupIds:
- !GetAtt "DevEnvSecurityGroup.GroupId"
SubnetId:
Ref: DevEnvPublicSubnet
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeSize: 20
VolumeType: gp2
Tags:
- Key: Environment
Value: Dev
- Key: WebsiteName
Value: test
I am using Putty to connect to the EC2 instance with the private key file(ppk) that I associated with the EC2 instance. When tried to connect to instance with Putty, it is receiving the "Network error: Connection timed out" error message.
I even cannot connect to the instance using the AWS inbuilt "EC2 Instance Connect" through the web browser as well.
Greatly appreciate if you could point out to me the issue in my CF template.
You forgot to create AWS::EC2::SubnetRouteTableAssociation:
DevRouteAssos:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref DevEnvRouteTable
SubnetId: !Ref DevEnvPublicSubnet

AWS: Getting 502 from Application LoadBalancer to EC2 instance

I have 2 EC2 instances in 2 public subnets. The EC2 instances are fronted my an Application Load Balancer in the same public subnet as the EC2 instances. The Security groups for the EC2's is set to only accept tcp traffic from the security group the load balancer is in.
I am getting a 502 when I hit the Application Load Balancers endpoint.
I am deploying using CloudFormation. Here is the relevant bit of code.
AWSTemplateFormatVersion: "2010-09-09"
Description: Deploy a 3-tier wordpress system. (Plublic and Private subnets and DB on RDS)
Parameters:
VpcId:
Description: VPC id
Type: String
Default: vpc-0b6a616f830dd7d5a
PublicSubnetA:
Description: Subnet Id where instance will create
Type: String
Default: subnet-0616a6183bee2b276
PrivateSubnetA:
Description: Subnet Id where instance will create
Type: String
Default: subnet-06784a19612a64444
PublicSubnetB:
Description: Subnet Id where instance will create
Type: String
Default: subnet-04f7e39ac1431f22a
PrivateSubnetB:
Description: Subnet Id where instance will create
Type: String
Default: subnet-0fa6aa79eaee582bf
EC2KeyName:
Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
Type: AWS::EC2::KeyPair::KeyName
Default: test
ConstraintDescription: must be the name of an existing EC2 KeyPair.
EC2InstanceType:
Description: EC2 instance type
Type: String
Default: t2.micro
ConstraintDescription: must be a valid EC2 instance type.
WebServerInstanceAMI:
Description: EC2 instance type
Type: AWS::EC2::Image::Id
Default: ami-0210560cedcb09f07
ConstraintDescription: must be an existing AMI ID.
SSHLocation:
Description: The IP address range that can be used to SSH to the EC2 instances
Type: String
MinLength: 9
MaxLength: 18
Default: 0.0.0.0/0
AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
Application:
Description: Application Name
Type: String
AllowedPattern: "[A-Za-z0-9-]+"
Default: test
Environment:
AllowedValues: [preprod,prod]
Default: preprod
Description: The name of the Environment
Type: String
Resources:
LoadBalancerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VpcId
GroupDescription: ELB Security Group
SecurityGroupIngress:
- FromPort: 80
IpProtocol: tcp
CidrIp: 0.0.0.0/0
ToPort: 80
Description: Allow from internet
Tags:
- Key: Name
Value: !Sub '${Application}-loadbalancer-sg'
- Key: Project
Value: !Ref Application
WebServerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: 'SSH and Port 80'
VpcId:
Ref: VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref 'SSHLocation'
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId:
Ref: LoadBalancerSecurityGroup
Tags:
- Key: Name
Value: !Sub '${Application}-webserver-sg'
- Key: Project
Value: !Ref Application
LoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: ApplicationLoadBalancer
Scheme: internet-facing
Subnets:
- !Ref PublicSubnetA
- !Ref PublicSubnetB
SecurityGroups:
- !Ref LoadBalancerSecurityGroup
LoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref LoadBalancer
Port: 80
Protocol: HTTP
DefaultActions:
- Type: forward
TargetGroupArn: !Ref ApplicationTargetGroup
ApplicationTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckIntervalSeconds: 30
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 15
HealthyThresholdCount: 3
UnhealthyThresholdCount: 3
HealthCheckPath: /index.html
Matcher:
HttpCode: '200'
Name: ApplicationTargetGroup
VpcId: !Ref VpcId
Port: 80
Protocol: HTTP
TargetGroupAttributes:
- Key: deregistration_delay.timeout_seconds
Value: '20'
Targets:
- Id: !Ref WebServerInstance1
Port: 80
- Id: !Ref WebServerInstance2
Port: 80
WebServerInstance1:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref EC2InstanceType
KeyName: !Ref EC2KeyName
SubnetId: !Ref PublicSubnetA
SecurityGroupIds:
- !Ref WebServerSecurityGroup
ImageId: !Ref WebServerInstanceAMI
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
cd /tmp
sudo yum update -y
sudo yum install -y httpd
echo "Welcome from the instance 1" > /var/www/html/index.html
sudo -u root service httpd start
WebServerInstance2:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref EC2InstanceType
KeyName: !Ref EC2KeyName
SubnetId: !Ref PublicSubnetB
SecurityGroupIds:
- !Ref WebServerSecurityGroup
ImageId: !Ref WebServerInstanceAMI
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
cd /tmp
sudo yum update -y
sudo yum install -y httpd
echo "Welcome from the instance 2" > /var/www/html/index.html
sudo -u root service httpd start
Outputs:
LoadBalancerDnsName:
Description: Load Balancer public facing DNS
Export:
Name: !Sub ${AWS::StackName}-LoadBaancer
Value: !GetAtt LoadBalancer.DNSName
I have a look at the resources deployed in the console UI and I can see the correct security group rules on the EC2 instances. I don't see when the ALB would have trouble sending messages to the EC2 instances.
Question: Why am I getting a 502 error when I hit the ALBs endpoint?
I deployed your template in my VPC. The template is perfectly fine and works without any issues, including your load balancer and the website.
Thus whatever is causing your issues, is outside of this template. Probably VPC definition is incorrect, but it is not showed. You can make new question with details of your VPC setup if you want.

Resizing root volume size of ec2 instance with cloudformation

I have an instance created with cloudformation like below:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref ServerAMI
InstanceType: !Ref ServerInstanceType
KeyName: !Ref KeyName
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeSize: 30
NetworkInterfaces:
- AssociatePublicIpAddress: 'false'
DeleteOnTermination: 'true'
DeviceIndex: '0'
GroupSet:
- Ref: ServerSecurityGroup
SubnetId: !Ref SubnetID
Tags:
- { Key: Name, Value: !Ref AWS::StackName }
My root volume in this case is created at 30GB. If I try increase this root volume size by setting the VolumeSize value then my ec2 instance is terminated and recreated.
Yet in the console I am able to increase the size of my root volume without recreation of my instance.
Is there any work around for this in order to prevent ec2 instance from being terminated when trying to increase root volume size via cloudformation?
Edit:
Here is a small test stack I'm using to test this again. Deployed once, then change VolumeSize and redeploy - it wants to replace the instance:
AWSTemplateFormatVersion: '2010-09-09'
Description: Test stack for a single ec2 instance
Parameters:
ServerAMI:
Type: String
Default: ami-096f43ef67d75e998
ServerInstanceType:
Type: String
Default: t2.small
DefaultVPCID:
Type: String
SubnetID:
Type: String
KeyName:
Type: AWS::EC2::KeyPair::KeyName
Resources:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref ServerAMI
InstanceType: !Ref ServerInstanceType
KeyName: !Ref KeyName
BlockDeviceMappings:
- DeviceName: /dev/xvda #Linux
Ebs:
VolumeSize: 30
NetworkInterfaces:
- AssociatePublicIpAddress: 'false'
DeleteOnTermination: 'true'
DeviceIndex: '0'
GroupSet:
- Ref: ServerSecurityGroup
SubnetId: !Ref SubnetID
Tags:
- { Key: Name, Value: !Ref AWS::StackName }
ServerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Webserver security group
VpcId: !Ref DefaultVPCID
SecurityGroupIngress:
- { IpProtocol: tcp, FromPort: '22', ToPort: '22', CidrIp: '127.0.0.1/32', Description: 'Test Instance' }
Unfortunately, I don't believe you can - per the CloudFormation documentation:
After the instance is running, you can modify only the DeleteOnTermination parameter for the attached volumes without interrupting the instance. Modifying any other parameter results in instance replacement.

How to use existing VPC in AWS CloudFormation template for new SecurityGroup

I am trying to EC2 instance (new), Security group (new) and VPC(existing). Here is my cloudformation template.
When I run the template in Stack, I got error as *"Value () for parameter groupId is invalid. The value cannot be empty"*. How to solve this?
Template:
Parameters:
VPCID:
Description: Name of an existing VPC
Type: AWS::EC2::VPC::Id
KeyName:
Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
Type: AWS::EC2::KeyPair::KeyName
ConstraintDescription: must be the name of an existing EC2 KeyPair.
InstanceType:
Description: EC2 instance type
Type: String
Default: t2.medium
AllowedValues:
- t2.medium
- t2.large
AccessLocation:
Description: The IP address range that can be used to access to the EC2 instances
Type: String
Resources:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref 'InstanceType'
SecurityGroups:
- !Ref 'InstanceSecurityGroup'
KeyName: !Ref 'KeyName'
ImageId: !Ref 'ImageId'
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPCID
GroupDescription: Enable SSH
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: !Ref 'AccessLocation'
SecurityGroups can only be used for default VPC. Since you are explicitly assigning VPCID to InstanceSecurityGroup, this will be considered as non-default, resulting in failed deployment.
You must use SecurityGroupIds (not SecurityGroups) in your case as your VPC use will be considered as non-default:
SecurityGroupIds:
- !GetAtt 'InstanceSecurityGroup.GroupId'
The error in EC2Instance resource in SecurityGroups attribute. SecurityGroups needs an array of GroupId but when you use !Ref InstanceSecurityGroup this returns ResourceId. So you need to use GetAtt instead to get GroupId.
Parameters:
VPCID:
Description: Name of an existing VPC
Type: AWS::EC2::VPC::Id
KeyName:
Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
Type: AWS::EC2::KeyPair::KeyName
ConstraintDescription: must be the name of an existing EC2 KeyPair.
InstanceType:
Description: EC2 instance type
Type: String
Default: t2.medium
AllowedValues:
- t2.medium
- t2.large
AccessLocation:
Description: The IP address range that can be used to access to the EC2 instances
Type: String
Resources:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref 'InstanceType'
SecurityGroups:
- !GetAtt InstanceSecurityGroup.GroupId
KeyName: !Ref 'KeyName'
ImageId: !Ref 'ImageId'
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPCID
GroupDescription: Enable SSH
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: !Ref 'AccessLocation'
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html

Assign private IP only with CloudFormation

I'm using CloudFormation to create an EC2 instance. What I am trying to achieve is only assign a private IP. No public IP. Everything gets created fine and it creates a DNS entry for the private IP, but it also creates a public IP. How can I tell it to not create a public IP. Here is my template. The vpc_id and subnet_id is on a private network.
AWSTemplateFormatVersion: '2010-09-09'
Description: 'AWS CloudFormation template for creating riskInternalElk instance with DNS record'
Parameters:
Resources:
InstanceSecurityGroup:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupName: "{{security_group_name}}"
GroupDescription: "{{security_group_name}}"
VpcId: "{{vpc_id}}"
SecurityGroupIngress:
{% for item in security_group_ingress %}
- IpProtocol: "{{item.protocol}}"
FromPort: "{{item.from_port}}"
ToPort: "{{item.to_port}}"
CidrIp: "{{item.cidr_ip}}"
{% endfor %}
NetworkInterface:
Type: AWS::EC2::NetworkInterface
Properties:
SubnetId: "{{subnet_id}}"
Description: "{{subnet_description}}"
GroupSet:
- !Ref InstanceSecurityGroup
SourceDestCheck: true
Tags:
- Key: Network
Value: Web
EC2Instance:
Type: AWS::EC2::Instance
Properties:
Tags:
- Key: "Name"
Value: "{{instance_name}}"
ImageId: "{{image_id}}"
InstanceType: "{{instance_type}}"
KeyName: "{{key_name}}"
NetworkInterfaces:
- NetworkInterfaceId: !Ref NetworkInterface
DeviceIndex: 1
BlockDeviceMappings:
- DeviceName: "{{device_name}}"
Ebs:
VolumeType: "gp2"
VolumeSize: "{{volume_size}}"
Encrypted: true
DeleteOnTermination: false
DnsRecord:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneName: "{{hosted_zone_name}}"
Comment: "DNS name for risk internal ec2 instance."
Name: "{{host_name}}"
Type: A
TTL: '60'
ResourceRecords:
- !GetAtt EC2Instance.PrivateIp
You can specify the information in the EC2:Instance resource set for the NetworkInterfaces differently to have it deviate from the subnets setting for assigning a public IP.
Specifically set the AssociatePublicIpAddress to "False" and move your NetworkInterface resource to be in-line like this:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
Tags:
- Key: "Name"
Value: "{{instance_name}}"
ImageId: "{{image_id}}"
InstanceType: "{{instance_type}}"
KeyName: "{{key_name}}"
NetworkInterfaces:
- AssociatePublicIpAddress: false <--- This should do it
DeleteOnTermination: false
DeviceIndex: 0
SubnetId: "{{subnet_id}}"
Description: "{{subnet_description}}"
GroupSet:
- !Ref InstanceSecurityGroup
SourceDestCheck: true
BlockDeviceMappings:
- DeviceName: "{{device_name}}"
Ebs:
VolumeType: "gp2"
VolumeSize: "{{volume_size}}"
Encrypted: true
DeleteOnTermination: false
You control the assignment of public IP addresses to EC2 instances thru the subnet configuration. The subnet defines MapPublicIpOnLaunch. This also means that the subnet must be part of your cloudformation stack.
If you are using Auto Scaling, then you have the option AssociatePublicIpAddress in AWS::AutoScaling::LaunchConfiguration
AWS::EC2::Subnet
AWS::AutoScaling::LaunchConfiguration
Check the Subnet for the setting, "Auto-assign public IPv4 address".
Change it by going to the VPC Console and selecting the Subnet-->Actions-->"Modify auto-assign IP settings".