Amazon EC2 Essentials
EC2 essentials, CLI commands, and best practices
Amazon EC2 (Elastic Compute Cloud) is AWS's virtual computing service that lets you launch and manage virtual servers (instances) in the cloud.
The problem it solves: It eliminates the need to purchase, configure, and maintain physical hardware to run applications. It provides scalable, on-demand compute capacity.
When to use it:
- You need full control over the operating system and configuration
- Apps that require persistent resources (web servers, databases, workers)
- Predictable workloads or those requiring dedicated instances
Alternatives:
- Lambda: For serverless code without server management
- ECS/Fargate: For containers without managing infrastructure
- Lightsail: For simple cases with predefined configuration
Key Concepts
| Concept | Description |
|---|---|
| Instance Types | Hardware families that define CPU, RAM, storage, and networking. Naming convention: [family][generation].[size] (e.g., t3.medium, m5.xlarge) |
| Keypairs | SSH key pair (public/private) for secure authentication. AWS stores the public key, you keep the private one. |
| Security Groups | Instance-level virtual firewall that controls inbound (ingress) and outbound (egress) traffic using rules based on ports and CIDRs. |
| User Data Scripts | Bash scripts that run automatically when launching an instance (only on first boot). Useful for software installation and initial configuration. |
| EBS (Elastic Block Store) | Persistent storage volumes that attach to EC2 instances like "virtual hard drives." They exist independently of instances. |
| Elastic IP | Static public IP address that persists even when you stop/restart the instance. You're charged if it's allocated but not associated with a running instance. |
| CPU Credits (T instances) | Burst performance system for T family. You accumulate credits when using less than baseline, you spend them when you need more CPU. |
| AMI (Amazon Machine Image) | Template containing the operating system, applications, and configuration for launching instances. |
Essential AWS CLI Commands
Creating Resources
# Create keypair
aws ec2 create-key-pair \
--key-name my-keypair \
--query 'KeyMaterial' \
--output text > my-keypair.pem
chmod 400 my-keypair.pem # Adjust permissions
# Create security group
aws ec2 create-security-group \
--group-name web-server-sg \
--description "Allow HTTP and SSH" \
--vpc-id vpc-xxxxxx
# Add rules to security group
aws ec2 authorize-security-group-ingress \
--group-id sg-xxxxx \
--protocol tcp \
--port 22 \
--cidr 157.100.121.171/32 # Your specific IP
# Launch instance
aws ec2 run-instances \
--image-id ami-0da00c97ce64145f1 \
--instance-type t3.micro \
--key-name my-keypair \
--security-group-ids sg-xxxxx \
--user-data file://userdata.sh \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=WebServer-01}]'
# Allocate Elastic IP
aws ec2 allocate-addressQuerying Resources
# Verify identity (pre-flight)
aws sts get-caller-identity
# List VPCs (find default VPC)
aws ec2 describe-vpcs \
--query 'Vpcs[?IsDefault==`true`].VpcId' \
--output text
# Find most recent AMI
aws ec2 describe-images \
--owners amazon \
--filters "Name=name,Values=al2023-ami-2023*" \
"Name=architecture,Values=x86_64" \
--query 'sort_by(Images, &CreationDate)[-1].ImageId' \
--output text
# Check instance state
aws ec2 describe-instances \
--instance-ids i-xxxxx \
--query 'Reservations[0].Instances[0].[State.Name,PublicIpAddress]' \
--output table
# Detailed status checks
aws ec2 describe-instance-status \
--instance-ids i-xxxxx
# View applied security group
aws ec2 describe-security-groups \
--group-ids sg-xxxxx
# View EBS volumes
aws ec2 describe-volumes \
--volume-ids vol-xxxxx
# Console output (debugging)
aws ec2 get-console-output \
--instance-id i-xxxxx \
--output text > console-output.txt
# List Elastic IPs
aws ec2 describe-addressesModifying Resources
# Modify instance attribute
aws ec2 modify-instance-attribute \
--instance-id i-xxxxx \
--instance-type t3.small
# Change volume DeleteOnTermination
aws ec2 modify-instance-attribute \
--instance-id i-xxxxx \
--block-device-mappings DeviceName=/dev/xvda,Ebs={DeleteOnTermination=false}Deleting Resources
# Terminate instance
aws ec2 terminate-instances \
--instance-ids i-xxxxx
# Delete security group
aws ec2 delete-security-group \
--group-id sg-xxxxx
# Release Elastic IP
aws ec2 release-address \
--allocation-id eipalloc-xxxxx
# Delete keypair
aws ec2 delete-key-pair \
--key-name my-keypairArchitecture and Flows
EC2 Instance Components
Instance Launch Flow
EBS Lifecycle
Best Practices Checklist
Security
- Never expose port 22 to
0.0.0.0/0- use specific IP or Session Manager - Use security groups with least privilege principle
- Rotate keypairs periodically and store them securely
- Enable encryption on EBS volumes (
Encrypted: true) - Use IAM roles instead of hardcoding credentials on instances
- Keep OS updated (
yum update -yin user data)
Cost Optimization
- Set
DeleteOnTermination: truefor ephemeral instances - Release Elastic IPs that aren't in use
- Monitor CPU Credits on T instances - consider M family if constantly bursting
- Use appropriate sizes - start small and scale based on metrics
- Consider Reserved Instances or Savings Plans for predictable workloads
- Terminate development instances outside business hours
Performance
- Choose instance type based on the real bottleneck (CPU vs RAM vs I/O)
- Use gp3 instead of gp2 for better cost/performance
- For I/O intensive workloads, consider Instance Store or io2 EBS
- Launch instances in Availability Zone close to users
- Enable detailed monitoring if you need metrics every 1 min
Reliability
- Never use a single instance in production - design for multiple AZs
- Implement proper health checks
- Automate deployments with user data or config management
- Create AMIs from configured instances for quick recovery
- Configure automated snapshots for critical EBS volumes
Operational Excellence
- Use consistent tags (
Name,Environment,Project,Owner) - Document in user data what's installed and why
- Use CloudWatch for centralized logs
- Implement Infrastructure as Code (CloudFormation/Terraform)
- Maintain inventory of instances and their purposes
Common Mistakes to Avoid
SSH Timeout even though security group is correct
Why it happens: Your ISP may block outbound port 22 due to security policies.
How to diagnose:
# Test 1: Can you reach port 80?
curl http://[instance-ip] # If it works, it's not AWS
# Test 2: Specifically verify SSH
nc -zv [instance-ip] 22 # If timeout, local network issueSolution:
- Use AWS Systems Manager Session Manager (doesn't require port 22)
- Change SSH to an alternative port (e.g., 2222, 443)
- Contact your ISP or use a VPN
Forgetting to adjust keypair permissions
Why it happens: SSH rejects files with overly open permissions for security.
Typical error: WARNING: UNPROTECTED PRIVATE KEY FILE!
Solution:
chmod 400 my-keypair.pem # Always after creating keypairRunning out of CPU Credits on T instances without noticing
Why it happens: Sustained workloads consume credits faster than accumulation.
Symptom: Instance slow after hours of load, but CloudWatch shows low CPU usage (because it's throttled to baseline).
Solution:
- Monitor
CPUCreditBalancemetric in CloudWatch - If constantly low, migrate to M family or enable Unlimited mode (with cost awareness)
Unexpected Elastic IP costs
Why it happens: Allocated but not attached = $0.005/hour.
Solution:
# List orphaned EIPs
aws ec2 describe-addresses \
--query 'Addresses[?AssociationId==null]'
# Release immediately if not in use
aws ec2 release-address --allocation-id eipalloc-xxxxxLosing data when terminating instance
Why it happens: DeleteOnTermination: true on EBS volume (default).
Prevention:
- For critical data, always set
DeleteOnTermination: false - Create snapshots before major changes
- Use RDS/DynamoDB for databases instead of EBS
Not checking status checks before diagnosing
Why it happens: Assuming "running" = "functional."
Solution:
# Always check detailed status checks
aws ec2 describe-instance-status --instance-ids i-xxxxxLook for InstanceStatus: ok and SystemStatus: ok before investigating networking.
Cost Considerations
What generates costs in EC2
| Component | Cost | Unit |
|---|---|---|
| Running instance | Variable by type | Per hour |
| EBS volumes | ~0.10/GB | Per GB-month |
| Unassociated Elastic IP | $0.005/hour | Per hour |
| Data transfer OUT | $0.09/GB after 100GB | Per GB |
| EBS Snapshots | ~$0.05/GB | Per GB-month |
Cost Optimization
Free Tier (first 12 months):
- 750 hours/month of
t2.microort3.micro(Linux) - 30 GB of EBS General Purpose (gp2 or gp3)
- 1 GB of snapshots
Strategies:
- Right-sizing: Start with
t3.micro, scale based on CloudWatch metrics - Stop vs Terminate: For dev/test, stop when not in use (you don't pay for instance, only EBS)
- Spot Instances: 70-90% discount for fault-tolerant workloads (not covered yet)
- Reserved/Savings Plans: Up to 72% discount for predictable workloads (not covered yet)
Monitoring:
# View costs by instance type
aws ce get-cost-and-usage \
--time-period Start=2025-10-01,End=2025-10-10 \
--granularity DAILY \
--metrics UnblendedCost \
--group-by Type=DIMENSION,Key=INSTANCE_TYPEIntegration with Other Services
| Service | How it integrates | Typical use case |
|---|---|---|
| VPC | EC2 lives inside VPC | Networking, subnets, security groups |
| EBS | Storage volumes for EC2 | Root volumes, data persistence |
| IAM | Instance profiles / roles | Permissions to access S3, DynamoDB, etc. |
| CloudWatch | Instance metrics and logs | Monitoring CPU, RAM, custom metrics |
| Auto Scaling | Automatic instance management | Scale out/in based on demand |
| ELB | Traffic distribution | Load balancing across multiple instances |
| S3 | Artifact storage | User data scripts, backups, static assets |
| RDS | Database backend | EC2 app servers + RDS database |
| Route 53 | DNS routing | Map domains to instances or load balancers |
| Systems Manager | Remote management | Session Manager (SSH alternative), patching |