There are more AWS SDK examples available in the AWS Doc SDK Examples
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
-
- AWS 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 API details, see the following topics in AWS CLI Command Reference.
-
Creating an Amazon RDS DB instance
Creating and managing a VPC Lattice service network