AWS: Shrink an EBS configured in GPT mode

I don't really know why, but my image on my EC2 server was not configured in MBR but in GPT. All the guides I found for shrinking a root EBS was not made for GPT.

First of all, you cannot shrink an EBS. You can expand it but shrinking is not allowed. To achieve that goal, you have to copy the content on another EBS volume.

View current partitioning

  1. Stop your EC2 instance and dettach your root volume (let's call it V1).
  2. Create a new volume with the new target size (V2).
  3. Create a new EC2 instance. Attach it V1 and V2.
  4. SSH into your instance and type sudo lsblk
    admin@ip-10-99-4-58:~$ sudo lsblk
    NAME    MAJ:MIN RM    SIZE RO TYPE MOUNTPOINT
    xvda    202:0    0      8G  0 disk
    └─xvda1 202:1    0      8G  0 part /
    xvdf    202:80   0     70G  0 disk
    xvdg    202:96   0    300G  0 disk
    ├─xvdg1 202:97   0 1007.5K  0 part
    └─xvdg2 202:98   0    300G  0 part
    
    In my example, V1 is xvdg and V2 is xvdf
  5. Install gdisk if it's not already installed in your OS.
  6. View V1 partitioning with sudo gdisk -l /dev/xvdg
    admin@ip-10-99-4-58:~$ sudo gdisk -l /dev/xvdg
    GPT fdisk (gdisk) version 1.0.1
    
    Partition table scan:
      MBR: protective
      BSD: not present
      APM: not present
      GPT: present
    
    Found valid GPT with protective MBR; using GPT.
    Disk /dev/xvdg: 629145600 sectors, 300.0 GiB
    Logical sector size: 512 bytes
    Disk identifier (GUID): D6CFA2DD-A1E7-425F-87B8-395D3361807E
    Partition table holds up to 128 entries
    First usable sector is 34, last usable sector is 629145566
    Partitions will be aligned on 8-sector boundaries
    Total free space is 0 sectors (0 bytes)
    
    Number  Start (sector)    End (sector)  Size       Code  Name
       1              34            2048   1007.5 KiB  EF02  primary
       2            2049       629145566   300.0 GiB   8300
    
    Please write down the first and the last sector of the first partition.

Create partitioning on the new disk

  1. Replicate this partitioning onto V2. Use gdisk another time:
    admin@ip-10-99-4-58:~$ sudo gdisk /dev/xvdf
    GPT fdisk (gdisk) version 1.0.1
    
    Partition table scan:
      MBR: not present
      BSD: not present
      APM: not present
      GPT: not present
    
    Creating new GPT entries.
    
    Command (? for help):
    
  2. Go in expert mode (x), then press l to set alignement, enter 1, then press m to go back.
    Command (? for help): x
    
    Expert command (? for help): l
    Enter the sector alignment value (1-65536, default = 2048): 1
    
    Expert command (? for help): m
    
  3. Create a new BIOS boot partition with n. Set the first and the last sector with the value you wrote down on step 6. In my case 34 and 2048. Set the type to EF02.
    Command (? for help): n
    Partition number (1-128, default 1): 1
    First sector (34-146800606, default = 34) or {+-}size{KMGTP}: 34
    Last sector (34-146800606, default = 146800606) or {+-}size{KMGTP}: 2048
    Current type is 'Linux filesystem'
    Hex code or GUID (L to show codes, Enter = 8300): EF02
    Changed type of partition to 'BIOS boot partition'
    
  4. Create another partition with Linux type. Leave all default values.
    Command (? for help): n
    Partition number (2-128, default 2):
    First sector (2049-146800606, default = 2049) or {+-}size{KMGTP}:
    Last sector (2049-146800606, default = 146800606) or {+-}size{KMGTP}:
    Current type is 'Linux filesystem'
    Hex code or GUID (L to show codes, Enter = 8300):
    Changed type of partition to 'Linux filesystem'
    
  5. Write the new partition table with w
    Command (? for help): w
    
    Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
    PARTITIONS!!
    
    Do you want to proceed? (Y/N): y
    OK; writing new GUID partition table (GPT) to /dev/xvdf.
    The operation has completed successfully.
    

Create the filesystem and replicate the old UUID

  1. Create an ext4 partition on /dev/xvdf2
    admin@ip-10-99-4-58:~$ sudo mkfs.ext4 /dev/xvdf2
    mke2fs 1.43.4 (31-Jan-2017)
    Creating filesystem with 18349819 4k blocks and 4587520 inodes
    Filesystem UUID: 68690b84-c1e5-4532-a467-33047975dc14
    Superblock backups stored on blocks:
            32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
            4096000, 7962624, 11239424
    
    Allocating group tables: done
    Writing inode tables: done
    Creating journal (131072 blocks): done
    Writing superblocks and filesystem accounting information: done
    
  2. When you created the new ext4 partition, a new UUID has been generated. We want the old UUID back, otherwise the system won't boot. Get the UUID of /dev/xvdg2 with sudo blkid /dev/xvdg2
    admin@ip-10-99-4-58:~$ sudo blkid /dev/xvdg2
    /dev/xvdg2: UUID="5cfc0e59-b149-4ddc-8741-74bd7e71f91c" TYPE="ext4" PTTYPE="dos" PARTUUID="05266ce5-177c-4bab-8001-302ad2119d7c"
    
  3. Copy it to /dev/xvdf2
    admin@ip-10-99-4-58:~$ sudo tune2fs /dev/xvdf2 -U 5cfc0e59-b149-4ddc-8741-74bd7e71f91c
    tune2fs 1.43.4 (31-Jan-2017)
    Setting UUID on a checksummed filesystem could take some time.
    Proceed anyway (or wait 5 seconds) ? (y,N) y
    

Copy the data

  1. Mount both disk onto the system
    admin@ip-10-99-4-58:~$ mkdir -p /source /target
    admin@ip-10-99-4-58:~$ sudo mount /dev/xvdg2 /source/
    admin@ip-10-99-4-58:~$ sudo mount /dev/xvdf2 /target
    
  2. rsync the data (careful, no trailing / after /target):
    sudo rsync -HAXxSa /source/ /target
    

Install GRUB

  1. Prepare the chroot environment so that we can install GRUB in the BIOS boot partition of the new disk
    admin@ip-10-99-4-58: sudo -i
    root@ip-10-99-4-58:~$ cd /target/
    root@ip-10-99-4-58:/target$ mount -t proc proc proc/
    root@ip-10-99-4-58:/target$ mount -t sysfs sys sys/
    root@ip-10-99-4-58:/target$ mount -o bind /dev dev/
    root@ip-10-99-4-58:/target$ chroot .
    
  2. Install GRUB
    root@ip-10-99-4-58:/# grub-install /dev/xvdf
    
  3. Leave chroot with exit, then unmount all
    root@ip-10-99-4-58:/$ exit
    root@ip-10-99-4-58:/target$ umount proc
    root@ip-10-99-4-58:/target$ umount dev
    root@ip-10-99-4-58:/target$ umount sys
    root@ip-10-99-4-58:/target$ cd
    root@ip-10-99-4-58:~$ umount /target
    root@ip-10-99-4-58:~$ umount /source
    
  4. Detach both EBS volume from you EC2 instance and mount V2 as /dev/xvda on your old EC2 instance. Boot it. If all went well, you have your new shrinked system !

Damien Gustave

Read more posts by this author.