Introduction
Amazon EC2 (Elastic Compute Cloud) is one of AWS’s core and most popular services, providing virtual servers (called Instances) that can scale flexibly in the cloud.
Simply put, instead of purchasing and maintaining physical hardware, EC2 allows you to “rent” computers with customizable configurations (CPU, RAM, storage, operating system) within minutes.
Key features
- Elasticity: You can instantly increase or decrease the number of servers to handle traffic, helping optimize performance.
- Flexible pricing: Uses a “Pay-as-you-go” model (pay only for what you use), reducing initial infrastructure investment costs.
- Full control: You get root access to each instance and can manage them like traditional physical servers.
- High reliability: EC2 runs on Amazon’s global infrastructure, ensuring high availability and strong security.
With EC2, developers can easily deploy everything from simple web applications and database systems to complex machine learning models quickly and efficiently.
Detail
Continue using AWS CDK. First, create a file lib/base-stack.ts to act as a parent class that receives shared config information from the .env file for all stacks:
import * as cdk from "aws-cdk-lib"
import { Construct } from "constructs"
export class BaseStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, {
...props,
env: {
region: process.env.CDK_REGION || process.env.CDK_DEFAULT_REGION,
},
})
}
}
Since this guide also includes instructions for creating an EC2 instance and connecting via SSH, you first need to create a key pair as follows:
aws ec2 create-key-pair --key-name {key name} --query 'KeyMaterial' --output text > {key name}.pem
# example
aws ec2 create-key-pair --key-name new-key-pair --query 'KeyMaterial' --output text > new-key-pair.pem
After execution, a file named new-key-pair.pem will be created.
Next, create the file lib/ec2-free-tier-stack.ts:
import * as cdk from "aws-cdk-lib"
import * as ec2 from "aws-cdk-lib/aws-ec2"
import * as iam from "aws-cdk-lib/aws-iam"
import { Construct } from "constructs"
import { BaseStack } from "../base-stack"
export class Ec2FreeTierStack extends BaseStack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props)
const keyPairName = "new-key-pair"
const keyPair = ec2.KeyPair.fromKeyPairName(this, "KeyPair", keyPairName)
const vpc = new ec2.Vpc(this, "NewVPC", {
maxAzs: 1,
natGateways: 0,
subnetConfiguration: [
{
name: "PublicSubnet",
subnetType: ec2.SubnetType.PUBLIC,
},
],
})
const role = new iam.Role(this, "Ec2Role", {
assumedBy: new iam.ServicePrincipal("ec2.amazonaws.com"),
})
role.addManagedPolicy(
iam.ManagedPolicy.fromAwsManagedPolicyName(
"AmazonSSMManagedInstanceCore",
),
)
const securityGroup = new ec2.SecurityGroup(this, "Ec2SG", {
vpc,
description: "Allow SSH and HTTP",
allowAllOutbound: true,
})
securityGroup.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.tcp(22),
"Allow SSH from anywhere",
)
const instance = new ec2.Instance(this, "FreeTierInstance", {
vpc,
instanceType: ec2.InstanceType.of(
ec2.InstanceClass.T2,
ec2.InstanceSize.MICRO,
),
machineImage: ec2.MachineImage.latestAmazonLinux2023(),
securityGroup,
role,
keyPair,
blockDevices: [
{
deviceName: "/dev/xvda",
volume: ec2.BlockDeviceVolume.ebs(30, {
volumeType: ec2.EbsDeviceVolumeType.GP3,
}),
},
],
})
new cdk.CfnOutput(this, "Instance ID", {
value: instance.instanceId,
})
new cdk.CfnOutput(this, "SSH-Command", {
value: `ssh -i ${keyPairName}.pem ec2-user@${instance.instancePublicIp}`,
})
}
}
- keyPairName: the name of the key pair you created earlier.
- natGateways: 0: note that a NAT Gateway is not needed here because it incurs charges.
- A role is created because the guide will include instructions for connecting with SSM (System Session Manager).
- securityGroup.addIngressRule: opens port 22 for SSH access.
- As you can see, I created a t2.micro instance using Linux with a 30GB volume.
Create the file bin/aws-cdk.ts and deploy the stack:
#!/usr/bin/env node
import * as cdk from "aws-cdk-lib/core"
import { Ec2FreeTierStack } from "../lib/ec2/ec2-free-tier-stack"
const app = new cdk.App()
new Ec2FreeTierStack(app, "Ec2FreeTierStack")
The resources will be created as follows:
✅ Ec2FreeTierStack
✨ Deployment time: 93.03s
Outputs:
Ec2FreeTierStack.InstanceID = i-678fb5d123dee498b
Ec2FreeTierStack.SSHCommand = ssh -i new-key-pair.pem ec2-user@12.654.119.70
✨ Total time: 113.42s
Connecting to EC2
Method 1
The simplest way to connect to a running EC2 instance (if you have an AWS account with access permissions) is via the AWS Console.
Go to EC2 Dashboard → Instances (running) → Select an instance → Click Connect.
Method 2
Connect via SSM (System Session Manager)
This method requires an AWS account with AWS access keys or a configured profile.
You also need to install the Session Manager Plugin here (depending on your OS)
Then connect like this:
aws ssm start-session --target {Instance ID}
# example
$ aws ssm start-session --target i-678fb5d123dee498b
Starting session with SessionId: user1-aqvauixf8g7nbp445pr2izx9hi
sh-5.2$ whoami
ssm-user
sh-5.2$ echo Hello
Hello
Use the instance ID generated after successfully deploying the stack.
Method 3
Use SSH (Secure Shell)
This method is not recommended because it is less secure than the two methods above. However, it may be necessary if you need to connect to an EC2 instance without having an account with direct access — in that case, you only need the .pem file.
Before connecting, you need to set the proper permissions for the .pem file depending on your OS.
Then connect using the command output after a successful CDK deployment:
ssh -i {keypair file}.pem ec2-user@{ip address}
# example
$ ssh -i new-key-pair.pem ec2-user@12.654.119.70
, #_
~\_ ####_ Amazon Linux 2023
~~ \_#####\
~~ \###|
~~ \#/ ___ https://aws.amazon.com/linux/amazon-linux-2023
~~ V~' '->
~~~ /
~~._. _/
_/ _/
_/m/'
[ec2-user@ip-10-0-7-50 ~]$ echo Hello
Hello
Happy coding!
See more articles here.
Comments
Post a Comment