{"id":20113304,"url":"https://github.com/cloudacademy/ebs-shrinker","last_synced_at":"2025-05-06T12:30:24.722Z","repository":{"id":77791487,"uuid":"244817114","full_name":"cloudacademy/ebs-shrinker","owner":"cloudacademy","description":"AWS EBS Volume Shrinker Demo","archived":false,"fork":false,"pushed_at":"2020-03-04T20:21:55.000Z","size":77,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-09T12:11:40.635Z","etag":null,"topics":["aws","cloudacademy","devops","ebs","ec2"],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cloudacademy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-04T05:39:14.000Z","updated_at":"2024-10-22T14:53:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"fedfe3a7-b18f-4cf2-b33d-a5a6b6d7b5ea","html_url":"https://github.com/cloudacademy/ebs-shrinker","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudacademy%2Febs-shrinker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudacademy%2Febs-shrinker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudacademy%2Febs-shrinker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudacademy%2Febs-shrinker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cloudacademy","download_url":"https://codeload.github.com/cloudacademy/ebs-shrinker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252683355,"owners_count":21788021,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","cloudacademy","devops","ebs","ec2"],"created_at":"2024-11-13T18:23:58.811Z","updated_at":"2025-05-06T12:30:24.716Z","avatar_url":"https://github.com/cloudacademy.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# EBS-Shrinker\n\nThe following script is provided to demonstrate how to resize an ebs root volume. The end-to-end solution will launch a demo EC2 instance with an initial 50Gb ebs gp2 root volume, and then resize it to 20Gb. \n\n**Note**: Please install the [jq utility](https://stedolan.github.io/jq/) before continuing - Steps 2 \u0026 4 below are dependent on it.\n\n**Note**: This script is provided to demonstrate how to perform root volume resizing - take extreme care when performing the same actions within a production environment. For extra safety measures - always snapshot any ebs volume BEFORE performing any resizing actions on it.\n\n# Example:\n\n[![asciicast](https://asciinema.org/a/307319.svg)](https://asciinema.org/a/307319)\n\n## Before Resizing\nPause at 1:36 (original root volume 50Gb)\n\n```\nFilesystem      Size  Used Avail Use% Mounted on                                                                               \nudev            481M     0  481M   0% /dev                                                                                     \ntmpfs            99M  748K   98M   1% /run                                                                                     \n/dev/xvda1       49G  1.1G   48G   3% /                                                                                        \ntmpfs           492M     0  492M   0% /dev/shm                                                                                 \ntmpfs           5.0M     0  5.0M   0% /run/lock                                                                                \ntmpfs           492M     0  492M   0% /sys/fs/cgroup                                                                           \n/dev/loop0       18M   18M     0 100% /snap/amazon-ssm-agent/1480                                                              \n/dev/loop1       90M   90M     0 100% /snap/core/8268                                                                          \ntmpfs            99M     0   99M   0% /run/user/1000 \n```\n\n## After Resizing\nPause at 3:52 (resized root volume 20Gb)\n\n```\nFilesystem      Size  Used Avail Use% Mounted on                                                                               \nudev            481M     0  481M   0% /dev                                                                                     \ntmpfs            99M  740K   98M   1% /run                                                                                     \n/dev/xvda        20G  1.3G   18G   7% /                                                                                        \ntmpfs           492M     0  492M   0% /dev/shm                                                                                 \ntmpfs           5.0M     0  5.0M   0% /run/lock                                                                                \ntmpfs           492M     0  492M   0% /sys/fs/cgroup                                                                           \n/dev/loop0       18M   18M     0 100% /snap/amazon-ssm-agent/1480                                                              \n/dev/loop1       90M   90M     0 100% /snap/core/8268                                                                          \ntmpfs            99M     0   99M   0% /run/user/1000     \n```\n\n# Script\n\n## Environment Variables 1\n\nDefaults to configure the deployment of a demo EC2 instance into the Oregon (```REGION```) region. The EC2 instance will be configured with the Ubuntu 18.04 OS (```IMAGE_ID```) installed on a 50Gb (```VOLUME_SIZE_LARGE```) sized root volume - which will then be cloned and downsized to a 20Gb (```VOLUME_SIZE_SMALL```) root volume\n\n```\nREGION=us-west-2\nAZ=us-west-2c\nIMAGE_ID=ami-0d1cd67c26f5fca19 #ubuntu 18.04\nUSER=ubuntu\nVOLUME_SIZE_LARGE=50 #starting size for ebs root volume\nVOLUME_SIZE_SMALL=20 #final size after resizing for ebs root volume\n```\n\n## Environment Variables 2\n\nYou need to update the following environment variables which will be used later to establish a demo EC2 instance with an initial root volume of 50Gb. The demo EC2 instance should be deployed into a subnet with a security group that ensures internet connectivity both in and out.  \n\n```\nSSH_KEY_NAME=\u003cec2 ssh keyname here - example: DemoSSHKey\u003e\nSSH_KEY_PATH=\u003cec2 ssh key path here - example: ~/.ssh/DemoSSHKey.pem\u003e\nSUBNET_ID=\u003csubnet id here - where demo ec2 instance is deployed - example: subnet-aa598002\u003e\nSECURITY_GROUP_ID=\u003csecurity group id here - needs to allow inbound ssh connections to the demo ec2 instance - example: \u003e\n```\n\n## Step 1\n\nLaunch a demo EC2 instance with a 50Gb root volume with Ubuntu 18.04 installed\n\n```\nCREATE_INSTANCE_RESULT=`aws ec2 run-instances \\\n    --region $REGION \\\n    --image-id $IMAGE_ID\\\n    --count 1 \\\n    --instance-type t2.micro \\\n    --key-name $SSH_KEY_NAME \\\n    --security-group-ids $SECURITY_GROUP_ID \\\n    --subnet-id $SUBNET_ID \\\n    --associate-public-ip-address \\\n    --block-device-mapping \"[ { \\\"DeviceName\\\": \\\"/dev/sda1\\\", \\\"Ebs\\\": { \\\"VolumeSize\\\": $VOLUME_SIZE_LARGE, \\\"VolumeType\\\": \\\"gp2\\\" } } ]\" \\\n    --tag-specifications \"ResourceType=instance,Tags=[{Key=Name,Value=CloudAcademy.EBS.Resizer.Demo}]\" \"ResourceType=volume,Tags=[{Key=Name,Value=EBSLargeVol}]\"`\n```\n\nOutcome:\n\n![step 1](/doc/step1.png)\n\n## Step 2\n\nRetrieve the demo EC2 instance id just launched.\n\n**Note**: Please install the [jq utility](https://stedolan.github.io/jq/) before continuing - this step is dependent on it.\n\n```\nINSTANCE_ID=`echo $CREATE_INSTANCE_RESULT | jq -r .Instances[0].InstanceId`\n\necho INSTANCE_ID=$INSTANCE_ID\n```\n\n## Step 3\n\nQuery and display all volumes currently attached to the demo EC2 instance. At the moment there should be just the one 50Gb GP2 root volume attached.\n\n```\naws ec2 describe-volumes \\\n    --region $REGION \\\n    --filters Name=attachment.instance-id,Values=$INSTANCE_ID\n```\n\n## Step 4\n\nCreate a smaller 20Gb (```VOLUME_SIZE_SMALL```) gp2 volume in the same availabilty zone. Capture the volume id and echo it back out to the console.\n\n**Note**: Please install the [jq utility](https://stedolan.github.io/jq/) before continuing - this step is dependent on it.\n\n```\nCREATE_VOL_RESULT=`aws ec2 create-volume \\\n    --region $REGION \\\n    --volume-type gp2 \\\n    --size $VOLUME_SIZE_SMALL \\\n    --availability-zone $AZ \\\n    --tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=EBSSmallVol}]'`\n\nNEW_VOL_ID=`echo $CREATE_VOL_RESULT | jq -r .VolumeId`\n\necho NEW_VOL_ID=$NEW_VOL_ID\n```\n\nOutcome:\n\n![step 4](/doc/step4.png)\n\n## Step 5\n\nStop the demo EC2 instance in preparation for attaching the new smaller volume.\n\n```\naws ec2 stop-instances  \\\n    --region $REGION \\\n    --instance-ids $INSTANCE_ID\n\naws ec2 wait instance-stopped \\\n    --region $REGION \\\n    --instance-ids $INSTANCE_ID\n```\n\nOutcome:\n\n![step 5](/doc/step5.png)\n\n## Step 6\n\nAttach the new smaller 20Gb volume to the EC2 demo instance and then restart it. The new volume will be attached to the ```/dev/xvdf``` device. \n\n```\naws ec2 attach-volume \\\n    --region $REGION \\\n    --volume-id $NEW_VOL_ID \\\n    --instance-id $INSTANCE_ID \\\n    --device /dev/xvdf   \n\naws ec2 start-instances  \\\n    --region $REGION \\\n    --instance-ids $INSTANCE_ID\n\naws ec2 wait instance-running \\\n    --region $REGION \\\n    --instance-ids $INSTANCE_ID\n```\n\nOutcome:\n\n![step 6](/doc/step6.png)\n\n## Step 7\n\nRetrieve the auto assigned public IP address and then SSH into the demo EC2 instance and run the commands ```lsblk``` and ```df -h``` to examine and display the attached devices.\n\n```\nPUBLIC_IP=`aws ec2 describe-instances \\\n    --region $REGION \\\n    --filters \\\n    \"Name=instance-state-name,Values=running\" \\\n    \"Name=instance-id,Values=$INSTANCE_ID\" \\\n    --query 'Reservations[*].Instances[*].[PublicIpAddress]' \\\n    --output text`\n\necho PUBLIC_IP=$PUBLIC_IP\n\nssh -o \"StrictHostKeyChecking no\" -v -i $SSH_KEY_PATH $USER@$PUBLIC_IP 'bash -s' \u003c\u003c\\EOF\nlsblk\necho\ndf -h\nEOF\n```\n\nOutput will be something like:\n\n```\nFilesystem      Size  Used Avail Use% Mounted on                                                                               \nudev            481M     0  481M   0% /dev                                                                                     \ntmpfs            99M  748K   98M   1% /run                                                                                     \n/dev/xvda1       49G  1.1G   48G   3% /                                                                                        \ntmpfs           492M     0  492M   0% /dev/shm                                                                                 \ntmpfs           5.0M     0  5.0M   0% /run/lock                                                                                \ntmpfs           492M     0  492M   0% /sys/fs/cgroup                                                                           \n/dev/loop0       18M   18M     0 100% /snap/amazon-ssm-agent/1480                                                              \n/dev/loop1       90M   90M     0 100% /snap/core/8268                                                                          \ntmpfs            99M     0   99M   0% /run/user/1000 \n```\n\n**Note**: The root volume is 50Gb\n\n## Step 8\n\n:muscle::muscle::muscle:\n\nThis is where the heavy lifting (resizing) happens!!\n\nThe resizing process involves the following sub steps:\n\n* Format the new ```/dev/xvdf``` volume using ```mkfs -t ext4```\n* Create a new directory ```/mnt/new-root-volume``` as the mount point for the ```/dev/xvdf``` device\n* Rsync all root volume files/folders recursively to the ```/mnt/new-root-volume``` directory\n* Install grub (boot loader) on the new ```/mnt/new-root-volume``` directory\n* Unmount the new ```/mnt/new-root-volume``` directory\n* Copy across both the UUID and Label from the original root volume to the new root volume\n\n```\nssh -o \"StrictHostKeyChecking no\" -v -i $SSH_KEY_PATH $USER@$PUBLIC_IP 'bash -s' \u003c\u003c\\EOF\necho shrink root vol start...\nlsblk\nNEW_ROOT_DIR=/mnt/new-root-volume\nNEW_DEV=/dev/xvdf\nsudo file -s $NEW_DEV\nsudo mkfs -t ext4 $NEW_DEV\nsudo mkdir $NEW_ROOT_DIR\nsudo mount $NEW_DEV $NEW_ROOT_DIR\ndf -h\necho rsyncing start...\nsudo rsync -axv / $NEW_ROOT_DIR/\necho install grub...\nsudo grub-install --root-directory=$NEW_ROOT_DIR --force $NEW_DEV\nsudo umount $NEW_ROOT_DIR\necho copy uuid across to new root dev...\nROOT_DEV=`sudo blkid -L cloudimg-rootfs`\nUUID=`blkid -s UUID -o value $ROOT_DEV`\nsudo tune2fs -U $UUID $NEW_DEV\necho copy system label across to new root vol...\nLABEL=`sudo e2label $ROOT_DEV`\nsudo e2label $NEW_DEV $LABEL\necho shrink root vol finished!!\nEOF\n```\n\nOutcome:\n\n![step 8](/doc/step8.png)\n\n## Step 9\n\nShutdown the demo EC2 instance in preparation for detaching the EBS volumes.\n\n```\naws ec2 stop-instances  \\\n    --region $REGION \\\n    --instance-ids $INSTANCE_ID\n\naws ec2 wait instance-stopped \\\n    --region $REGION \\\n    --instance-ids $INSTANCE_ID\n```\n\nOutcome:\n\n![step 9](/doc/step9.png)\n\n## Step 10\n\nDetach both EBS volumes, and then reattach the smaller and newer 20Gb ebs gp2 root volume and map it to the root device at ```/dev/sda1```.\n\n```\nfor vol in `aws ec2 describe-volumes \\\n                --region $REGION \\\n                --filters Name=attachment.instance-id,Values=$INSTANCE_ID \\\n                --query 'Volumes[*].Attachments[*].VolumeId' --output text`; \\\n    do aws --region us-west-2 ec2 detach-volume --volume-id $vol; \\\ndone\n\naws ec2 attach-volume \\\n    --region $REGION \\\n    --volume-id $NEW_VOL_ID \\\n    --instance-id $INSTANCE_ID \\\n    --device /dev/sda1\n```\n\nOutcome:\n\n![step 10](/doc/step10.png)\n\n## Step 11\n\nRestart the demo EC2 instance and query and display the updated auto assigned public IP address \n\n```\naws ec2 start-instances  \\\n    --region $REGION \\\n    --instance-ids $INSTANCE_ID\n\naws ec2 wait instance-running \\\n    --region $REGION \\\n    --instance-ids $INSTANCE_ID\n\nPUBLIC_IP=`aws ec2 describe-instances \\\n    --region $REGION \\\n    --filters \\\n    \"Name=instance-state-name,Values=running\" \\\n    \"Name=instance-id,Values=$INSTANCE_ID\" \\\n    --query 'Reservations[*].Instances[*].[PublicIpAddress]' \\\n    --output text`\n\necho PUBLIC_IP=$PUBLIC_IP\n```\n\nOutcome:\n\n![step 11](/doc/step11.png)\n\n## Step 12\n\n SSH into the demo EC2 instance and run the commands ```lsblk``` and ```df -h``` to examine and display the attached config of the root device. Compare with the previous values (see previous Step 7). \n\n```\nssh -o \"StrictHostKeyChecking no\" -v -i $SSH_KEY_PATH $USER@$PUBLIC_IP 'bash -s' \u003c\u003c\\EOF\nlsblk\necho\ndf -h\nEOF\n```\n\nOutput will be something like:\n\n```\nFilesystem      Size  Used Avail Use% Mounted on                                                                               \nudev            481M     0  481M   0% /dev                                                                                     \ntmpfs            99M  740K   98M   1% /run                                                                                     \n/dev/xvda        20G  1.3G   18G   7% /                                                                                        \ntmpfs           492M     0  492M   0% /dev/shm                                                                                 \ntmpfs           5.0M     0  5.0M   0% /run/lock                                                                                \ntmpfs           492M     0  492M   0% /sys/fs/cgroup                                                                           \n/dev/loop0       18M   18M     0 100% /snap/amazon-ssm-agent/1480                                                              \n/dev/loop1       90M   90M     0 100% /snap/core/8268                                                                          \ntmpfs            99M     0   99M   0% /run/user/1000     \n```\n\n**Note**: The root volume is now 20Gb\n\n# Result!\n\nThe demo EC2 instance is now operational again - this time with a resized and smaller 20Gb gp2 root ebs volume.\n\n:metal::metal::metal:","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudacademy%2Febs-shrinker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloudacademy%2Febs-shrinker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudacademy%2Febs-shrinker/lists"}