TechEarl

How to Increase Google Cloud VM Disk Size Without Rebooting

Grow a Google Cloud persistent disk on a live VM in three commands. Resize the disk in GCP, expand the partition with growpart, then stretch the filesystem with resize2fs or xfs_growfs. No detach, no reboot.

Ishan KarunaratneIshan Karunaratne⏱️ 14 min readUpdated
Grow a GCP persistent disk with zero downtime: gcloud compute disks resize, then growpart and resize2fs (ext4) or xfs_growfs (XFS). No detach, no reboot, on a live VM.

Google Cloud persistent disks grow online. The disk hardware is resized at the GCP control-plane layer in seconds, then the partition table and filesystem are stretched live from inside the VM. No detach, no reboot, no maintenance window. The whole operation is three commands once you know the device path: gcloud compute disks resize to enlarge the disk, sudo growpart to expand the partition, and sudo resize2fs (ext4) or sudo xfs_growfs (XFS) to stretch the filesystem. Below is the exact procedure, the verification commands to run before and after, the caveats that bite people once (shrinking, MBR ceiling, Extreme PD throttling), and a Console vs gcloud vs Terraform comparison so you can pick the right interface for your workflow.

How do I increase a Google Cloud VM disk size without rebooting?

Run gcloud compute disks resize DISK_NAME --size NEW_SIZE --zone ZONE to enlarge the persistent disk at the GCP layer. The hypervisor exposes the new size to the running VM within a few seconds. SSH into the instance and confirm the kernel sees it with lsblk. Expand the partition with sudo growpart /dev/DEVICE PART_NUM (typically /dev/sda 1 for boot disks on most public images). Finally, stretch the filesystem: sudo resize2fs /dev/sda1 for ext4 or sudo xfs_growfs / for XFS. Verify with df -h. The entire flow runs against a live VM with active connections, services, and disk I/O. No detach, no reboot, no downtime. For Extreme PD the only constraint is one resize per six hours, and shrinking is never supported on any disk type.

Jump to:

Try it with your own values

Before you start: prerequisites and backups

You need the Compute Instance Admin (v1) IAM role (roles/compute.instanceAdmin.v1) or an equivalent custom role with compute.disks.update. The VM can be running. The disk does not need to be detached.

Take a snapshot first. Snapshots are incremental, cheap, and the only single-command rollback you have if the partition table goes sideways:

bash
gcloud compute snapshots create pre-resize-$(date +%Y%m%d-%H%M) \
  --source-disk :disk_name \
  --source-disk-zone :zone

A 100 GB disk snapshot completes in seconds and costs cents. Mistakes on a live disk are not cheap.

Capture the current state so you have a before-and-after to compare:

bash
df -h
lsblk

df -h shows mounted filesystems and their used/free space. lsblk shows the block-device tree (disk → partitions → filesystems) and is where you'll confirm the new size lands.

Step 1: Resize the disk in GCP

The gcloud one-liner:

bash
gcloud compute disks resize :disk_name \
  --size :new_size \
  --zone :zone

--size is in GiB. The disk name is the persistent disk's name, not the VM's (though for boot disks they usually match). The flag is --zone for zonal disks; use --region instead for regional (replicated) disks.

For boot disks the disk name usually equals the VM name. List disks to confirm:

bash
gcloud compute disks list --filter="zone::zone"

The resize takes a few seconds and returns immediately. The new size is visible from inside the VM the moment the gcloud command returns, but the kernel may need a nudge to re-read the block-device geometry. Run lsblk from inside the VM to confirm. If the disk still shows the old size, force a rescan:

bash
echo 1 | sudo tee /sys/class/block/:device/device/rescan

This is rare on modern public images (Debian, Ubuntu, RHEL, Rocky all auto-detect) but worth knowing.

Console method: Compute Engine > Disks > click the disk > Edit > change Size > Save. Same effect, just slower if you're resizing more than one disk.

Step 2: Expand the partition

The kernel now sees the larger disk, but the partition table still says "this partition ends at the old boundary." Fix that with growpart from the cloud-utils-growpart package (pre-installed on every GCP public image):

bash
sudo growpart /dev/:device :partition

Two arguments, space-separated: the device (/dev/sda) and the partition number (1). Note the space, not a colon and not concatenated. A common typo is growpart /dev/sda1 (no space) which fails because growpart needs the disk and the partition index separately.

Output looks like:

code
CHANGED: partition=1 start=2048 old: size=209713119 end=209715167 new: size=419430399 end=419432447

If growpart isn't installed (rare, but happens on minimal or custom images):

bash
# Debian / Ubuntu
sudo apt-get update && sudo apt-get install -y cloud-guest-utils

# RHEL / Rocky / CentOS
sudo dnf install -y cloud-utils-growpart

For data disks with a single partition the call is identical with a different device, for example sudo growpart /dev/sdb 1. For data disks formatted as a whole-disk filesystem (no partition table) skip this step and go straight to filesystem resize against the raw device.

Step 3: Resize the filesystem

The partition is now the full size of the disk, but the filesystem inside the partition still believes it's the old size. The command depends on the filesystem type.

ext4 (Debian, Ubuntu, most custom Linux images):

bash
sudo resize2fs /dev/:device:partition

resize2fs reads the partition geometry and grows the ext4 superblock to match. Online resize on a mounted filesystem is supported and is what runs here. Expected output:

code
resize2fs 1.46.5 (30-Dec-2021)
Filesystem at /dev/sda1 is mounted on /; on-line resizing required
old_desc_blocks = 13, new_desc_blocks = 25
The filesystem on /dev/sda1 is now 52428795 (4k) blocks long.

XFS (RHEL 8+, Rocky, AlmaLinux, some Ubuntu cloud images):

bash
sudo xfs_growfs :mount

XFS resizes by mount point, not by device. / is the root mount; for a data disk mounted at /data it would be sudo xfs_growfs /data. XFS can only grow, never shrink, which matches the GCP disk constraint anyway.

Btrfs (uncommon on GCP, but supported):

bash
sudo btrfs filesystem resize max :mount

If you don't know the filesystem type, the next section has the detection commands.

Verify the new size

bash
df -h
lsblk

df -h should now show the new free space on the mount point. lsblk should show the partition matching the disk size.

A complete before-and-after on a boot disk grown from 100 GB to 200 GB:

code
# Before
$ df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        98G   42G   52G  45% /

# After
$ df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       196G   42G  149G  22% /

Same Used, larger Size. That's the green light. Total wall-clock for the three commands on a typical boot disk: under 30 seconds, no reboot, active SSH session never drops.

Detect the filesystem before you resize it

Run any of these to identify the filesystem type and partition layout. Useful when you've inherited a VM and don't know what shape its disk is in.

bash
# Filesystem type per partition
lsblk -f

# Filesystem type of the root mount
findmnt -T / -o SOURCE,TARGET,FSTYPE

# Disk and partition geometry
sudo parted -l

# Quick filesystem type lookup by device
sudo blkid /dev/sda1

lsblk -f is the fastest single command and shows everything at once: device tree, filesystem type, label, UUID, and mountpoint.

Cheat sheet for picking the resize command:

FilesystemResize command
ext2 / ext3 / ext4sudo resize2fs /dev/DEVICE
XFSsudo xfs_growfs MOUNT_POINT
Btrfssudo btrfs filesystem resize max MOUNT_POINT
ZFSsudo zpool online -e POOL DEVICE
FAT32 / NTFSnot online-resizable on Linux

The first three cover ~99% of GCP Linux VMs.

Console vs gcloud vs Terraform

The resize itself is identical at the API layer. The interface choice is about your workflow.

ApproachBest forCommand / action
Cloud ConsoleOne-off resizes, exploringCompute Engine > Disks > Edit > Size
gcloud CLIScripted, one-shot, ad-hoc batchesgcloud compute disks resize DISK --size N --zone Z
TerraformInfra-as-code, audit trail, multi-environmentgoogle_compute_disk.size = 200 then terraform apply
REST APIProgrammatic, custom toolingPATCH /compute/v1/projects/PROJECT/zones/ZONE/disks/DISK

For Terraform specifically, the only attribute that changes is size:

hcl
resource "google_compute_disk" "data" {
  name = "data-disk"
  zone = "us-central1-a"
  size = 200  # was 100
  type = "pd-balanced"
}

Terraform performs the resize in place. It does NOT trigger a replacement, which is exactly what you want. The growpart and resize2fs steps still have to happen inside the VM, typically via a remote-exec provisioner or a separate Ansible/SSM run.

To batch-resize many disks via gcloud, a Bash for loop over a disk-name list is the simplest pattern:

bash
for disk in web-01 web-02 web-03; do
    gcloud compute disks resize "$disk" --size 200 --zone us-central1-a --quiet
done

Pair with a Bash while loop and a gcloud compute disks describe poll if you need to wait for the resize to be observed by each VM before proceeding to the partition step.

Caveats and gotchas

You cannot shrink a persistent disk. Ever. The only path to a smaller disk is: create a new smaller disk, copy data over, switch the VM to use it, delete the old one. Plan capacity with this in mind; over-provisioning is reversible only the hard way.

MBR partition tables cap at 2 TB. GPT supports the full range up to 64 TiB. GCP public images ship GPT by default, but custom images imported from older infrastructure may still be MBR. Check with sudo parted /dev/sda print | grep "Partition Table". If it says msdos, you're on MBR and capped at 2 TB.

Maximum disk size is 64 TiB for Balanced, Performance (SSD), Standard, and Extreme persistent disks. Hyperdisk goes higher but uses a different resize path.

Extreme PD throttles resizes to once per 6 hours. Plan accordingly. The other disk types have no such limit.

Custom images may not auto-detect the new size on boot. Public Google-managed images (Debian, Ubuntu, RHEL, Rocky, Windows) auto-grow the boot disk's partition and filesystem on first boot after a resize. Custom or imported images do not. If you're on a custom image, the three-step procedure above is mandatory.

Boot disks vs data disks. The device is /dev/sda for the boot disk on most public images and /dev/sdb, /dev/sdc, etc. for additional data disks. NVMe-backed instances (C3, N4, third-gen and later) use /dev/nvme0n1, /dev/nvme0n2 instead. lsblk is the source of truth.

Snapshots before, not regrets after. A snapshot is faster than typing this sentence and saves the disk in its current state. Cost is incremental-only, measured in cents. There is no excuse to skip it on production disks.

Performance scales with capacity on some disk types. Standard PD throughput is capped at 1.2 MB/s per GB of provisioned size. Going from 100 GB to 200 GB doubles your throughput ceiling. Balanced PD and Performance PD have different scaling rules. Check the GCP disk performance docs if you care about the exact numbers for your disk type.

Don't run fdisk just because an old guide tells you to. Some older blog posts (including the one currently ranking on dev.to) advise running sudo fdisk /dev/sda and pressing w to "fix the GPT partition table" before growpart. This is unnecessary on modern GCP public images and risks corruption if you press the wrong key in fdisk's interactive mode. growpart handles the partition table update on its own.

What to do next

FAQ

TagsGoogle CloudGCPCompute EnginePersistent DiskLinuxgcloudgrowpartresize2fs
Share
Ishan Karunaratne

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years across software, Linux systems, DevOps, and infrastructure — and a more recent focus on AI. Currently Chief Technology Officer at a tech startup in the healthcare space.

Keep reading

Related posts

Connect to a GCP Compute Engine VM with plain OpenSSH and no gcloud CLI. Add a public key via instance metadata, ssh to the external IP, configure ~/.ssh/config, plus OS Login and IAP.

How to SSH into a Google Cloud VM Without gcloud

Connect to a GCP VM using plain OpenSSH, no gcloud required. Add a public key to instance metadata, fetch the external IP, and ssh in like any normal Linux box. Plus OS Login, IAP, and a Windows PuTTY path.

Match a hex color code with regex. 3-digit, 6-digit, and 8-digit (alpha) forms. Case-insensitive. JavaScript / Python / PHP examples, engine notes, common mistakes, test cases.

How to Match a Hex Color Code with Regex

Match a hex color code with regex. 3-digit, 6-digit, and 8-digit (alpha) forms. JavaScript / Python / PHP examples, engine notes, common mistakes, a stripped-hash variant.