Home / Notebooks / Cloud
Cloud
intermediate

Amazon EC2 Essentials

Essential AWS Elastic Compute Cloud concepts for virtual server management

March 10, 2024
Updated regularly

Amazon EC2 Essentials

Quick reference guide for AWS Elastic Compute Cloud (EC2).

What is Amazon EC2?

Amazon EC2 provides scalable virtual servers in the cloud:

  • Virtual machines (instances) in the AWS cloud
  • Complete control over operating system and software
  • Flexible sizing (CPU, memory, storage, networking)
  • Pay-as-you-go or reserved pricing
  • Global infrastructure with multiple regions and availability zones
  • Auto Scaling for dynamic workloads
  • Instance Types

    General Purpose

    T-Series (Burstable)
    ├── t4g: ARM-based, best value (up to 40% cost savings)
    ├── t3: Intel/AMD, balanced performance
    └── t2: Previous generation
    
    M-Series (Balanced)
    ├── m7g: ARM-based, latest generation
    ├── m6i: Intel, general purpose
    └── m5: Previous generation Intel
    

    Use Cases: Web servers, development environments, small databases

    Compute Optimized

    C-Series
    ├── c7g: ARM-based, highest performance
    ├── c6i: Intel, compute intensive
    └── c5: Previous generation
    

    Use Cases: Batch processing, high-performance web servers, gaming servers

    Memory Optimized

    R-Series (Memory Intensive)
    ├── r7g: ARM-based, large memory
    ├── r6i: Intel, memory optimized
    └── r5: Previous generation
    
    X-Series (Extreme Memory)
    └── x2: Up to 4TB RAM
    

    Use Cases: In-memory databases (Redis, SAP HANA), big data analytics

    Storage Optimized

    I-Series (High IOPS)
    └── i4i: NVMe SSD storage
    
    D-Series (Dense Storage)
    └── d3: HDD-based, large capacity
    

    Use Cases: NoSQL databases, data warehousing, log processing

    Accelerated Computing

    P-Series (GPU - ML/AI)
    ├── p4: NVIDIA A100 GPUs
    └── p3: NVIDIA V100 GPUs
    
    G-Series (GPU - Graphics)
    └── g5: NVIDIA A10G GPUs
    

    Use Cases: Machine learning, video processing, gaming

    Launching Instances

    AWS CLI - Launch Instance

    # ========== Launch Basic Instance ==========
    aws ec2 run-instances \
      --image-id ami-12345678 \
      --instance-type t3.micro \
      --key-name my-key-pair \
      --security-group-ids sg-12345678 \
      --subnet-id subnet-12345678 \
      --count 1 \
      --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=MyInstance}]'
    
    # ========== Launch with User Data ==========
    aws ec2 run-instances \
      --image-id ami-12345678 \
      --instance-type t3.micro \
      --key-name my-key-pair \
      --security-group-ids sg-12345678 \
      --subnet-id subnet-12345678 \
      --user-data file://user-data.sh
    
    # ========== Launch with Multiple Storage Volumes ==========
    aws ec2 run-instances \
      --image-id ami-12345678 \
      --instance-type t3.medium \
      --key-name my-key-pair \
      --block-device-mappings '[
        {
          "DeviceName": "/dev/xvda",
          "Ebs": {
            "VolumeSize": 30,
            "VolumeType": "gp3",
            "DeleteOnTermination": true,
            "Encrypted": true
          }
        },
        {
          "DeviceName": "/dev/sdf",
          "Ebs": {
            "VolumeSize": 100,
            "VolumeType": "gp3",
            "DeleteOnTermination": false
          }
        }
      ]'
    

    User Data Script

    #!/bin/bash
    # This script runs on instance first launch
    
    # Update packages
    yum update -y
    
    # Install web server
    yum install -y httpd
    
    # Start web server
    systemctl start httpd
    systemctl enable httpd
    
    # Create simple webpage
    echo "<h1>Hello from EC2!</h1>" > /var/www/html/index.html
    
    # Install CloudWatch agent
    wget https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm
    rpm -U ./amazon-cloudwatch-agent.rpm
    

    Instance Management

    Start, Stop, Reboot

    # ========== Start Instance ==========
    aws ec2 start-instances --instance-ids i-1234567890abcdef0
    
    # ========== Stop Instance ==========
    aws ec2 stop-instances --instance-ids i-1234567890abcdef0
    
    # ========== Reboot Instance ==========
    aws ec2 reboot-instances --instance-ids i-1234567890abcdef0
    
    # ========== Terminate Instance ==========
    aws ec2 terminate-instances --instance-ids i-1234567890abcdef0
    

    Describe and List Instances

    # ========== List All Instances ==========
    aws ec2 describe-instances
    
    # ========== List Running Instances ==========
    aws ec2 describe-instances \
      --filters "Name=instance-state-name,Values=running" \
      --query "Reservations[].Instances[].[InstanceId,InstanceType,PublicIpAddress,Tags[?Key=='Name'].Value|[0]]" \
      --output table
    
    # ========== Get Instance Details ==========
    aws ec2 describe-instances \
      --instance-ids i-1234567890abcdef0
    
    # ========== List Instances by Tag ==========
    aws ec2 describe-instances \
      --filters "Name=tag:Environment,Values=production"
    

    Modify Instance

    # ========== Change Instance Type ==========
    # 1. Stop the instance
    aws ec2 stop-instances --instance-ids i-1234567890abcdef0
    
    # 2. Wait for stopped state
    aws ec2 wait instance-stopped --instance-ids i-1234567890abcdef0
    
    # 3. Modify instance type
    aws ec2 modify-instance-attribute \
      --instance-id i-1234567890abcdef0 \
      --instance-type "{\"Value\": \"t3.medium\"}"
    
    # 4. Start the instance
    aws ec2 start-instances --instance-ids i-1234567890abcdef0
    
    # ========== Enable Termination Protection ==========
    aws ec2 modify-instance-attribute \
      --instance-id i-1234567890abcdef0 \
      --disable-api-termination
    
    # ========== Disable Termination Protection ==========
    aws ec2 modify-instance-attribute \
      --instance-id i-1234567890abcdef0 \
      --no-disable-api-termination
    

    Elastic Block Store (EBS)

    Volume Types

    TypeUse CaseIOPSThroughputSize
    gp3General purpose SSD3,000-16,000125-1,000 MB/s1GB-16TB
    gp2General purpose SSD (legacy)100-16,000Up to 250 MB/s1GB-16TB
    io2High performance SSDUp to 64,000Up to 1,000 MB/s4GB-16TB
    st1Throughput optimized HDD500Up to 500 MB/s125GB-16TB
    sc1Cold HDD (lowest cost)250Up to 250 MB/s125GB-16TB

    EBS Commands

    # ========== Create Volume ==========
    aws ec2 create-volume \
      --volume-type gp3 \
      --size 100 \
      --availability-zone us-east-1a \
      --encrypted \
      --tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=MyVolume}]'
    
    # ========== Attach Volume ==========
    aws ec2 attach-volume \
      --volume-id vol-1234567890abcdef0 \
      --instance-id i-1234567890abcdef0 \
      --device /dev/sdf
    
    # ========== Detach Volume ==========
    aws ec2 detach-volume \
      --volume-id vol-1234567890abcdef0
    
    # ========== Create Snapshot ==========
    aws ec2 create-snapshot \
      --volume-id vol-1234567890abcdef0 \
      --description "Backup before upgrade" \
      --tag-specifications 'ResourceType=snapshot,Tags=[{Key=Name,Value=MySnapshot}]'
    
    # ========== List Snapshots ==========
    aws ec2 describe-snapshots --owner-ids self
    
    # ========== Delete Snapshot ==========
    aws ec2 delete-snapshot --snapshot-id snap-1234567890abcdef0
    
    # ========== Modify Volume ==========
    aws ec2 modify-volume \
      --volume-id vol-1234567890abcdef0 \
      --size 200 \
      --volume-type gp3 \
      --iops 4000
    

    Mount EBS Volume (Linux)

    # ========== Check Available Disks ==========
    lsblk
    
    # ========== Create Filesystem ==========
    sudo mkfs -t ext4 /dev/xvdf
    
    # ========== Mount Volume ==========
    sudo mkdir /data
    sudo mount /dev/xvdf /data
    
    # ========== Persist Mount (Add to /etc/fstab) ==========
    # Get UUID
    sudo blkid /dev/xvdf
    
    # Add to /etc/fstab
    echo "UUID=your-uuid-here /data ext4 defaults,nofail 0 2" | sudo tee -a /etc/fstab
    
    # ========== Verify ==========
    df -h
    

    AMI (Amazon Machine Image)

    Create AMI

    # ========== Create AMI from Instance ==========
    aws ec2 create-image \
      --instance-id i-1234567890abcdef0 \
      --name "MyApp-v1.0-$(date +%Y%m%d)" \
      --description "MyApp production image" \
      --no-reboot
    
    # ========== Create AMI with Reboot ==========
    aws ec2 create-image \
      --instance-id i-1234567890abcdef0 \
      --name "MyApp-v1.0" \
      --reboot
    
    # ========== List AMIs ==========
    aws ec2 describe-images --owners self
    
    # ========== Deregister AMI ==========
    aws ec2 deregister-image --image-id ami-1234567890abcdef0
    
    # ========== Copy AMI to Another Region ==========
    aws ec2 copy-image \
      --source-region us-east-1 \
      --source-image-id ami-1234567890abcdef0 \
      --region us-west-2 \
      --name "MyApp-v1.0-west"
    

    Security Groups

    Security Group Commands

    # ========== Create Security Group ==========
    aws ec2 create-security-group \
      --group-name web-sg \
      --description "Security group for web servers" \
      --vpc-id vpc-1234567890abcdef0
    
    # ========== Add Inbound Rules ==========
    # Allow HTTP
    aws ec2 authorize-security-group-ingress \
      --group-id sg-1234567890abcdef0 \
      --protocol tcp \
      --port 80 \
      --cidr 0.0.0.0/0
    
    # Allow HTTPS
    aws ec2 authorize-security-group-ingress \
      --group-id sg-1234567890abcdef0 \
      --protocol tcp \
      --port 443 \
      --cidr 0.0.0.0/0
    
    # Allow SSH from specific IP
    aws ec2 authorize-security-group-ingress \
      --group-id sg-1234567890abcdef0 \
      --protocol tcp \
      --port 22 \
      --cidr 203.0.113.0/24
    
    # Allow traffic from another security group
    aws ec2 authorize-security-group-ingress \
      --group-id sg-1234567890abcdef0 \
      --protocol tcp \
      --port 3306 \
      --source-group sg-0987654321fedcba0
    
    # ========== Remove Inbound Rule ==========
    aws ec2 revoke-security-group-ingress \
      --group-id sg-1234567890abcdef0 \
      --protocol tcp \
      --port 22 \
      --cidr 0.0.0.0/0
    
    # ========== List Security Groups ==========
    aws ec2 describe-security-groups
    
    # ========== Delete Security Group ==========
    aws ec2 delete-security-group --group-id sg-1234567890abcdef0
    

    Key Pairs

    Key Pair Management

    # ========== Create Key Pair ==========
    aws ec2 create-key-pair \
      --key-name my-key-pair \
      --query 'KeyMaterial' \
      --output text > my-key-pair.pem
    
    # Set proper permissions
    chmod 400 my-key-pair.pem
    
    # ========== List Key Pairs ==========
    aws ec2 describe-key-pairs
    
    # ========== Delete Key Pair ==========
    aws ec2 delete-key-pair --key-name my-key-pair
    
    # ========== Import Existing Key ==========
    aws ec2 import-key-pair \
      --key-name imported-key \
      --public-key-material fileb://~/.ssh/id_rsa.pub
    

    Connect to Instance

    # ========== SSH Connection ==========
    ssh -i my-key-pair.pem ec2-user@54.123.45.67
    
    # For Ubuntu
    ssh -i my-key-pair.pem ubuntu@54.123.45.67
    
    # ========== SSH with Port Forwarding ==========
    ssh -i my-key-pair.pem -L 8080:localhost:80 ec2-user@54.123.45.67
    
    # ========== SCP File Transfer ==========
    # Upload file
    scp -i my-key-pair.pem file.txt ec2-user@54.123.45.67:/home/ec2-user/
    
    # Download file
    scp -i my-key-pair.pem ec2-user@54.123.45.67:/home/ec2-user/file.txt ./
    
    # ========== Session Manager (No SSH Key Needed) ==========
    aws ssm start-session --target i-1234567890abcdef0
    

    Elastic IP (Static IP)

    Elastic IP Commands

    # ========== Allocate Elastic IP ==========
    aws ec2 allocate-address --domain vpc
    
    # ========== Associate Elastic IP ==========
    aws ec2 associate-address \
      --instance-id i-1234567890abcdef0 \
      --allocation-id eipalloc-12345678
    
    # ========== Disassociate Elastic IP ==========
    aws ec2 disassociate-address --association-id eipassoc-12345678
    
    # ========== Release Elastic IP ==========
    aws ec2 release-address --allocation-id eipalloc-12345678
    
    # ========== List Elastic IPs ==========
    aws ec2 describe-addresses
    

    Auto Scaling

    Launch Template

    # ========== Create Launch Template ==========
    aws ec2 create-launch-template \
      --launch-template-name my-template \
      --version-description "v1" \
      --launch-template-data '{
        "ImageId": "ami-12345678",
        "InstanceType": "t3.micro",
        "KeyName": "my-key-pair",
        "SecurityGroupIds": ["sg-12345678"],
        "UserData": "IyEvYmluL2Jhc2gKeXVtIHVwZGF0ZSAteQ==",
        "TagSpecifications": [{
          "ResourceType": "instance",
          "Tags": [{
            "Key": "Name",
            "Value": "AutoScaled-Instance"
          }]
        }]
      }'
    
    # ========== Create Auto Scaling Group ==========
    aws autoscaling create-auto-scaling-group \
      --auto-scaling-group-name my-asg \
      --launch-template "LaunchTemplateName=my-template,Version=1" \
      --min-size 2 \
      --max-size 10 \
      --desired-capacity 2 \
      --vpc-zone-identifier "subnet-12345,subnet-67890" \
      --health-check-type ELB \
      --health-check-grace-period 300 \
      --tags "Key=Environment,Value=production,PropagateAtLaunch=true"
    
    # ========== Update Auto Scaling Group ==========
    aws autoscaling update-auto-scaling-group \
      --auto-scaling-group-name my-asg \
      --desired-capacity 5
    
    # ========== Create Scaling Policy ==========
    aws autoscaling put-scaling-policy \
      --auto-scaling-group-name my-asg \
      --policy-name scale-up \
      --policy-type TargetTrackingScaling \
      --target-tracking-configuration '{
        "PredefinedMetricSpecification": {
          "PredefinedMetricType": "ASGAverageCPUUtilization"
        },
        "TargetValue": 70.0
      }'
    

    Load Balancer Integration

    Application Load Balancer

    # ========== Create Target Group ==========
    aws elbv2 create-target-group \
      --name my-targets \
      --protocol HTTP \
      --port 80 \
      --vpc-id vpc-12345678 \
      --health-check-path /health \
      --health-check-interval-seconds 30
    
    # ========== Register Instances ==========
    aws elbv2 register-targets \
      --target-group-arn arn:aws:elasticloadbalancing:region:account:targetgroup/my-targets \
      --targets Id=i-1234567890abcdef0 Id=i-0987654321fedcba0
    
    # ========== Create Load Balancer ==========
    aws elbv2 create-load-balancer \
      --name my-alb \
      --subnets subnet-12345 subnet-67890 \
      --security-groups sg-12345678
    
    # ========== Create Listener ==========
    aws elbv2 create-listener \
      --load-balancer-arn arn:aws:elasticloadbalancing:region:account:loadbalancer/app/my-alb \
      --protocol HTTP \
      --port 80 \
      --default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:region:account:targetgroup/my-targets
    

    Monitoring and Logging

    CloudWatch Metrics

    # ========== Get CPU Utilization ==========
    aws cloudwatch get-metric-statistics \
      --namespace AWS/EC2 \
      --metric-name CPUUtilization \
      --dimensions Name=InstanceId,Value=i-1234567890abcdef0 \
      --start-time 2024-01-01T00:00:00Z \
      --end-time 2024-01-02T00:00:00Z \
      --period 3600 \
      --statistics Average
    
    # ========== Create Alarm ==========
    aws cloudwatch put-metric-alarm \
      --alarm-name high-cpu \
      --alarm-description "Alert when CPU exceeds 80%" \
      --metric-name CPUUtilization \
      --namespace AWS/EC2 \
      --statistic Average \
      --period 300 \
      --threshold 80 \
      --comparison-operator GreaterThanThreshold \
      --evaluation-periods 2 \
      --dimensions Name=InstanceId,Value=i-1234567890abcdef0 \
      --alarm-actions arn:aws:sns:region:account:my-topic
    

    Instance Metadata

    # ========== Get Instance ID ==========
    curl http://169.254.169.254/latest/meta-data/instance-id
    
    # ========== Get Instance Type ==========
    curl http://169.254.169.254/latest/meta-data/instance-type
    
    # ========== Get Public IP ==========
    curl http://169.254.169.254/latest/meta-data/public-ipv4
    
    # ========== Get User Data ==========
    curl http://169.254.169.254/latest/user-data
    
    # ========== IMDSv2 (More Secure) ==========
    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" http://169.254.169.254/latest/meta-data/instance-id
    

    Pricing Models

    On-Demand Instances

    Pay per hour/second with no commitment
    ├── Best for: Short-term, unpredictable workloads
    ├── Flexibility: Highest
    └── Cost: Highest per hour
    

    Reserved Instances

    1 or 3 year commitment for significant discount (up to 72%)
    ├── Standard RI: Fixed instance type and region
    ├── Convertible RI: Can change instance type
    └── Scheduled RI: Run on specific schedule
    

    Savings Plans

    Flexible pricing model (1 or 3 year commitment)
    ├── Compute Savings Plans: Up to 66% savings
    ├── EC2 Instance Savings Plans: Up to 72% savings
    └── Flexibility: Can change instance type, OS, region
    

    Spot Instances

    Up to 90% discount, can be interrupted
    ├── Best for: Fault-tolerant workloads
    ├── Use cases: Batch processing, data analysis
    └── Risk: Can be terminated with 2-minute warning
    

    Best Practices

    Security

  • Use IAM roles instead of storing credentials on instances
  • Enable encryption for EBS volumes
  • Use Security Groups as firewalls (least privilege)
  • Disable SSH password authentication (key-based only)
  • Use Systems Manager Session Manager instead of SSH
  • Enable VPC Flow Logs for network monitoring
  • Keep instances updated with security patches
  • Use private subnets for backend instances
  • Performance

  • Choose appropriate instance type for workload
  • Use Enhanced Networking (SR-IOV)
  • Enable EBS optimization for disk-intensive workloads
  • Use gp3 volumes for better price/performance
  • Place instances in multiple AZs for high availability
  • Use placement groups for low-latency applications
  • Cost Optimization

  • Right-size instances based on actual usage
  • Stop unused instances instead of leaving them running
  • Use Spot Instances for non-critical workloads
  • Purchase Reserved Instances or Savings Plans
  • Delete unattached EBS volumes
  • Delete old snapshots
  • Use Auto Scaling to match demand
  • Monitor with Cost Explorer and set budgets
  • Reliability

  • Use multiple Availability Zones
  • Create regular AMI backups
  • Automate with CloudFormation/Terraform
  • Enable termination protection for critical instances
  • Use Auto Scaling Groups for self-healing
  • Implement health checks
  • Use Load Balancers for traffic distribution
  • Troubleshooting

    Common Issues

    # ========== Cannot Connect via SSH ==========
    # Check security group allows port 22
    # Verify key pair permissions (chmod 400)
    # Check instance is running
    # Verify public IP/DNS
    
    # ========== Instance Status Checks Failing ==========
    # System status check: AWS infrastructure issue
    # Instance status check: OS/application issue
    aws ec2 describe-instance-status --instance-ids i-1234567890abcdef0
    
    # ========== Disk Space Full ==========
    df -h
    # Clean up logs, delete unused files
    # Increase EBS volume size
    
    # ========== High CPU Usage ==========
    top
    # Identify processes consuming CPU
    # Optimize application or upgrade instance type
    
    # ========== View System Logs ==========
    aws ec2 get-console-output --instance-id i-1234567890abcdef0
    

    Tips

  • Tag everything for organization and cost tracking
  • Use Systems Manager for centralized management
  • Enable detailed monitoring for critical instances
  • Automate with CloudFormation or Terraform
  • Use AWS Backup for automated backups
  • Implement proper naming conventions
  • Document your architecture
  • Regular security audits with AWS Config
  • Use AWS Cost Anomaly Detection
  • Leverage AWS Compute Optimizer for recommendations
  • Resources

  • AWS EC2 Documentation
  • EC2 Instance Types
  • EC2 Pricing Calculator
  • AWS Well-Architected Framework
  • EC2 Best Practices
  • Topics

    AWSEC2CloudInfrastructureDevOps

    Found This Helpful?

    If you have questions or suggestions for improving these notes, I'd love to hear from you.