Skip to main content

EC2 - Elastic Compute Cloud

Docs: https://docs.aws.amazon.com/ec2

https://console.aws.amazon.com/ec2/v2/home

Cheatsheet - https://digitalcloud.training/amazon-ec2/

Autoscaling cheatsheet - https://digitalcloud.training/amazon-ec2/

IaaS

You manage the OS and whatever you want to run on top it, and AWS manages the hypervisor and the hardware below.

Virtual servers

Each EC2 instance is a virtual server or virtual machine that runs on top of host servers.

The virtualization technology of EC2 is Nitro.

Learn

Tutorial 'Host a WordPress blog' (note that there are 2):

Instance types

https://aws.amazon.com/ec2/instance-types/

https://docs.aws.amazon.com/ec2/latest/instancetypes/instance-types.html

t2.micro:

  • t is the family
  • 2 is the generation
  • micro is the size (CPU, memory, storage and network)

Our experience indicates that you'll overestimate the resource requirements for your applications. We recommend that you try to start your application with a smaller instance type than you think you need at first and change the instance type later if needed. (AWS in Action p. 63)

Launch instance

  • Make sure you are at the right region
  • Go to the EC2 Dashboard and click the button 'Launch instance'
  • Give it a Name
  • Choose the OS image (Amazon Machine Image)
    • Eg pick Amazon Linux 2023
  • Choose the instance type (t2.nano, t2.micro...)
  • Choose a key pair if you plan to connect to the instance using SSH
    • You can create a new one of type 'RSA', file format .pem and name like us-east-kp
  • On the 'Network settings'
    • VPC: select one or just use the default
    • Subnet: No preference
    • Auto-assign public IP: Enable
    • Firewall (security groups):
      • If we don't have any, create a new one:
        • Check 'Create security group'
        • Give it a name, eg 'WebSSHAccess', and edit the Description too, putting the same name and the creation date
        • Type: ssh
        • Source type: Anywhere, or any IP
        • (This will open port 22 for SSH access)
      • If we have one:
        • Check 'Select exiting security group' and select it
  • Advanced details (optional)
    • IAM instance profile: attach any IAM Role for accessing services like S3
    • Metadata accessible: Enabled
    • Metadata version: V1 and V2 or V2
    • Set 'User data'
  • Click 'Launch instance'

To terminate the instance, at the Instances pages open the 'Instance state' drop-down and click 'Terminate instance'.

Connect

Connect to your EC2 instance - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connect.html

Options:

SSH with key pair

(Prerequisites) Connect to your Linux instance using SSH - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connect-to-linux-instance.html

(ssh commands) Connect to your Linux instance using an SSH client - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connect-linux-inst-ssh.html

We connect to an SSH server running on the instance. Port 22 (where the SSH daemon runs) must be open; we do this with the security group (the firewall).

The client has the private key (contained on a .pem file), and the server the public key (at ~/.ssh/authorized_keys). Anyone with the public key can access the instance.

To connect, we can use either the 'Public IPv4 address' (eg 3.87.6.57) or 'Public IPv4 DNS' (eg ec2-3-87-6-57.compute-1.amazonaws.com; note that it has the public IP on the name).

chmod 400 us-east-kp.pem # Fix WARNING: UNPROTECTED PRIVATE KEY FILE!
ssh -i us-east-kp.pem ec2-user@ec2-107-22-100-77.compute-1.amazonaws.com
# or
ssh -i us-east-kp.pem ec2-user@107.22.100.77

If asked:

"The authenticity of host 'ec2-107-22-100-77.compute-1.amazonaws.com (107.22.100.77)' can't be established. This key is not known by any other names Are you sure you want to continue connecting (yes/no/[fingerprint])?"

Say 'yes'. It will say "Warning: Permanently added 'ec2-107-22-100-77.compute-1.amazonaws.com' (ED25519) to the list of known hosts."

Problems:

  • You need to open the port 22.
  • It's not possible to change the key pair externally after launching the EC2 instance.
  • It works only for a single user.

It's preferable to use the Session Manager.

EC2 Instance Connect

Connect to your Linux instance with EC2 Instance Connect - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connect-linux-inst-eic.html

Uses SSH but there's no need to have a key :) It creates a temporary key pair: When you connect to an instance using EC2 Instance Connect, the Instance Connect API pushes an SSH public key to the instance metadata where it remains for 60 seconds.

Uses IAM for access control.

You can use a terminal or a browser. Port 22 needs to be open. The instance needs to have a public IPv4 address.

Session Manager (AWS Systems Manager)

tip

Open https://console.aws.amazon.com/systems-manager/session-manager/$INSTANCEID in your browser. (INSTANCEID is like i-01269dace6eb55218.)

Uses IAM for access control. No need to open any ports (unlike SSH, which requires opening the port 22, or RDP, which requires opening the port 3389). No need to configure a key pair upfront (it uses temporary key pairs). No need to maintain a bastion host. Is the most secure option. See all benefits here.

You can use either an interactive one-click browser-based shell or the AWS Command Line Interface (AWS CLI). To connect from the terminal (instead of the browser) see Install the Session Manager plugin for the AWS CLI.

Requirements:

  • The SSM agent needs to be installed. It is on Amazon Linux, Ubuntu and some other AMIs.
  • The EC2 instance needs to be launched with an IAM instance profile role having the permission policy AmazonSSMManagedInstanceCore, which "Allows EC2 instances to call AWS services like CloudWatch and Systems Manager on your behalf.".

When launching an EC2 instance using the console do:

  • At "Key pair (login)", choose "Proceed without a key pair (Not recommended)".
  • At "Network settings", choose "Create security group" and uncheck "Allow SSH traffic fom".
  • At "Advanced details" → "IAM instance profile", choose a role that has the permission policy AmazonSSMManagedInstanceCore. (You need the trust policy sts:AssumeRole as well, see this.)

RDP (Windows)

Remote Desktop Protocol. To connect to Windows machines. There are clients for many OS. You access the desktop using a graphical interface.

Port 3389 must be open on the security group.

Internet gateway

Enables access to/from the internet.

When we connect to the EC2 instance we do so through the internet gateway.

Security group (instance firewall)

tip

To debug misconfiguration in firewall rules or monitor network traffic you can:

  • Use the VPC Reachability Analyzer to simulate the traffic and see if the tool finds the configuration problem.
  • Enable VPC Flow Logs to get access to aggregated log messages containing rejected connections.

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html

A virtual firewall that controls incoming and outgoing (inbound and outbound) traffic at the instance level (in contrast with Network ACL, which operate at the subnet level).

The rules control which direction (inbound or outbound), IP protocols (TCP, UDP, ICMP), port and IP addresses we can connect from/to. We can also specify a security group.

By default, a security group:

  • Does not allow any inbound traffic. You need to add rules yourself to do so.
  • Contains a rule that allows all outbound traffic. If you want something more restrictive, you need to remove the rule and add other rules.

Source 0.0.0.0/0 means any IPv4 address, and ::/0 any IPv6 address.

Metadata

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html

Information about the instance, stored locally on the instance.

The IP address 169.254.169.254 is the address of Instance Metadata Service that runs locally on the same computer. It's a link-local address. It can be accessed only from the instance.

To get the instance metadata run:

# V1
curl http://169.254.169.254/
curl http://169.254.169.254/latest/meta-data
curl http://169.254.169.254/latest/meta-data/instance-id
curl http://169.254.169.254/latest/meta-data/public-ipv4

# V2
# Get token
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
# or
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
# Use token
curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/placement/availability-zone

# You can do this with a single command
EC2AZ=$(TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` && curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/placement/availability-zone)

User Data

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-add-user-data.html

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html

Code scripts that run when the instance starts, to customize the instance.

#!/bin/bash
yum update -y

Limited to 16 kB.

Accessible at the metadata at http://169.254.169.254/latest/user-data.

Run Apache server

#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd

Once the Apache server is running, there are various ways to customize the HTML:

echo '<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Hello!</title></head><body><p>Hello!</p></body></html>' > /var/www/html/index.html
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
AZ=`curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/placement/availability-zone`

cat > /var/www/html/index.html <<EOF
<html>
<head>
<title>Instance Availability Zone</title>
</head>
<body>
<div>This instance is located in Availability Zone: $AZ</div>
</body>
</html>
EOF

Networking

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-networking.html

Network interface adapter

Important: you can have multiple adapters connected to the instance, which can be on diferent subnets, but the subnets have to be in the same availability zone. Thus, you cannot move a network interface to a different AZ.

Each instance has a default (primary, eth0) network interface attached to a subnet, and a private IP address on the subnet. (If it's on a public subnet, it can also have a public IP, which is associated with the private IP.) The primary network interface cannot be detached. You can optionally attach the instance to more subnets using more network interface adapters, but each subnet has to be on the same availability zone.

Adapter types:

IP address

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-instance-addressing.html

We release your instance's public IP address when it is stopped, hibernated, or terminated. Your stopped or hibernated instance receives a new public IP address when it is started.

Private IP:

  • Doesn't change, even if the instance is stopped.
  • Used on public and private subnets.

Public IP:

  • Is dynamic. It's associated to the instance until it is stopped or terminated, thus you cannot use it in application code since it can change. Note that the ‘Public IPv4 DNS’ (eg ec2-3-94-61-169.compute-1.amazonaws.com) will also change, since it includes the public IP.
  • Used in public subnets only.

Note that when you reboot an instance it keeps the public IPv4 address, see docs.

Pricing

https://aws.amazon.com/blogs/aws/new-aws-public-ipv4-address-charge-public-ip-insights/

https://www.linkedin.com/pulse/changes-aws-public-ip-address-charges-neal-k-davis-j0wae/ - https://www.youtube.com/watch?v=4EvktMxjyxU

Elastic IP

An Elastic IP address is static; it does not change over time.

You can assign the elastic IP (EIP) to a second network interface eth1 (will be on a different subnet than eth0), and attach this network interface to an instance. If the instance is stopped and started, the IP won't change.

Both an ENI and EIP can be mapped to a different instance in the same AZ. However, as explained above, the ENI cannot be moved to a different AZ, but the EIP can. Thus, if the instance fails, we can move the ENI or the EIP to another instance within the same AZ, or move the EIP to an instance in different AZ.

Elastic IP addresses are only for IPv4, not IPv6.

You are charged for elastic IPs that are allocated to your account but you don't actually use on a running instance. On a EC2 instance, if you do Instance state → Stop instance you'll see this warning:

After you stop the instance, you are no longer charged usage or data transfer fees for it. However, you will still be billed for associated resources, such as attached EBS volumes and associated Elastic IP addresses.

And when you terminate an instance with an elastic IP it says:

Elastic IPs which are not associated with an instance will incur an hourly cost. Amazon EC2 pricing To disassociate and release Elastic IPs associated with this instance, go to the Elastic IPs screen. The following Elastic IPs are still associated with your account: 34.192.137.227

To release an EIP, first disassociate it from the network interface at EC2 → Network interfaces, select the network interface with the EIP, and then do Actions → Disassociate address. (Afterwards, if the instance is not running, you can optionally delete the network interface with Actions → Delete.) Then go to EC2 → Elastic IP addresses, select the allocated EIP and do Actions → Release Elastic IP address.

NAT

https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html

Network Address Translation.

Receives traffic on one IP and translates it and sends it out using a different IP.

The internet gateway transforms the instance's public IP to a private IP (and viceversa) in incoming and outgoing network packets.

See https://stackoverflow.com/questions/74455063/what-exactly-are-nat-gateway-and-internet-gateway-on-aws

NAT Gateways exist because organizations want the additional security offered by private subnets, which guarantee that there is no inbound access from the Internet. Similar security can be provided with a Security Group, so private subnets aren't actually required.

Bastion hosts

info

CloudFormation template - https://aws.amazon.com/solutions/implementations/linux-bastion/

Allows to connect to an instance on a private subnet through an instance on a public subnet.

Can be done with a NAT gateway or a NAT instance.

How to Connect to a Private EC2 Instance in a VPC Using a Bastion Host - https://www.youtube.com/watch?v=rn9kAXz6qxA - See this accompanying blog post 'SSH into EC2 in Private Subnet' - https://digitalcloud.training/ssh-into-ec2-in-private-subnet

How can I connect to a private Amazon RDS instance from local system through EC2 as a bastion host? - https://www.youtube.com/watch?v=ypWzL3PdKx0

NAT gateway

An AWS service used to allow instances in private subnets to connect to the Internet.

Announcement: https://aws.amazon.com/blogs/aws/new-managed-nat-network-address-translation-gateway-for-aws

To do it, launch a NAT gateway in a public subnet, and add a route 0.0.0.0/0 to the private subnet's route table pointing to the NAT Gateway.

Traffic is outbound only. No one outside from the Internet will be able to connect to the private instance. This allows the instance to call an external service, download software updates etc. If we wanted bidirectional traffic, we would deploy the instance on a public subnet, so that it has a public IP, and use Internet Gateway.

Example: VPC with servers in private subnets and NAT - https://docs.aws.amazon.com/vpc/latest/userguide/vpc-example-private-subnets-nat.html

Important

Since a NAT gateway has an Elastic IP, you'll be charged. If you delete the NAT gateway, you need to release the EIP too afterwards. You also pay for the data processed by the NAT gateway, and for data transfers. See https://aws.amazon.com/vpc/pricing/

To reduce costs, you can:

Steps

We have a private instance on a private subnet. We deploy a NAT gateway to a public subnet, since it needs to have public IP assigned, which needs to be an elastic IP (in 'Elastic IP allocation ID' click 'Allocate Elastic IP'). The NAT gateway talks to the Internet Gateway on behalf of the private instance.

We create a private route table, explicitly associated to the private subnet (on 'Subnet associations'). Then on 'Edit routes' we add a route entry with 'Destination' 0.0.0.0/0 (ie everything else that is not routed locally via the VPC router) and for 'Target' choose 'NAT Gateway', selecting the NAT gateway we've created. So any address outside of the subnet address range will go to the NAT gateway.

The private instance can use it's private IP address to connect to the private IP of the NAT gateway, which will forward the traffic to the Internet Gateway using Network Address Translation, and reach the Internet.

Main route table (public subnet):

DestinationTarget
10.0.0.0/16local
0.0.0.0/0igw-id

Private route table (private subnet):

DestinationTarget
10.0.0.0/16local
0.0.0.0/0nat-gateway-id

To check that the setup is correct do:

  • Connect to a public instance using Instance Connect.
  • From the terminal, using nano, create a file containing the private instance's SSH key-pair, and then chmod 400.
  • Connect to the private instance with ssh, using its private IPv4 address.
  • Once connected to the private instance, run ping google.com. It should receive a response.

NAT instance

Not used much nowadays since we have NAT gateways. It was the way to do it in the past, but NAT gateways, since they are managed by AWS, are highly available and they scale automatically.

Unlike NAT gateways, is not an AWS service. It's a special AMI pre-configured. Has amzn-ami-vpc-nat on the name.

You have to disable the source and destination checks to function as a NAT.

See https://stackoverflow.com/questions/22188444/why-do-we-need-private-subnet-in-vpc

Lifecycle

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html

Stopped

  • Only for EBS-backend instances. If the root volume is instance store-backed you cannot stop it.
  • You are not charged in EC2, but you pay for the EBS data since the volumes remain attached.
  • RAM is lost.
  • Host will be different when it restarts → if there's some maintenance or the host has an issue, we can stop the instance to move it.
  • Private IPv4 and IPv6 address is retained, but public (not Elastic) IPv4 is not. Elastic IPs are always retained.

Hibernating

  • For On-Demand or Spot instances.
  • Needs to be enabled when launched.
  • Only for supported AMIs.
  • RAM is saved on a EBS volume and restored when restarted.
  • Processes running are resumed when restarted.
  • Previously attached data volumes are reattached.
  • Instance ID is retained.

Reboot

  • Equivalent to an OS reboot.
  • All IP address and DNS names are retained.

For retirement

  • Scheduled to be retired by AWS when there is an irreparable failure of the underlying hardware, .

Terminated

  • Root EBS volumes are deleted by default.

Recovered

  • Automatic recovery be configured or you can do so using a CloudWatch alarm.
  • The recovered instance is identical to the original instance.

Pricing

https://aws.amazon.com/ec2/pricing

Instance purchasing options - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-purchasing-options.html

EC2 Pricing Models Explained - https://www.youtube.com/watch?v=rmFlOo7MNW0

On-Demand

  • No up-front commitment.
  • Most expensive option (standard rate, no discount).
  • Pay by the second (Amazon Linux) or hour (RHEL, SUSE).
  • To try something, test a new app or for unpredictable workloads. Not for steady, long-term workloads.

Spot

  • Bid on spare capacity.
  • Least expensive option, up to 90% discount.
  • Instance can be terminated at any time, thus workload needs to be interruptible.
  • To run compute heavy tasks like ML or HPC (hundreds or thousands of servers) at a very low cost.

Reserved (RI)

  • Commitment of 1-3 years.
  • About 30-60% savings, up to 72%.
  • You pay for capacity even if you don't use it, but on the other hand you ensure you'll have capacity.
  • Can be Standard or Convertible (more expensive but you can change the instance attributes).

Savings plan

  • Best of all options, see this.
  • Hourly spend commitment of 1-3 years. Anything beyond that you'll pay On-Demand price.
  • Saving up to 72%.
  • More flexibility than reserved.
  • Three types of Savings Plans: Compute Savings Plans (includes Fargate and Lambda too), EC2 Instance Savings Plans, and Amazon SageMaker Savings Plans.

Dedicated instances

  • Might share hardware with other instances from the same AWS account that are not Dedicated Instances.
  • Billed per instance.

Dedicated hosts

  • Physical server that is fully dedicated for your use.
  • Dedicated hardware to support software licenses (since we have visibility of sockets and physical cores) or compliance/regulatory requirements.
  • Billed per host.

AMI

Important

The AMI ID is region-specific, that is, the AMI ID of the latest Amazon Linux is different in us-east-1 and us-west-1. Is important to set the right value in CloudFormation templates.

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html

Amazon Machine Image. A template with a read-only filesystem including the OS, additional software like a server and applications and configuration.

The AMI does not include the kernel of the OS. The kernel is loaded from Amazon Kernel Image (AKI)

Can be backed by EBS (persistent) or instance store (non-persistent).

You can find AMIs in the AWS Marketplace: https://aws.amazon.com/marketplace

Automatically clean up unused AMIs to reduce EBS storage consumption and costs - https://cloudonaut.io/cleaning-up-amis - https://www.npmjs.com/package/aws-amicleaner

Amazon Linux

https://aws.amazon.com/linux/amazon-linux-2023

https://github.com/amazonlinux/amazon-linux-2023

What is Amazon Linux 2023? - https://docs.aws.amazon.com/linux/al2023/ug/what-is-amazon-linux.html

Comparing AL2 and Amazon Linux 2023 - https://docs.aws.amazon.com/linux/al2023/ug/compare-with-al2.html

Amazon Linux is originally based on RHEL, like CentOS. See Relationship to Fedora.

It uses the yum package manager. To install software run:

yum update -y
yum install -y httpd

AL2 (not the 2023) has extras - https://docs.aws.amazon.com/linux/al2/ug/al2-extras.html

amazon-linux-extras list
sudo amazon-linux-extras install python3.8

Placement groups

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/placement-groups.html

Placement groups are optional. If you don't launch your instances into a placement group, EC2 tries to place the instances in such a way that all of your instances are spread out across the underlying hardware to minimize correlated failures.

Options:

  • Cluster: instance are close (eg on the same rack) to have low-latency and high throughput. For HPC.
  • Partition: split instances in partitions, and each partition runs on a separate underlying hardware. You can have up to 7 partitions per AZ. When we have data replicated and we want to ensure there's always a node running, eg Kafka or Cassandra.
  • Spread: a small group of instances that all run on different hardware (ie a different rack) to reduce correlated failures.

You choose it when you launch the instance.

CLI

https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/index.html

See this example: https://github.com/AWSinAction/code3/blob/main/chapter04/virtualmachine.sh

See List and filter using the CLI and API.

Note that if you use wildcards (*) in --filters you need to use quotes.

aws ec2 describe-instances
aws ec2 describe-instances --filters Name=instance-type,Values=t2.micro
aws ec2 describe-instances --filters Name=instance-state-name,Values=stopped Name=instance-type,Values=t2.micro
tip

Use --query to extract data from the JSON response using JMESPath.

Use --output text to pass the output to grep, sed or awk.

aws ec2 describe-images --filters "Name=name,Values=amzn2-ami-hvm-2.0.202*-x86_64-gp2" --query "Images[0].ImageId" --output text
aws ec2 describe-regions