ec2

AWS CLI EC2 Cheatsheet: Manage Amazon EC2 instances, AMIs, EBS volumes, security groups, and subnets. Quickly find commands for common EC2 tasks.

AWS CLI EC2 Cheatsheet

EC2 AWS CLI Commands

A comprehensive cheatsheet for managing Amazon EC2 instances using the AWS Command Line Interface (CLI). Find essential commands for EC2, AMI, EBS, Security Groups, and Subnets.

EC2 Instance Management

Run Instances

Create the EBS Mapping:

[
    {
        "DeviceName": "/dev/sda1",
        "Ebs": {
            "DeleteOnTermination": true,
            "VolumeSize": 50,
            "VolumeType": "standard"
        }
    }
]

Get the latest AMI (ecs optimized in this case):

AWS_AMI_ID="$(aws --profile prod ssm get-parameter --name '/aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id' | jq -r '.Parameter.Value')"

Create a EC2 instance:

aws --profile default ec2 run-instances --image-id ${AWS_AMI_ID} --count 1 \
     --instance-type t2.micro --key-name mykey \
     --subnet-id subnet-123456789 --security-group-ids ${AWS_SG_ID} \
     --block-device-mappings file://ebs_mapping.json \
     --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=MyEC2}]' 'ResourceType=volume,Tags=[{Key=Name,Value=MyEC2}]' \
     --iam-instance-profile '{"Name":"my-instance-role"}' \
     --user-data file://userdata.txt

AMI Management

Create AMI

Create a AMI:

$ aws --profile dev ec2 create-image --instance-id $INSTANCE_ID --name "test-ami_$(date +%F)" --description "test ami created on $(date +%F)" --no-reboot
ami-xxxxxxxx

Describe AMI Creation Status:

$ aws --profile dev ec2 describe-images --image-ids ami-xxxxxxxx --query "Images[*].{State:State}" --output text
# pending (or available)

EC2 Instance Querying

Query EC2 Instances

Get the EC2 InstanceID by Tag Name:

$ aws --profile dev ec2 describe-instances --filters "Name=tag:Name,Values=test-instance" --query "Reservations[*].Instances[*].{Instance:InstanceId}" --output text
i-07043caxxxxxxxxxx

Show InstanceId, State, PrivateDnsName of a given PrivateDnsName:

$ aws --profile dev ec2 describe-instances --query 'Reservations[*].Instances[?PrivateDnsName==`ip-192-168-42-186.eu-west-1.compute.internal`].[InstanceId,PrivateDnsName,State.Name][][]'
[
    "i-0d016de17a46d5178",
    "ip-192-168-42-186.eu-west-1.compute.internal",
    "running"
]

Show the EC2 Instances Tag:Name value:

$ aws --region eu-west-1 ec2 describe-tags --filters "Name=resource-id,Values=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)" --query 'Tags[?Key==`Name`].Value' --output text
my-ec2-instance

Show EC2 instances in table format:

aws ec2 describe-instances \
  --query "Reservations[*].Instances[*].{Name:Tags[?Key=='Name']|[0].Value,InstanceID:InstanceId,Status:State.Name}" \
  --filters "Name=instance-state-name,Values=running" "Name=tag:Name,Values='*'" \
  --output table

More Examples: - https://ripon-banik.medium.com/top-10-examples-of-aws-cli-query-e717524dc346

EBS Volume Management

Modify EBS Volume

Modify a EBS volume from GP2 to GP3:

$ aws ec2 modify-volume --volume-type gp3 --volume-id vol-0xxxxxxxxxxxxxxxx
{
    "VolumeModification": {
        "VolumeId": "vol-0xxxxxxxxxxxxxxxx",
        "ModificationState": "modifying",
        "TargetSize": 8,
        "TargetIops": 3000,
        "TargetVolumeType": "gp3",
        "TargetThroughput": 125,
        "TargetMultiAttachEnabled": false,
        "OriginalSize": 8,
        "OriginalIops": 100,
        "OriginalVolumeType": "gp2",
        "OriginalMultiAttachEnabled": false,
        "Progress": 0,
        "StartTime": "2022-03-28T11:30:52+00:00"
    }
}

Describe Status of Modication:

$ aws ec2 describe-volumes --volume-id vol-0xxxxxxxxxxxxxxxx
{
    "Volumes": [
        {
            "Attachments": [
                {
                    "AttachTime": "2021-06-08T16:02:40+00:00",
                    "Device": "/dev/sda1",
                    "InstanceId": "i-089ef13267c44a4a9",
                    "State": "attached",
                    "VolumeId": "vol-0xxxxxxxxxxxxxxxx",
                    "DeleteOnTermination": true
                }
            ],
            "AvailabilityZone": "eu-west-1c",
            "CreateTime": "2021-06-08T16:02:40.226000+00:00",
            "Encrypted": false,
            "Size": 8,
            "SnapshotId": "snap-0xxxxxxxxxxxxxxxx",
            "State": "in-use",
            "VolumeId": "vol-0xxxxxxxxxxxxxxxx",
            "Iops": 3000,
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "my-instance"
                },
                {
                    "Key": "Environment",
                    "Value": "dev"
                }
            ],
            "VolumeType": "gp3",
            "MultiAttachEnabled": false,
            "Throughput": 125
        }
    ]
}

To only see the status:

$ aws ec2 describe-volumes --volume-id vol-0xxxxxxxxxxxxxxxx | jq -r '.Volumes[].State'
in-use

Security Group Management

Describe Security Group

Describe Security Group:

$ aws --profile dev ec2 describe-security-groups --group-ids "sg-00000000000000000"
{
    "SecurityGroups": [
        {
            "IpPermissionsEgress": [],
            "Description": "",
             "Tags": [],
             "IpPermissions": [],
             "GroupName": "",
             "VpcId": "",
             "OwnerId": "",
             "GroupId": ""
        }
    ]
}

View Ingress Rules:

$ aws --profile dev ec2 describe-security-groups --group-ids "sg-00000000000000000" | jq -r .SecurityGroups[].IpPermissions
[
  {
    "PrefixListIds": [],
    "FromPort": 22,
    "IpRanges": [
      {
        "CidrIp": "10.1.10.0/24"
      }
    ],
    "ToPort": 22,
    "IpProtocol": "tcp",
    "UserIdGroupPairs": [],
    "Ipv6Ranges": []
  }
]

Allow Ingress Rule:

$ aws --profile dev ec2 authorize-security-group-ingress --group-id sg-00000000000000000 --protocol tcp --port 3306 --cidr 10.1.10.0/16

Subnet Management

List Subnets

List the subnets containing "private" in tags:

$ aws --profile prod ec2 describe-subnets --filters "Name=vpc-id,Values=vpc-xxxxxx" | jq -r '.Subnets[] | select(.Tags[].Value | contains("private"))'
{
  "AvailabilityZone": "eu-west-1c",
  "AvailabilityZoneId": "euw1-az3",
  "AvailableIpAddressCount": 4089,
  "CidrBlock": "172.31.80.0/20",
  "DefaultForAz": false,
  "MapPublicIpOnLaunch": false,
  "State": "available",
  "SubnetId": "subnet-xxxxxxxx",
  "VpcId": "vpc-xxxxxxx",
  "OwnerId": "xxxxxxxxxxx",
  "AssignIpv6AddressOnCreation": false,
  "Ipv6CidrBlockAssociationSet": [],
  "Tags": [
    {
      "Key": "Name",
      "Value": "prod-private-subnet-1c"
    }
  ],
  "SubnetArn": "arn:aws:ec2:eu-west-1:xxxxxxxxx:subnet/subnet-xxxxxxxx"
}
{
...

Get only the subnetids:

$ aws --profile prod ec2 describe-subnets --filters "Name=vpc-id,Values=vpc-xxxxxxxx" | jq -r '.Subnets[] | select(.Tags[].Value | contains("private")) .SubnetId'
subnet-xxxxxx
subnet-xxxxxx
subnet-xxxxxx