Creating an EC2 instance
Introduction
In this post I shall demonstrate how easy it is to create an EC2 instance, and a security group within an existing AWS VPC.
Python examples follow.
Initialize project
mkdir ec2-instance-demo
cd ec2-instance-demo
cdk init --language python
Activate virtual env
source .env/bin/activate
Install dependencies
pip install -r requirements.txt
List stacks
cdk ls
ec2-instance
Stack file
ec2_instance_stack.py
(located inside the ec2_instance
directory)
-
Import the required packages
aws_ec2
-
Define an existing VPC using id
vpcID
-
Define a new security group
sec_group
-
Define the name to assign to the EC2 instance
instanceName
-
Define the type of instance to use
instanceType
-
Define the name of the AMI to assign to the instance
amiName
from aws_cdk import (
core,
aws_ec2 as ec2,
)
vpcID="<VPC-ID>"
instanceName="webserver-1"
instanceType="t2.micro"
amiName="amzn2-ami-hvm-2.0.20200520.1-x86_64-gp2"
class Ec2InstanceStack(core.Stack):
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
# The code that defines your stack goes here
# lookup existing VPC
vpc = ec2.Vpc.from_lookup(
self,
"vpc",
vpc_id=vpcID,
)
# create a new security group
sec_group = ec2.SecurityGroup(
self,
"sec-group-allow-ssh",
vpc=vpc,
allow_all_outbound=True,
)
# add a new ingress rule to allow port 22 to internal hosts
sec_group.add_ingress_rule(
peer=ec2.Peer.ipv4('10.0.0.0/16'),
description="Allow SSH connection",
connection=ec2.Port.tcp(22)
)
# define a new ec2 instance
ec2_instance = ec2.Instance(
self,
"ec2-instance",
instance_name=instanceName,
instance_type=ec2.InstanceType(instanceType),
machine_image=ec2.MachineImage().lookup(name=amiName),
vpc=vpc,
security_group=sec_group,
)
CDK operations
Verify changes
Run a cdk diff
to see what changes will be applied in AWS.
cdk diff
jsii.errors.JavaScriptError:
Error: Cannot retrieve value from context provider vpc-provider since account/region are not specified at the stack level. Either configure "env" with explicit account and region when you define your stack, or use the environment variables "CDK_DEFAULT_ACCOUNT" and "CDK_DEFAULT_REGION" to inherit environment information from the CLI (not recommended for production stacks)
Solving the error message
As the error message implies CDK is looking for the account and region information.
It could not find the information in the environment variables: CDK_DEFAULT_ACCOUNT
and CDK_DEFAULT-REGION
.
We could set these environment variables and that would be fine for development purposes; but CDK does highlight that this is not recommended for production stacks.
So, the alternative fix here is to set the information inside the app.py
The app.py
file requires fine tuning to point to a specific AWS region and AWS account.
The boilerplate file does not contain this information, and this is required in order to create an EC2 instance using the CDK.
#!/usr/bin/env python3
from aws_cdk import core
from ec2_instance.ec2_instance_stack import Ec2InstanceStack
app = core.App()
env = core.Environment(region="<region>",account="<account-id>")
Ec2InstanceStack(app, "ec2-instance",env=env)
app.synth()
Here you define the env
variable to point to a region
and use account
The env
is then passed into the stack Ec2InstanceStack
Notice that at the end of the file app.synth()
.
This synthesizes the code written using the AWS CDK framework into a cloud assembly, i.e. into a CloudFormation template.
By default the CloudFormation template lives in the project directory under cdk.out
Now, run cdk diff
again.
cdk diff
Stack ec2-instance
IAM Statement Changes
┌───┬──────────────────────────────────┬────────┬────────────────┬───────────────────────────┬───────────┐
│ │ Resource │ Effect │ Action │ Principal │ Condition │
├───┼──────────────────────────────────┼────────┼────────────────┼───────────────────────────┼───────────┤
│ + │ ${ec2-instance/InstanceRole.Arn} │ Allow │ sts:AssumeRole │ Service:ec2.amazonaws.com │ │
└───┴──────────────────────────────────┴────────┴────────────────┴───────────────────────────┴───────────┘
Security Group Changes
┌───┬──────────────────────┬─────┬────────────┬─────────────────┐
│ │ Group │ Dir │ Protocol │ Peer │
├───┼──────────────────────┼─────┼────────────┼─────────────────┤
│ + │ ${sec-group.GroupId} │ In │ TCP 22 │ 10.0.0.0/16 │
│ + │ ${sec-group.GroupId} │ Out │ Everything │ Everyone (IPv4) │
└───┴──────────────────────┴─────┴────────────┴─────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)
Resources
[+] AWS::EC2::SecurityGroup sec-group secgroup81B6576A
[+] AWS::IAM::Role ec2-instance/InstanceRole ec2instanceInstanceRoleCA97C688
[+] AWS::IAM::InstanceProfile ec2-instance/InstanceProfile ec2instanceInstanceProfile9BCE9015
[+] AWS::EC2::Instance ec2-instance ec2instance42082E81
Changes:
- New security group (x1)
- New IAM roles (x2)
- New EC2 instance (x1)
Synth
Run cdk synth
to see the CloudFormation template generated from the code written in CDK.
Deploy
Now, run a cdk deploy
.
Accept the changes when you are ready to deploy.
The provisioning of cloud infrastructure is carried out via CloudFormation.
cdk deploy
This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening).
Please confirm you intend to make the following modifications:
IAM Statement Changes
┌───┬──────────────────────────────────┬────────┬────────────────┬───────────────────────────┬───────────┐
│ │ Resource │ Effect │ Action │ Principal │ Condition │
├───┼──────────────────────────────────┼────────┼────────────────┼───────────────────────────┼───────────┤
│ + │ ${ec2-instance/InstanceRole.Arn} │ Allow │ sts:AssumeRole │ Service:ec2.amazonaws.com │ │
└───┴──────────────────────────────────┴────────┴────────────────┴───────────────────────────┴───────────┘
Security Group Changes
┌───┬──────────────────────┬─────┬────────────┬─────────────────┐
│ │ Group │ Dir │ Protocol │ Peer │
├───┼──────────────────────┼─────┼────────────┼─────────────────┤
│ + │ ${sec-group.GroupId} │ In │ TCP 22 │ 10.0.0.0/16 │
│ + │ ${sec-group.GroupId} │ Out │ Everything │ Everyone (IPv4) │
└───┴──────────────────────┴─────┴────────────┴─────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)
Do you wish to deploy these changes (y/n)? y
Monitor the output to check the progress.
Once finished, head over to the AWS management console, too see the new infrastructure components deployed.
Destroy
You can remove the deployed components via cdk destroy
Are you sure you want to delete: ec2-instance (y/n)? y
ec2-instance: destroying...
...
✅ ec2-instance: destroyed