AWS
Essential AWS CLI commands and service configurations for cloud infrastructure management.
AWS
Essential AWS CLI commands and service configurations for cloud infrastructure management.
Overview
Amazon Web Services (AWS) provides on-demand cloud computing platforms and APIs. This cheatsheet covers core services for compute, storage, networking, identity management, containers, serverless, databases, and monitoring.
graph TB
subgraph AWS Cloud Architecture
subgraph Compute
EC2[EC2 Instances]
Lambda[Lambda Functions]
ECS[ECS/EKS Containers]
end
subgraph Storage
S3[S3 Buckets]
EBS[EBS Volumes]
end
subgraph Database
RDS[RDS Databases]
DynamoDB[DynamoDB Tables]
end
subgraph Networking
VPC[VPC]
ALB[Load Balancer]
R53[Route 53]
end
subgraph Security
IAM[IAM Users/Roles]
SG[Security Groups]
end
subgraph Monitoring
CW[CloudWatch]
end
end
Users[Users] --> R53
R53 --> ALB
ALB --> EC2
ALB --> ECS
EC2 --> S3
EC2 --> RDS
Lambda --> DynamoDB
Lambda --> S3
IAM --> EC2
IAM --> Lambda
CW --> EC2
CW --> Lambda
AWS CLI Configuration
Installation and Setup
# Install AWS CLI v2 (Linux)
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
# Verify installation
aws --version
# Configure default profile
aws configure
# AWS Access Key ID: AKIAIOSFODNN7EXAMPLE
# AWS Secret Access Key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
# Default region name: eu-west-1
# Default output format: json
Authentication Methods
# Configure named profile
aws configure --profile production
# Set profile for current session
export AWS_PROFILE=production
# Use profile for single command
aws s3 ls --profile production
# Configure with SSO
aws configure sso
aws sso login --profile sso-profile
# Assume role and export credentials
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/MyRole \
--role-session-name MySession \
--query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \
--output text
# Get caller identity (verify authentication)
aws sts get-caller-identity
Configuration Files
# ~/.aws/credentials
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
[production]
aws_access_key_id = AKIAI44QH8DHBEXAMPLE
aws_secret_access_key = je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY
# ~/.aws/config
[default]
region = eu-west-1
output = json
[profile production]
region = eu-west-2
output = table
role_arn = arn:aws:iam::123456789012:role/ProductionRole
source_profile = default
EC2 Essentials
Key Pairs
# Create key pair and save private key
aws ec2 create-key-pair \
--key-name my-key-pair \
--query 'KeyMaterial' \
--output text > my-key-pair.pem
# Set correct 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
Security Groups
# Create security group
aws ec2 create-security-group \
--group-name my-sg \
--description "My security group" \
--vpc-id vpc-1234567890abcdef0
# Add SSH access rule
aws ec2 authorize-security-group-ingress \
--group-id sg-903004f8 \
--protocol tcp \
--port 22 \
--cidr 10.0.0.0/8
# Add HTTP access
aws ec2 authorize-security-group-ingress \
--group-id sg-903004f8 \
--protocol tcp \
--port 80 \
--cidr 0.0.0.0/0
# List security groups
aws ec2 describe-security-groups --group-ids sg-903004f8
# Remove rule
aws ec2 revoke-security-group-ingress \
--group-id sg-903004f8 \
--protocol tcp \
--port 22 \
--cidr 10.0.0.0/8
Launching and Managing Instances
# Launch instance (enforce IMDSv2: HttpTokens=required mandates session
# tokens; HttpPutResponseHopLimit=1 stops containers/NAT'd workloads
# proxying the token — use 2 if containers legitimately need IMDS)
aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--instance-type t3.micro \
--key-name my-key-pair \
--security-group-ids sg-903004f8 \
--subnet-id subnet-6e7f829e \
--count 1 \
--metadata-options "HttpTokens=required,HttpPutResponseHopLimit=1,HttpEndpoint=enabled" \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=MyInstance}]'
# Require IMDSv2 on an existing instance
aws ec2 modify-instance-metadata-options \
--instance-id i-1234567890abcdef0 \
--http-tokens required \
--http-put-response-hop-limit 1 \
--http-endpoint enabled
# List instances
aws ec2 describe-instances \
--filters "Name=instance-state-name,Values=running" \
--query 'Reservations[].Instances[].{ID:InstanceId,Type:InstanceType,IP:PublicIpAddress,Name:Tags[?Key==`Name`].Value|[0]}'
# Get instance public IP
aws ec2 describe-instances \
--instance-ids i-1234567890abcdef0 \
--query 'Reservations[0].Instances[0].PublicIpAddress' \
--output text
# Stop instance
aws ec2 stop-instances --instance-ids i-1234567890abcdef0
# Start instance
aws ec2 start-instances --instance-ids i-1234567890abcdef0
# Terminate instance
aws ec2 terminate-instances --instance-ids i-1234567890abcdef0
# Connect via SSH
ssh -i my-key-pair.pem ec2-user@ec2-198-51-100-1.compute-1.amazonaws.com
AMI Management
# Create AMI from instance
aws ec2 create-image \
--instance-id i-1234567890abcdef0 \
--name "My-AMI-$(date +%Y%m%d)" \
--description "Backup AMI"
# List AMIs
aws ec2 describe-images \
--owners self \
--query 'Images[*].{ID:ImageId,Name:Name,Created:CreationDate}'
# Copy AMI to another region
aws ec2 copy-image \
--source-image-id ami-0abcdef1234567890 \
--source-region eu-west-1 \
--region eu-west-2 \
--name "Copied-AMI"
S3 Operations
Bucket Management
# Create bucket (with region)
aws s3 mb s3://my-unique-bucket-name --region eu-west-1
# Create bucket with versioning enabled
aws s3api create-bucket \
--bucket my-versioned-bucket \
--region eu-west-1 \
--create-bucket-configuration LocationConstraint=eu-west-1
aws s3api put-bucket-versioning \
--bucket my-versioned-bucket \
--versioning-configuration Status=Enabled
# List buckets
aws s3 ls
# List bucket contents
aws s3 ls s3://my-bucket/prefix/
# Delete empty bucket
aws s3 rb s3://my-bucket
# Delete bucket with contents
aws s3 rb s3://my-bucket --force
Upload and Download
# Upload single file
aws s3 cp myfile.txt s3://my-bucket/
# Upload with custom metadata
aws s3 cp myfile.txt s3://my-bucket/ \
--metadata '{"project":"demo","env":"prod"}'
# Download file
aws s3 cp s3://my-bucket/myfile.txt ./
# Upload directory recursively
aws s3 cp ./local-dir s3://my-bucket/remote-dir --recursive
# Download directory
aws s3 cp s3://my-bucket/remote-dir ./local-dir --recursive
# Sync local to S3 (only changed files)
aws s3 sync ./local-dir s3://my-bucket/remote-dir
# Sync S3 to local
aws s3 sync s3://my-bucket/remote-dir ./local-dir
# Sync with delete (mirror)
aws s3 sync ./local-dir s3://my-bucket/remote-dir --delete
# Sync excluding patterns
aws s3 sync ./local-dir s3://my-bucket/remote-dir \
--exclude "*.tmp" \
--exclude "*.log"
Lifecycle Rules
# Create lifecycle configuration file
cat > lifecycle.json << 'EOF'
{
"Rules": [
{
"ID": "MoveToGlacier",
"Status": "Enabled",
"Filter": {
"Prefix": "logs/"
},
"Transitions": [
{
"Days": 30,
"StorageClass": "STANDARD_IA"
},
{
"Days": 90,
"StorageClass": "GLACIER"
}
],
"Expiration": {
"Days": 365
}
}
]
}
EOF
# Apply lifecycle configuration
aws s3api put-bucket-lifecycle-configuration \
--bucket my-bucket \
--lifecycle-configuration file://lifecycle.json
# Get lifecycle configuration
aws s3api get-bucket-lifecycle-configuration --bucket my-bucket
Presigned URLs
# Generate presigned URL for download (1 hour expiry)
aws s3 presign s3://my-bucket/myfile.txt --expires-in 3600
# Note: `aws s3 presign` only generates GET (download) URLs.
# For upload (PUT) presigned URLs, use an SDK, e.g. boto3:
# boto3.client('s3').generate_presigned_url('put_object',
# Params={'Bucket': 'my-bucket', 'Key': 'upload-path/file.txt'},
# ExpiresIn=3600)
IAM Basics
IAM Architecture
graph TB
subgraph IAM Components
User[IAM User]
Group[IAM Group]
Role[IAM Role]
Policy[IAM Policy]
end
subgraph Resources
EC2[EC2]
S3[S3]
Lambda[Lambda]
end
User --> Group
Group --> Policy
User --> Policy
Role --> Policy
Policy --> EC2
Policy --> S3
Policy --> Lambda
EC2 -.->|Assume| Role
Lambda -.->|Assume| Role
User Management
# Create user
aws iam create-user --user-name john.smith
# Create access keys for user
aws iam create-access-key --user-name john.smith
# List users
aws iam list-users
# Add user to group
aws iam add-user-to-group \
--user-name john.smith \
--group-name developers
# Delete user
aws iam delete-user --user-name john.smith
Role Management
# Create trust policy file
cat > trust-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
# Create role
aws iam create-role \
--role-name MyEC2Role \
--assume-role-policy-document file://trust-policy.json
# Attach managed policy to role
aws iam attach-role-policy \
--role-name MyEC2Role \
--policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
# Create instance profile (for EC2)
aws iam create-instance-profile --instance-profile-name MyEC2Profile
# Add role to instance profile
aws iam add-role-to-instance-profile \
--instance-profile-name MyEC2Profile \
--role-name MyEC2Role
# Assume role (get temporary credentials)
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/MyRole \
--role-session-name MySession
Policy Management
# Create policy document
cat > s3-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
]
}
]
}
EOF
# Create custom policy
aws iam create-policy \
--policy-name MyS3Policy \
--policy-document file://s3-policy.json
# Attach policy to user
aws iam attach-user-policy \
--user-name john.smith \
--policy-arn arn:aws:iam::123456789012:policy/MyS3Policy
# List attached policies for user
aws iam list-attached-user-policies --user-name john.smith
# Get policy details
aws iam get-policy \
--policy-arn arn:aws:iam::123456789012:policy/MyS3Policy
VPC Fundamentals
VPC Architecture
graph TB
subgraph VPC 10.0.0.0/16
subgraph Public Subnet 10.0.1.0/24
NAT[NAT Gateway]
ALB[Application LB]
Bastion[Bastion Host]
end
subgraph Private Subnet 10.0.2.0/24
EC2_1[EC2 Instance]
EC2_2[EC2 Instance]
end
subgraph Private Subnet 10.0.3.0/24
RDS[(RDS Database)]
end
IGW[Internet Gateway]
end
Internet((Internet)) --> IGW
IGW --> ALB
IGW --> Bastion
ALB --> EC2_1
ALB --> EC2_2
EC2_1 --> NAT
EC2_2 --> NAT
NAT --> IGW
EC2_1 --> RDS
EC2_2 --> RDS
VPC and Subnet Creation
# Create VPC
aws ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=MyVPC}]'
# Enable DNS hostnames
aws ec2 modify-vpc-attribute \
--vpc-id vpc-1234567890abcdef0 \
--enable-dns-hostnames
# Create public subnet
aws ec2 create-subnet \
--vpc-id vpc-1234567890abcdef0 \
--cidr-block 10.0.1.0/24 \
--availability-zone eu-west-1a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=PublicSubnet}]'
# Create private subnet
aws ec2 create-subnet \
--vpc-id vpc-1234567890abcdef0 \
--cidr-block 10.0.2.0/24 \
--availability-zone eu-west-1a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=PrivateSubnet}]'
# Enable auto-assign public IP for public subnet
aws ec2 modify-subnet-attribute \
--subnet-id subnet-1234567890abcdef0 \
--map-public-ip-on-launch
Internet Gateway and NAT Gateway
# Create internet gateway
aws ec2 create-internet-gateway \
--tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=MyIGW}]'
# Attach to VPC
aws ec2 attach-internet-gateway \
--internet-gateway-id igw-1234567890abcdef0 \
--vpc-id vpc-1234567890abcdef0
# Allocate Elastic IP for NAT Gateway
aws ec2 allocate-address --domain vpc
# Create NAT gateway in public subnet
aws ec2 create-nat-gateway \
--subnet-id subnet-1234567890abcdef0 \
--allocation-id eipalloc-1234567890abcdef0 \
--tag-specifications 'ResourceType=natgateway,Tags=[{Key=Name,Value=MyNAT}]'
Route Tables
# Create route table
aws ec2 create-route-table \
--vpc-id vpc-1234567890abcdef0 \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=PublicRT}]'
# Add route to internet gateway (for public subnet)
aws ec2 create-route \
--route-table-id rtb-1234567890abcdef0 \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id igw-1234567890abcdef0
# Add route to NAT gateway (for private subnet)
aws ec2 create-route \
--route-table-id rtb-0987654321fedcba0 \
--destination-cidr-block 0.0.0.0/0 \
--nat-gateway-id nat-1234567890abcdef0
# Associate route table with subnet
aws ec2 associate-route-table \
--route-table-id rtb-1234567890abcdef0 \
--subnet-id subnet-1234567890abcdef0
# List route tables
aws ec2 describe-route-tables \
--filters "Name=vpc-id,Values=vpc-1234567890abcdef0"
ECS/EKS Basics
ECS Cluster Management
# Create ECS cluster
aws ecs create-cluster --cluster-name my-cluster
# List clusters
aws ecs list-clusters
# Describe cluster
aws ecs describe-clusters --clusters my-cluster
Task Definitions
# Register task definition
cat > task-def.json << 'EOF'
{
"family": "my-app",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"containerDefinitions": [
{
"name": "my-container",
"image": "nginx:latest",
"essential": true,
"portMappings": [
{
"containerPort": 80,
"protocol": "tcp"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-app",
"awslogs-region": "eu-west-1",
"awslogs-stream-prefix": "ecs"
}
}
}
]
}
EOF
aws ecs register-task-definition --cli-input-json file://task-def.json
# List task definitions
aws ecs list-task-definitions --family-prefix my-app
# Deregister task definition
aws ecs deregister-task-definition --task-definition my-app:1
ECS Services
# Create service
aws ecs create-service \
--cluster my-cluster \
--service-name my-service \
--task-definition my-app:1 \
--desired-count 2 \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[subnet-12345],securityGroups=[sg-12345],assignPublicIp=ENABLED}"
# Update service (deploy new task definition)
aws ecs update-service \
--cluster my-cluster \
--service my-service \
--task-definition my-app:2 \
--desired-count 3
# List services
aws ecs list-services --cluster my-cluster
# Describe service
aws ecs describe-services \
--cluster my-cluster \
--services my-service
EKS Cluster Management
# Create EKS cluster
aws eks create-cluster \
--name my-eks-cluster \
--role-arn arn:aws:iam::123456789012:role/EKSClusterRole \
--resources-vpc-config subnetIds=subnet-12345,subnet-67890,securityGroupIds=sg-12345
# Update kubeconfig for kubectl
aws eks update-kubeconfig --name my-eks-cluster --region eu-west-1
# List clusters
aws eks list-clusters
# Describe cluster
aws eks describe-cluster --name my-eks-cluster
# Create node group
aws eks create-nodegroup \
--cluster-name my-eks-cluster \
--nodegroup-name my-nodes \
--node-role arn:aws:iam::123456789012:role/EKSNodeRole \
--subnets subnet-12345 subnet-67890 \
--instance-types t3.medium \
--scaling-config minSize=1,maxSize=3,desiredSize=2
Lambda Functions
Serverless Architecture
sequenceDiagram
participant Client
participant APIGW as API Gateway
participant Lambda
participant DDB as DynamoDB
participant S3
participant CW as CloudWatch
Client->>APIGW: HTTP Request
APIGW->>Lambda: Invoke Function
Lambda->>DDB: Read/Write Data
Lambda->>S3: Store/Retrieve Files
Lambda->>CW: Log Events
Lambda-->>APIGW: Response
APIGW-->>Client: HTTP Response
Creating and Managing Functions
# Create deployment package
zip function.zip lambda_function.py
# Create Lambda function
# (python3.11 runs on Amazon Linux 2; prefer the AL2023-based
# python3.12/3.13 runtimes for new functions)
aws lambda create-function \
--function-name my-function \
--runtime python3.13 \
--role arn:aws:iam::123456789012:role/LambdaExecutionRole \
--handler lambda_function.handler \
--zip-file fileb://function.zip \
--timeout 30 \
--memory-size 256 \
--environment "Variables={ENV=production,LOG_LEVEL=INFO}"
# Update function code
aws lambda update-function-code \
--function-name my-function \
--zip-file fileb://function.zip
# Update function configuration
aws lambda update-function-configuration \
--function-name my-function \
--timeout 60 \
--memory-size 512
# List functions
aws lambda list-functions
# Get function details
aws lambda get-function --function-name my-function
Invoking Functions
# Invoke synchronously
aws lambda invoke \
--function-name my-function \
--payload '{"key": "value"}' \
--cli-binary-format raw-in-base64-out \
response.json
# Invoke asynchronously
aws lambda invoke \
--function-name my-function \
--invocation-type Event \
--payload '{"key": "value"}' \
--cli-binary-format raw-in-base64-out \
response.json
# Invoke with log output
aws lambda invoke \
--function-name my-function \
--payload '{"key": "value"}' \
--cli-binary-format raw-in-base64-out \
--log-type Tail \
--query 'LogResult' \
--output text response.json | base64 --decode
Event Source Mappings
# Create SQS trigger
aws lambda create-event-source-mapping \
--function-name my-function \
--event-source-arn arn:aws:sqs:eu-west-1:123456789012:my-queue \
--batch-size 10
# Create DynamoDB Streams trigger
aws lambda create-event-source-mapping \
--function-name my-function \
--event-source-arn arn:aws:dynamodb:eu-west-1:123456789012:table/my-table/stream/2023-01-01T00:00:00.000 \
--batch-size 100 \
--starting-position LATEST
# List event source mappings
aws lambda list-event-source-mappings --function-name my-function
Function Versions and Aliases
# Publish version
aws lambda publish-version \
--function-name my-function \
--description "Production release v1.0"
# Create alias
aws lambda create-alias \
--function-name my-function \
--name prod \
--function-version 1
# Update alias to new version
aws lambda update-alias \
--function-name my-function \
--name prod \
--function-version 2
CloudWatch Logs and Metrics
Log Management
# Create log group
aws logs create-log-group --log-group-name /aws/my-app
# Set retention policy
aws logs put-retention-policy \
--log-group-name /aws/my-app \
--retention-in-days 30
# List log groups
aws logs describe-log-groups --log-group-name-prefix /aws/
# Get log streams
aws logs describe-log-streams \
--log-group-name /aws/lambda/my-function \
--order-by LastEventTime \
--descending
# Get log events
aws logs get-log-events \
--log-group-name /aws/lambda/my-function \
--log-stream-name '2023/01/01/[$LATEST]abc123'
# Filter log events (search logs)
aws logs filter-log-events \
--log-group-name /aws/lambda/my-function \
--filter-pattern "ERROR" \
--start-time $(date -d '1 hour ago' +%s000)
# Tail logs in real-time (built into AWS CLI v2)
aws logs tail /aws/lambda/my-function --follow
CloudWatch Insights Queries
# Run Insights query
aws logs start-query \
--log-group-name /aws/lambda/my-function \
--start-time $(date -d '1 day ago' +%s) \
--end-time $(date +%s) \
--query-string 'fields @timestamp, @message | filter @message like /ERROR/ | sort @timestamp desc | limit 20'
# Get query results
aws logs get-query-results --query-id abc123-def456
Custom Metrics
# Put custom metric
aws cloudwatch put-metric-data \
--namespace "MyApp" \
--metric-name "ProcessedItems" \
--value 100 \
--unit Count \
--dimensions Environment=production,Service=api
# Get metric statistics
aws cloudwatch get-metric-statistics \
--namespace AWS/Lambda \
--metric-name Invocations \
--dimensions Name=FunctionName,Value=my-function \
--start-time $(date -d '1 hour ago' -u +%Y-%m-%dT%H:%M:%SZ) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
--period 300 \
--statistics Sum Average
CloudWatch Alarms
# Create alarm
aws cloudwatch put-metric-alarm \
--alarm-name high-cpu-alarm \
--alarm-description "Alarm when CPU exceeds 80%" \
--metric-name CPUUtilization \
--namespace AWS/EC2 \
--statistic Average \
--period 300 \
--threshold 80 \
--comparison-operator GreaterThanThreshold \
--dimensions Name=InstanceId,Value=i-1234567890abcdef0 \
--evaluation-periods 2 \
--alarm-actions arn:aws:sns:eu-west-1:123456789012:my-topic
# List alarms
aws cloudwatch describe-alarms --alarm-name-prefix "high-"
# Delete alarm
aws cloudwatch delete-alarms --alarm-names high-cpu-alarm
DynamoDB Basics
Table Management
# Create table
aws dynamodb create-table \
--table-name Users \
--attribute-definitions \
AttributeName=userId,AttributeType=S \
AttributeName=email,AttributeType=S \
--key-schema \
AttributeName=userId,KeyType=HASH \
--global-secondary-indexes \
"IndexName=EmailIndex,KeySchema=[{AttributeName=email,KeyType=HASH}],Projection={ProjectionType=ALL},ProvisionedThroughput={ReadCapacityUnits=5,WriteCapacityUnits=5}" \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5
# Create on-demand table
aws dynamodb create-table \
--table-name Orders \
--attribute-definitions AttributeName=orderId,AttributeType=S \
--key-schema AttributeName=orderId,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
# List tables
aws dynamodb list-tables
# Describe table
aws dynamodb describe-table --table-name Users
# Delete table
aws dynamodb delete-table --table-name Users
Read and Write Operations
# Put item
aws dynamodb put-item \
--table-name Users \
--item '{
"userId": {"S": "user123"},
"email": {"S": "john@example.com"},
"name": {"S": "John Smith"},
"age": {"N": "30"},
"active": {"BOOL": true}
}'
# Get item
aws dynamodb get-item \
--table-name Users \
--key '{"userId": {"S": "user123"}}'
# Update item
aws dynamodb update-item \
--table-name Users \
--key '{"userId": {"S": "user123"}}' \
--update-expression "SET age = :newage, #n = :newname" \
--expression-attribute-names '{"#n": "name"}' \
--expression-attribute-values '{":newage": {"N": "31"}, ":newname": {"S": "John D. Smith"}}'
# Delete item
aws dynamodb delete-item \
--table-name Users \
--key '{"userId": {"S": "user123"}}'
# Batch write items
aws dynamodb batch-write-item --request-items file://batch-items.json
Queries and Scans
# Query by partition key
aws dynamodb query \
--table-name Users \
--key-condition-expression "userId = :uid" \
--expression-attribute-values '{":uid": {"S": "user123"}}'
# Query with filter
aws dynamodb query \
--table-name Orders \
--key-condition-expression "customerId = :cid" \
--filter-expression "orderStatus = :status" \
--expression-attribute-values '{
":cid": {"S": "cust123"},
":status": {"S": "PENDING"}
}'
# Query GSI
aws dynamodb query \
--table-name Users \
--index-name EmailIndex \
--key-condition-expression "email = :email" \
--expression-attribute-values '{":email": {"S": "john@example.com"}}'
# Scan with filter (use sparingly)
aws dynamodb scan \
--table-name Users \
--filter-expression "age > :minage" \
--expression-attribute-values '{":minage": {"N": "25"}}'
RDS Basics
Instance Management
# Create RDS instance
aws rds create-db-instance \
--db-instance-identifier my-postgres \
--db-instance-class db.t3.micro \
--engine postgres \
--engine-version 17.9 \
--master-username admin \
--master-user-password 'MySecurePassword123!' \
--allocated-storage 20 \
--storage-type gp3 \
--vpc-security-group-ids sg-12345678 \
--db-subnet-group-name my-subnet-group \
--backup-retention-period 7 \
--multi-az \
--publicly-accessible
# List instances
aws rds describe-db-instances \
--query 'DBInstances[*].{ID:DBInstanceIdentifier,Status:DBInstanceStatus,Engine:Engine,Endpoint:Endpoint.Address}'
# Get connection endpoint
aws rds describe-db-instances \
--db-instance-identifier my-postgres \
--query 'DBInstances[0].Endpoint.Address' \
--output text
# Modify instance
aws rds modify-db-instance \
--db-instance-identifier my-postgres \
--db-instance-class db.t3.small \
--apply-immediately
# Stop instance
aws rds stop-db-instance --db-instance-identifier my-postgres
# Start instance
aws rds start-db-instance --db-instance-identifier my-postgres
# Delete instance
aws rds delete-db-instance \
--db-instance-identifier my-postgres \
--skip-final-snapshot
Subnet Groups
# Create DB subnet group
aws rds create-db-subnet-group \
--db-subnet-group-name my-subnet-group \
--db-subnet-group-description "My DB subnet group" \
--subnet-ids subnet-12345678 subnet-87654321
# List subnet groups
aws rds describe-db-subnet-groups
Backups and Snapshots
# Create manual snapshot
aws rds create-db-snapshot \
--db-instance-identifier my-postgres \
--db-snapshot-identifier my-postgres-backup-$(date +%Y%m%d)
# List snapshots
aws rds describe-db-snapshots \
--db-instance-identifier my-postgres
# Restore from snapshot
aws rds restore-db-instance-from-db-snapshot \
--db-instance-identifier my-postgres-restored \
--db-snapshot-identifier my-postgres-backup-20230101
# Copy snapshot to another region
aws rds copy-db-snapshot \
--source-db-snapshot-identifier arn:aws:rds:eu-west-1:123456789012:snapshot:my-snapshot \
--target-db-snapshot-identifier my-snapshot-copy \
--source-region eu-west-1 \
--region eu-west-2
Parameter Groups
# Create parameter group
aws rds create-db-parameter-group \
--db-parameter-group-name my-postgres-params \
--db-parameter-group-family postgres17 \
--description "Custom PostgreSQL parameters"
# Modify parameters
aws rds modify-db-parameter-group \
--db-parameter-group-name my-postgres-params \
--parameters "ParameterName=max_connections,ParameterValue=200,ApplyMethod=pending-reboot" \
"ParameterName=shared_buffers,ParameterValue=256MB,ApplyMethod=pending-reboot"
# Apply parameter group to instance
aws rds modify-db-instance \
--db-instance-identifier my-postgres \
--db-parameter-group-name my-postgres-params \
--apply-immediately
Quick Reference
Essential Commands
| Task | Command |
|---|---|
| Configure CLI | aws configure |
| Verify identity | aws sts get-caller-identity |
| Switch profile | export AWS_PROFILE=myprofile |
| List EC2 instances | aws ec2 describe-instances --query 'Reservations[].Instances[].{ID:InstanceId,State:State.Name}' |
| SSH to EC2 | ssh -i key.pem ec2-user@<ip> |
| List S3 buckets | aws s3 ls |
| Sync to S3 | aws s3 sync ./local s3://bucket/path |
| Invoke Lambda | aws lambda invoke --function-name fn --payload '{}' out.json |
| Tail CloudWatch logs | aws logs tail /aws/lambda/fn --follow |
| Get RDS endpoint | aws rds describe-db-instances --db-instance-identifier mydb --query 'DBInstances[0].Endpoint.Address' |
| Query DynamoDB | aws dynamodb query --table-name tbl --key-condition-expression "pk = :v" --expression-attribute-values '{":v":{"S":"val"}}' |
Common Filters and Queries
# Get running EC2 instance IDs
aws ec2 describe-instances \
--filters "Name=instance-state-name,Values=running" \
--query 'Reservations[].Instances[].InstanceId' \
--output text
# Get Lambda function names
aws lambda list-functions \
--query 'Functions[].FunctionName' \
--output text
# Get security group rules
aws ec2 describe-security-groups \
--group-ids sg-12345678 \
--query 'SecurityGroups[0].IpPermissions'
# Get latest Amazon Linux 2023 AMI (via SSM public parameter)
aws ssm get-parameter \
--name /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64 \
--query 'Parameter.Value' \
--output text
# Or via describe-images (AL2 reached end of life on 30 June 2026)
aws ec2 describe-images \
--owners amazon \
--filters "Name=name,Values=al2023-ami-*-x86_64" \
--query 'Images | sort_by(@, &CreationDate) | [-1].ImageId' \
--output text
Common Issues and Solutions
| Issue | Cause | Solution |
|---|---|---|
Unable to locate credentials |
No credentials configured | Run aws configure or set AWS_PROFILE |
An error occurred (AccessDenied) |
Insufficient IAM permissions | Check IAM policies, verify user/role has required permissions |
An error occurred (InvalidParameterValue) |
Wrong region or resource ID | Verify --region flag matches resource location |
Request limit exceeded |
API throttling | Implement exponential backoff, use pagination |
| EC2 instance unreachable | Security group or VPC config | Check security group rules, verify route tables and IGW |
| S3 bucket already exists | Bucket names are globally unique | Choose a different, unique bucket name |
| Lambda timeout | Execution time exceeded | Increase timeout (max 15 min), optimise code |
| RDS connection refused | Security group or network | Add inbound rule for port 5432/3306, check VPC routing |
DynamoDB ProvisionedThroughputExceededException |
Capacity exceeded | Enable auto-scaling or switch to on-demand |
| ECS task stuck in PENDING | No resources or image pull failure | Check cluster capacity, verify image name and ECR permissions |
Debugging Commands
# Check AWS CLI configuration
aws configure list
# Verify current identity
aws sts get-caller-identity
# Test IAM permissions
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:user/john \
--action-names s3:GetObject \
--resource-arns arn:aws:s3:::my-bucket/*
# Check VPC flow logs for network issues
aws logs filter-log-events \
--log-group-name /aws/vpc/flowlogs \
--filter-pattern "REJECT"
# Get CloudTrail events for API troubleshooting
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=RunInstances
Related Topics
To extend your AWS knowledge and build comprehensive cloud infrastructure skills, consider exploring these related topics:
- Terraform - Infrastructure as code for provisioning AWS resources declaratively
- GCP/Azure - Alternative cloud platforms for multi-cloud strategies
- Container Security - Securing ECS/EKS workloads with image scanning and runtime protection
- Prometheus/Grafana - Enhanced monitoring and visualisation beyond CloudWatch
- Ansible - Configuration management for EC2 instances and hybrid environments
- CI/CD Patterns - Automated deployment pipelines with CodePipeline, CodeBuild, or Jenkins