Create an AWS EC2 instance with the AWS CLI - Step 1 - Launch Instance
Make sure you do this setup first:
Steps:
- Launch an AWS EC2 instance (this post)
- Attach an instance role to allow S3 access
- Cleanup
Scripts are
bash
Setup
Names
Assign resource names:
# VPC
vpc="vpc-ec2"
# Subnets
subnet_1="subnet-ec2-1"
subnet_2="subnet-ec2-2"
# Internet Gateway
internet_gateway="igw-ec2"
# Route Table
route_table="rtb-ec2"
# Security Group
security_group="security-ec2"
# instance
instance="instance-ec2"
# SSH access key
key="aws-ec2-key"
VPC
Create a VPC (Virtual Private Cloud):
aws ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value='$vpc'}]'
Subnets
Create 2 subnets:
vpc_id=$(aws ec2 describe-vpcs --filters Name=tag:Name,Values=$vpc | jq -r '.Vpcs[0].VpcId')
# 1st subnet
aws ec2 create-subnet \
--vpc-id $vpc_id \
--cidr-block 10.0.0.0/24 \
--availability-zone us-west-2a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value='$subnet_1'}]'
# 2nd subnet
aws ec2 create-subnet \
--vpc-id $vpc_id \
--cidr-block 10.0.1.0/24 \
--availability-zone us-west-2a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value='$subnet_2'}]'
Optionally modify the public IP addressing behavior of your subnet so that an instance launched into the subnet automatically receives a public IP address. Otherwise, you should associate an Elastic IP address with your instance after launch so that it's reachable from the Internet.
subnet_id=$(aws ec2 describe-subnets --filters Name=tag:Name,Values=$subnet_1 | jq -r '.Subnets[0].SubnetId')
aws ec2 modify-subnet-attribute --subnet-id $subnet_id --map-public-ip-on-launch
Internet Gateway
After you've created the VPC and subnets, you can make one of the subnets a public subnet by attaching an Internet gateway to your VPC, creating a custom route table, and configuring routing for the subnet to the Internet gateway.
Create
aws ec2 create-internet-gateway \
--tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value='$internet_gateway'}]'
Attach to VPC
vpc_id=$(aws ec2 describe-vpcs --filters Name=tag:Name,Values=$vpc | jq -r '.Vpcs[0].VpcId')
internet_gateway_id=$(aws ec2 describe-internet-gateways --filters Name=tag:Name,Values=$internet_gateway | jq -r '.InternetGateways[0].InternetGatewayId')
aws ec2 attach-internet-gateway --vpc-id $vpc_id --internet-gateway-id $internet_gateway_id
Route Table
Create:
vpc_id=$(aws ec2 describe-vpcs --filters Name=tag:Name,Values=$vpc | jq -r '.Vpcs[0].VpcId')
aws ec2 create-route-table \
--vpc-id $vpc_id \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value='$route_table'}]'
Associate with a subnet:
# 1st subnet
subnet_id=$(aws ec2 describe-subnets --filters Name=tag:Name,Values=$subnet_1 | jq -r '.Subnets[0].SubnetId')
route_table_id=$(aws ec2 describe-route-tables --filters Name=tag:Name,Values=$route_table | jq -r '.RouteTables[0].RouteTableId')
aws ec2 associate-route-table --subnet-id $subnet_id --route-table-id $route_table_id
Create a route in the route table that points all traffic (0.0.0.0/0
) to the Internet gateway:
route_table_id=$(aws ec2 describe-route-tables --filters Name=tag:Name,Values=$route_table | jq -r '.RouteTables[0].RouteTableId')
internet_gateway_id=$(aws ec2 describe-internet-gateways --filters Name=tag:Name,Values=$internet_gateway | jq -r '.InternetGateways[0].InternetGatewayId')
aws ec2 create-route \
--route-table-id $route_table_id \
--gateway-id $internet_gateway_id \
--destination-cidr-block 0.0.0.0/0
Confirm route is active:
route_table_id=$(aws ec2 describe-route-tables --filters Name=tag:Name,Values=$route_table | jq -r '.RouteTables[0].RouteTableId')
aws ec2 describe-route-tables --route-table-id $route_table_id
Security Group
Create a security group in your VPC:
vpc_id=$(aws ec2 describe-vpcs --filters Name=tag:Name,Values=$vpc | jq -r '.Vpcs[0].VpcId')
aws ec2 create-security-group \
--group-name $security_group \
--description "Security group for instance access" \
--vpc-id $vpc_id \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value='$security_group'}]'
Add a rule that allows SSH access from anywhere:
group_id=$(aws ec2 describe-security-groups --filters Name=tag:Name,Values=$security_group | jq -r '.SecurityGroups[0].GroupId')
aws ec2 authorize-security-group-ingress \
--group-id $group_id \
--protocol tcp --port 22 --cidr 0.0.0.0/0
EC2 Instance
List Amazon Linux images (via System Manager):
aws ssm get-parameters-by-path --path /aws/service/ami-amazon-linux-latest --query "Parameters[].Name"
Launch instance:
subnet_id=$(aws ec2 describe-subnets --filters Name=tag:Name,Values=$subnet_1 | jq -r '.Subnets[0].SubnetId')
group_id=$(aws ec2 describe-security-groups --filters Name=tag:Name,Values=$security_group | jq -r '.SecurityGroups[0].GroupId')
aws ec2 run-instances \
--subnet-id $subnet_id \
--security-group-ids $group_id \
--image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64 \
--instance-type t2.micro \
--count 1 \
--key-name $key \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value='$instance'}]'
Check instance status. Wait until it is running
:
instance_id=$(aws ec2 describe-instances --filters Name=tag:Name,Values=$instance | jq -r '.Reservations[-1].Instances[-1].InstanceId')
aws ec2 describe-instances --instance-id $instance_id | jq -r '.Reservations[0].Instances[0].State'
Login into the instance:
instance_public_ip=$(aws ec2 describe-instances --filters Name=tag:Name,Values=$instance | jq -r '.Reservations[-1].Instances[-1].PublicIpAddress')
ssh -i ~/.ssh/$key ec2-user@$instance_public_ip
Next step: Attach an instance role to allow S3 access