View a markdown version of this page

Creating and managing Amazon EBS volumes - Amazon Elastic Compute Cloud
Services or capabilities described in Amazon Web Services documentation might vary by Region. To see the differences applicable to the China Regions, see Getting Started with Amazon Web Services in China (PDF).

Creating and managing Amazon EBS volumes

The following code example shows how to:

  • Create an EBS volume

  • Check volume status

  • Create an EC2 instance (optional)

  • Attach a volume to an EC2 instance

  • Clean up resources

Bash
Amazon CLI with Bash script
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the Sample developer tutorials repository.

#!/bin/bash # Script to create and manage Amazon EBS volumes # This script demonstrates how to create an EBS volume and attach it to an EC2 instance # It can also create a test EC2 instance if needed # Set up logging LOG_FILE="ebs-volume-creation.log" exec > >(tee -a "$LOG_FILE") 2>&1 echo "Starting EBS volume creation script at $(date)" echo "==============================================" # Function to handle errors handle_error() { echo "ERROR: $1" echo "Resources created:" if [ -n "$VOLUME_ID" ]; then echo "- EBS Volume: $VOLUME_ID" fi if [ -n "$INSTANCE_ID" ]; then echo "- EC2 Instance: $INSTANCE_ID" fi if [ -n "$SG_ID" ]; then echo "- Security Group: $SG_ID" fi echo "" echo "===========================================" echo "CLEANUP CONFIRMATION" echo "===========================================" echo "An error occurred. Do you want to clean up created resources? (y/n): " read -r CLEANUP_CHOICE if [[ "$CLEANUP_CHOICE" =~ ^[Yy]$ ]]; then cleanup_resources else echo "Resources were not cleaned up. You will need to delete them manually." fi exit 1 } # Function to clean up resources cleanup_resources() { echo "Cleaning up resources..." if [ -n "$VOLUME_ID" ] && [ "$ATTACHED" = true ]; then echo "Detaching volume $VOLUME_ID..." aws ec2 detach-volume --volume-id "$VOLUME_ID" # Wait for volume to be detached echo "Waiting for volume to be detached..." aws ec2 wait volume-available --volume-ids "$VOLUME_ID" fi if [ -n "$VOLUME_ID" ]; then echo "Deleting volume $VOLUME_ID..." aws ec2 delete-volume --volume-id "$VOLUME_ID" fi if [ -n "$INSTANCE_ID" ] && [ "$CREATED_INSTANCE" = true ]; then echo "Terminating instance $INSTANCE_ID..." aws ec2 terminate-instances --instance-ids "$INSTANCE_ID" echo "Waiting for instance to terminate..." aws ec2 wait instance-terminated --instance-ids "$INSTANCE_ID" fi # Clean up security group if created if [ -n "$SG_ID" ] && [ "$CREATED_INSTANCE" = true ]; then echo "Deleting security group $SG_ID..." # Wait a bit for instance termination to complete sleep 10 aws ec2 delete-security-group --group-id "$SG_ID" 2>/dev/null || echo "Security group may have dependencies, delete manually if needed" fi echo "Cleanup completed." } # Function to get available instance type get_available_instance_type() { local region=$1 # Try instance types in order of preference (cheapest first) local instance_types=("t3.nano" "t3.micro" "t2.micro" "t2.nano") for instance_type in "${instance_types[@]}"; do local available=$(aws ec2 describe-instance-type-offerings \ --region "$region" \ --filters "Name=instance-type,Values=$instance_type" \ --query "length(InstanceTypeOfferings)" \ --output text) if [ "$available" -gt 0 ]; then echo "$instance_type" return 0 fi done # If none of the preferred types are available, get any available type local fallback_type=$(aws ec2 describe-instance-type-offerings \ --region "$region" \ --query "InstanceTypeOfferings[0].InstanceType" \ --output text) if [ "$fallback_type" != "None" ] && [ -n "$fallback_type" ]; then echo "$fallback_type" return 0 fi return 1 } # Get current region REGION=$(aws configure get region) if [ -z "$REGION" ]; then REGION=$(aws ec2 describe-availability-zones --query "AvailabilityZones[0].RegionName" --output text) fi echo "Using region: $REGION" # Get available Availability Zones echo "Retrieving available Availability Zones..." AZ=$(aws ec2 describe-availability-zones --filters "Name=state,Values=available" --query "AvailabilityZones[0].ZoneName" --output text) if [ -z "$AZ" ]; then handle_error "Failed to retrieve Availability Zones" fi echo "Using Availability Zone: $AZ" # Create a gp3 volume echo "Creating a 10 GiB gp3 volume in $AZ..." VOLUME_ID=$(aws ec2 create-volume \ --volume-type gp3 \ --size 10 \ --availability-zone "$AZ" \ --tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=EBSTutorialVolume},{Key=Purpose,Value=Tutorial}]' \ --query 'VolumeId' \ --output text) if [ -z "$VOLUME_ID" ]; then handle_error "Failed to create EBS volume" fi echo "Volume created with ID: $VOLUME_ID" # Wait for volume to become available echo "Waiting for volume to become available..." aws ec2 wait volume-available --volume-ids "$VOLUME_ID" if [ $? -ne 0 ]; then handle_error "Volume did not become available" fi # Check volume details echo "Retrieving volume details..." aws ec2 describe-volumes --volume-ids "$VOLUME_ID" # Ask if user wants to attach the volume to an instance echo "" echo "===========================================" echo "VOLUME ATTACHMENT" echo "===========================================" echo "Do you want to attach this volume to an EC2 instance? (y/n): " read -r ATTACH_CHOICE ATTACHED=false CREATED_INSTANCE=false INSTANCE_ID="" SG_ID="" if [[ "$ATTACH_CHOICE" =~ ^[Yy]$ ]]; then # List available instances in the same AZ echo "Retrieving EC2 instances in $AZ..." INSTANCES_COUNT=$(aws ec2 describe-instances \ --filters "Name=availability-zone,Values=$AZ" "Name=instance-state-name,Values=running" \ --query "length(Reservations[].Instances[])" \ --output text) # Check if there are any running instances in the AZ if [ "$INSTANCES_COUNT" -eq 0 ]; then echo "No running instances found in $AZ." echo "" echo "Would you like to create a test EC2 instance? (y/n): " read -r CREATE_INSTANCE_CHOICE if [[ "$CREATE_INSTANCE_CHOICE" =~ ^[Yy]$ ]]; then # Get available instance type echo "Finding available instance type for region $REGION..." INSTANCE_TYPE=$(get_available_instance_type "$REGION") if [ $? -ne 0 ] || [ -z "$INSTANCE_TYPE" ]; then handle_error "No suitable instance type found in region $REGION" fi echo "Using instance type: $INSTANCE_TYPE" # Get the latest Amazon Linux 2 AMI echo "Finding the latest Amazon Linux 2 AMI..." AMI_ID=$(aws ec2 describe-images \ --owners amazon \ --filters "Name=name,Values=amzn2-ami-hvm-*-x86_64-gp2" "Name=state,Values=available" \ --query "sort_by(Images, &CreationDate)[-1].ImageId" \ --output text) if [ -z "$AMI_ID" ]; then handle_error "Failed to find a suitable AMI" fi echo "Using AMI: $AMI_ID" # Check if a default VPC exists DEFAULT_VPC_ID=$(aws ec2 describe-vpcs \ --filters "Name=isDefault,Values=true" \ --query "Vpcs[0].VpcId" \ --output text) if [ "$DEFAULT_VPC_ID" = "None" ] || [ -z "$DEFAULT_VPC_ID" ]; then handle_error "No default VPC found. Please create a VPC and subnet before running this script." fi # Get a subnet in the selected AZ SUBNET_ID=$(aws ec2 describe-subnets \ --filters "Name=vpc-id,Values=$DEFAULT_VPC_ID" "Name=availability-zone,Values=$AZ" \ --query "Subnets[0].SubnetId" \ --output text) if [ -z "$SUBNET_ID" ] || [ "$SUBNET_ID" = "None" ]; then handle_error "No subnet found in $AZ. Please create a subnet before running this script." fi echo "Using subnet: $SUBNET_ID" # Create a security group that allows SSH SG_NAME="EBSTutorialSG-$(date +%s)" SG_ID=$(aws ec2 create-security-group \ --group-name "$SG_NAME" \ --description "Security group for EBS tutorial" \ --vpc-id "$DEFAULT_VPC_ID" \ --query "GroupId" \ --output text) if [ -z "$SG_ID" ]; then handle_error "Failed to create security group" fi echo "Created security group: $SG_ID" # Add a rule to allow SSH aws ec2 authorize-security-group-ingress \ --group-id "$SG_ID" \ --protocol tcp \ --port 22 \ --cidr 0.0.0.0/0 echo "Added SSH rule to security group" # Create the instance echo "Creating EC2 instance in $AZ with instance type $INSTANCE_TYPE..." INSTANCE_ID=$(aws ec2 run-instances \ --image-id "$AMI_ID" \ --instance-type "$INSTANCE_TYPE" \ --subnet-id "$SUBNET_ID" \ --security-group-ids "$SG_ID" \ --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=EBSTutorialInstance},{Key=Purpose,Value=Tutorial}]' \ --query "Instances[0].InstanceId" \ --output text) if [ -z "$INSTANCE_ID" ]; then handle_error "Failed to create EC2 instance" fi CREATED_INSTANCE=true echo "Instance created with ID: $INSTANCE_ID" # Wait for the instance to be running echo "Waiting for instance to be running..." aws ec2 wait instance-running --instance-ids "$INSTANCE_ID" # Wait a bit more for the instance to initialize echo "Waiting for instance initialization (30 seconds)..." sleep 30 else echo "Skipping instance creation and volume attachment." INSTANCE_ID="" fi else # Display available instances echo "Available instances in $AZ:" aws ec2 describe-instances \ --filters "Name=availability-zone,Values=$AZ" "Name=instance-state-name,Values=running" \ --query "Reservations[*].Instances[*].[InstanceId,Tags[?Key=='Name'].Value|[0],InstanceType]" \ --output table # Ask for instance ID echo "" echo "Enter the instance ID to attach the volume to (or press Enter to skip): " read -r INSTANCE_ID fi if [ -n "$INSTANCE_ID" ]; then # Attach volume to the instance echo "Attaching volume $VOLUME_ID to instance $INSTANCE_ID..." ATTACH_RESULT=$(aws ec2 attach-volume \ --volume-id "$VOLUME_ID" \ --instance-id "$INSTANCE_ID" \ --device "/dev/sdf" \ --query 'State' \ --output text) if [ $? -ne 0 ] || [ -z "$ATTACH_RESULT" ]; then handle_error "Failed to attach volume to instance" fi ATTACHED=true echo "Volume attached successfully. Device: /dev/sdf" # Verify attachment echo "Verifying attachment..." aws ec2 describe-volumes \ --volume-ids "$VOLUME_ID" \ --query "Volumes[0].Attachments" else echo "Skipping volume attachment." fi else echo "Skipping volume attachment." fi # Display summary of created resources echo "" echo "===========================================" echo "RESOURCE SUMMARY" echo "===========================================" echo "Created resources:" echo "- EBS Volume: $VOLUME_ID" if [ "$ATTACHED" = true ]; then echo " - Attached to: $INSTANCE_ID as /dev/sdf" fi if [ "$CREATED_INSTANCE" = true ]; then echo "- EC2 Instance: $INSTANCE_ID (type: $INSTANCE_TYPE)" fi if [ -n "$SG_ID" ]; then echo "- Security Group: $SG_ID" fi # Ask if user wants to clean up resources echo "" echo "===========================================" echo "CLEANUP CONFIRMATION" echo "===========================================" echo "Do you want to clean up all created resources? (y/n): " read -r CLEANUP_CHOICE if [[ "$CLEANUP_CHOICE" =~ ^[Yy]$ ]]; then cleanup_resources else echo "" echo "Resources were not cleaned up. You can manually delete them later." if [ -n "$VOLUME_ID" ]; then if [ "$ATTACHED" = true ]; then echo "To detach the volume:" echo " aws ec2 detach-volume --volume-id $VOLUME_ID" fi echo "To delete the volume:" echo " aws ec2 delete-volume --volume-id $VOLUME_ID" fi if [ "$CREATED_INSTANCE" = true ]; then echo "To terminate the instance:" echo " aws ec2 terminate-instances --instance-ids $INSTANCE_ID" fi if [ -n "$SG_ID" ]; then echo "To delete the security group (after instance termination):" echo " aws ec2 delete-security-group --group-id $SG_ID" fi fi echo "" echo "Script completed at $(date)" echo "=============================================="

For a complete list of Amazon SDK developer guides and code examples, see Create Amazon EC2 resources using an Amazon SDK. This topic also includes information about getting started and details about previous SDK versions.