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.