How to launch an EC2 instance in an existing VPC using CloudFormation

How to launch an EC2 instance in an existing VPC using CloudFormation
Sharing is Caring:

Launch an EC2 instance in an existing VPC using CloudFormation

In this post, I will help you launch an EC2 instance in an existing VPC using CloudFormation. I will also share the template in YAML as well as JSON for your convenience.

Prerequisite

  • An AWS Account
  • Basic Knowledge of EC2 and CloudFormation
  • Basic Knowledge of YAML/JSON

To be honest, I have seen many people asking this question on various online forums.

There is so much confusion around launching an EC2 in a VPC. And confusion is so obvious specially for beginners. So why not start with the confusion itself. 🙂

Why Confusion?

Well, If you have launched an EC2 instance from AWS EC2 console. You might remember that, In network we get to select a VPC and then subnet in the VPC in which you would like to launch the instance.

However, there is no VPC or VpcId parameter for AWS::EC2::Instance resource in CloudFormation.

You might wonder, How do we create an instance in a VPC then ?

Don’t worry It’s simple.

SubnetId represents a VPC when creating an EC2 instance using Cloud Formation. Therefore need to specify SubnetId parameter to launch the instance in VPC.

What’s even more confusing?

There are two places where SubnetId can be specified in a AWS::EC2::Instance resource.

  1. On Instance Level
  2. On Network Interface level

Let’s understand by an example for each one of these.

Instance Level SubnetId in an AWS::EC2::Instance resource

  DemoInstance:
    Type: 'AWS::EC2::Instance'
    Properties: 
      ImageId: !Ref ImageId
      InstanceType: !Ref InstanceType
      AvailabilityZone: !Ref AvailabilityZone
      KeyName: !Ref KeyName
      SecurityGroupIds: 
        - !Ref DemoSecurityGroup
      SubnetId: !Ref SubnetId

or

Network Interface Level SubnetId in an AWS::EC2::Instance resource

  DemoInstance:
    Type: 'AWS::EC2::Instance'
    Properties: 
      ImageId: !Ref ImageId
      InstanceType: !Ref InstanceType
      AvailabilityZone: !Ref AvailabilityZone
      KeyName: !Ref KeyName
      NetworkInterfaces:
        - DeviceIndex: 0
          AssociatePublicIpAddress: true
          DeleteOnTermination: true
          SubnetId: !Ref SubnetId
          GroupSet: 
            - !Ref DemoSecurityGroup

Where to specify SubnetId?

Have you got the requirement to attach a network interface to your instance?

Yes? -> Use SubnetId on interface level

No? -> Use SubnetId on instance level

Please note that, only one out of two can be specified. If you try to use SubnetId on instance level as well as network interface level. You will get below error.

Network interfaces and an instance-level subnet ID may not be specified on the same request (Service: AmazonEC2; Status Code: 400; Error Code: InvalidParameterCombination)

Same applies to security group.

  • Using Network Interface -> Use GroupSet parameter on network interface level
  • Not using Network Interface -> Use SecurityGroupIds parameter on instance level

If you try to use at both the places, you will get error like

Network interfaces and an instance-level security groups may not be specified on the same request (Service: AmazonEC2; Status Code: 400)

Don’t worry much. I am going to share fully working template for both the cases below.

Template to Launch an EC2 instance in an existing VPC using CloudFormation : YAML

Please note that as we discussed above, we will be having two template here.

  1. Without Network Interface
  2. With Network Interface

Without Network Interface:

AWSTemplateFormatVersion: '2010-09-09'
Description: Template to Create an EC2 instance in a VPC
   
Parameters:

  ImageId:
    Type: String
    Description: 'Linux 2 AMI for Ireland eu-west1 Region'
    Default: 'ami-0fc970315c2d38f01'
  VpcId:
    Type: String
    Description: VPC id
    Default: vpc-012b3456f0123456f4
  SubnetId:
    Type: String
    Description: Subnet in which to launch an EC2
    Default: subnet-0123ec12fd9af123b
  AvailabilityZone:
    Type: String
    Description: Availability Zone into which instance will launch
    Default: eu-west-1c
  InstanceType:
    Type: String
    Description: Choosing  t2 micro because it is free
    Default: t2.micro
  KeyName:
    Description: SSH Keypair to login to the instance
    Type: AWS::EC2::KeyPair::KeyName
    Default: demokeypair

Resources:
  DemoInstance:
    Type: 'AWS::EC2::Instance'
    Properties: 
      ImageId: !Ref ImageId
      InstanceType: !Ref InstanceType
      AvailabilityZone: !Ref AvailabilityZone
      KeyName: !Ref KeyName
      SecurityGroupIds: 
        - !Ref DemoSecurityGroup
      SubnetId: !Ref SubnetId

  DemoSecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      VpcId: !Ref VpcId
      GroupDescription: SG to allow SSH access via port 22
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIp: '0.0.0.0/0'
      Tags:
        - Key: Name
          Value: SSH-SG

Outputs:
  DemoInstanceId:
    Description: Instance Id 
    Value: !Ref DemoInstance

With Network Interface:

AWSTemplateFormatVersion: '2010-09-09'
Description: Template to Create an EC2 instance in a VPC
   
Parameters:

  ImageId:
    Type: String
    Description: 'Linux 2 AMI for Ireland eu-west1 Region'
    Default: 'ami-0fc970315c2d38f01'
  VpcId:
    Type: String
    Description: VPC id
    Default: vpc-012b3456f0123456f4
  SubnetId:
    Type: String
    Description: Subnet in which to launch an EC2
    Default: subnet-0123ec12fd9af123b
  AvailabilityZone:
    Type: String
    Description: Availability Zone into which instance will launch
    Default: eu-west-1c
  InstanceType:
    Type: String
    Description: Choosing  t2 micro because it is free
    Default: t2.micro
  KeyName:
    Description: SSH Keypair to login to the instance
    Type: AWS::EC2::KeyPair::KeyName
    Default: demokeypair

Resources:
  DemoInstance:
    Type: 'AWS::EC2::Instance'
    Properties: 
      ImageId: !Ref ImageId
      InstanceType: !Ref InstanceType
      AvailabilityZone: !Ref AvailabilityZone
      KeyName: !Ref KeyName
      NetworkInterfaces:
        - DeviceIndex: 0
          AssociatePublicIpAddress: true
          DeleteOnTermination: true
          SubnetId: !Ref SubnetId
          GroupSet: 
            - !Ref DemoSecurityGroup

  DemoSecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      VpcId: !Ref VpcId
      GroupDescription: SG to allow SSH access via port 22
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIp: '0.0.0.0/0'
      Tags:
        - Key: Name
          Value: SSH-SG

Outputs:
  DemoInstanceId:
    Description: Instance Id 
    Value: !Ref DemoInstance

Template to Launch an EC2 instance in an existing VPC using Cloud Formation : JSON

Same as YAML here also we have two template.

Without Network Interface:

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "Template to Create an EC2 instance in a VPC",
    "Parameters": {
        "ImageId": {
            "Type": "String",
            "Description": "Linux 2 AMI for Ireland eu-west1 Region",
            "Default": "ami-0fc970315c2d38f01"
        },
        "VpcId": {
            "Type": "String",
            "Description": "VPC id",
            "Default": "vpc-012b3456f0123456f4"
        },
        "SubnetId": {
            "Type": "String",
            "Description": "Subnet in which to launch an EC2",
            "Default": "subnet-0123ec12fd9af123b"
        },
        "AvailabilityZone": {
            "Type": "String",
            "Description": "Availability Zone into which instance will launch",
            "Default": "eu-west-1c"
        },
        "InstanceType": {
            "Type": "String",
            "Description": "Choosing  t2 micro because it is free",
            "Default": "t2.micro"
        },
        "KeyName": {
            "Description": "SSH Keypair to login to the instance",
            "Type": "AWS::EC2::KeyPair::KeyName",
            "Default": "demokeypair"
        }
    },
    "Resources": {
        "DemoInstance": {
            "Type": "AWS::EC2::Instance",
            "Properties": {
                "ImageId": {
                    "Ref": "ImageId"
                },
                "InstanceType": {
                    "Ref": "InstanceType"
                },
                "AvailabilityZone": {
                    "Ref": "AvailabilityZone"
                },
                "KeyName": {
                    "Ref": "KeyName"
                },
                "SecurityGroupIds": [
                    {
                        "Ref": "DemoSecurityGroup"
                    }
                ],
                "SubnetId": {
                    "Ref": "SubnetId"
                }
            }
        },
        "DemoSecurityGroup": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "VpcId": {
                    "Ref": "VpcId"
                },
                "GroupDescription": "SG to allow SSH access via port 22",
                "SecurityGroupIngress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": "22",
                        "ToPort": "22",
                        "CidrIp": "0.0.0.0/0"
                    }
                ],
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "SSH-SG"
                    }
                ]
            }
        }
    },
    "Outputs": {
        "DemoInstanceId": {
            "Description": "Instance Id",
            "Value": {
                "Ref": "DemoInstance"
            }
        }
    }
}

With Network Interface:

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "Template to Create an EC2 instance in a VPC",
    "Parameters": {
        "ImageId": {
            "Type": "String",
            "Description": "Linux 2 AMI for Ireland eu-west1 Region",
            "Default": "ami-0fc970315c2d38f01"
        },
        "VpcId": {
            "Type": "String",
            "Description": "VPC id",
            "Default": "vpc-012b3456f0123456f4"
        },
        "SubnetId": {
            "Type": "String",
            "Description": "Subnet in which to launch an EC2",
            "Default": "subnet-0123ec12fd9af123b"
        },
        "AvailabilityZone": {
            "Type": "String",
            "Description": "Availability Zone into which instance will launch",
            "Default": "eu-west-1c"
        },
        "InstanceType": {
            "Type": "String",
            "Description": "Choosing  t2 micro because it is free",
            "Default": "t2.micro"
        },
        "KeyName": {
            "Description": "SSH Keypair to login to the instance",
            "Type": "AWS::EC2::KeyPair::KeyName",
            "Default": "demokeypair"
        }
    },
    "Resources": {
        "DemoInstance": {
            "Type": "AWS::EC2::Instance",
            "Properties": {
                "ImageId": {
                    "Ref": "ImageId"
                },
                "InstanceType": {
                    "Ref": "InstanceType"
                },
                "AvailabilityZone": {
                    "Ref": "AvailabilityZone"
                },
                "KeyName": {
                    "Ref": "KeyName"
                },
                "NetworkInterfaces": [
                    {
                        "DeviceIndex": 0,
                        "AssociatePublicIpAddress": true,
                        "DeleteOnTermination": true,
                        "SubnetId": {
                            "Ref": "SubnetId"
                        },
                        "GroupSet": [
                            {
                                "Ref": "DemoSecurityGroup"
                            }
                        ]
                    }
                ]
            }
        },
        "DemoSecurityGroup": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "VpcId": {
                    "Ref": "VpcId"
                },
                "GroupDescription": "SG to allow SSH access via port 22",
                "SecurityGroupIngress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": "22",
                        "ToPort": "22",
                        "CidrIp": "0.0.0.0/0"
                    }
                ],
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "SSH-SG"
                    }
                ]
            }
        }
    },
    "Outputs": {
        "DemoInstanceId": {
            "Description": "Instance Id",
            "Value": {
                "Ref": "DemoInstance"
            }
        }
    }
}

Steps to Create a Stack

Once you have got your required template from above. Change the parameter value such as SubnetId, VpcId etc. as per your requirement.Save the it with .yml or .json as per the template and follow below steps.

  • Login to AWS Management Console, navigate to CloudFormation and click on Create stack
  • Click on “Upload a template file”, upload ec2instance.yml  or ec2instance.json and click Next
  • Enter the stack name and click on Next. In configuration, keep everything as default and click on Next.
  • In the events tab of stack, you can view the status.
  • Once stack is successfully created, go to Resources tab(Right next to Event) and click on your instance resource.
  • It will take you to your instance. You can verify all the details there.
launch an ec2 instance in an existing vpc

Conclusion

Let’s sum up what we did in this post.

  • We discussed why launching an EC2 instance in a VPC becomes confusing at times
  • We also saw how to correctly create an EC2 instance in VPC
  • Finally, I shared a working template in YAML as well as JSON

I hope you found this post helpful.

Enjoyed the content?

Subscribe to our newsletter below to get awesome AWS learning materials delivered straight to your inbox.

Subscribe to our newsletter below to get awesome AWS learning materials delivered straight to your inbox.

Don’t forget to motivate me by-

  • Adding a comment below on what you liked and what can be improved.
  • Follow us on
  • Subscribe to our newsletter to get notified each time we post new content
  • Share this post with your friends

Suggested Read:

Sharing is Caring:

2 thoughts on “How to launch an EC2 instance in an existing VPC using CloudFormation

  1. Thanks for a great template! I appreciated information on launching EC2 instance with existing VPC. I see a lot of templates where it’s being launched with a new VPC (nothing wrong with that).

    Keep up the great work and hope to see more!

Leave a Reply

Your email address will not be published. Required fields are marked *