Skip to content

Google Cloud Platform

Running ARROW on Google Cloud means staging a disk tarball in Cloud Storage, registering it as a Compute Engine custom image, and launching instances from that image. Your GCP build downloads as a ZIP containing the disk tarball and arrow-deploy, a single tool that does all of it.


FileWhat it is
disk.raw.tar.gzThe disk image, a sparse tarball of a raw disk, around 23 GB
arrow-deploy-linux-amd64The deploy tool for Linux
arrow-deploy-darwin-arm64The deploy tool for macOS (Apple silicon)
arrow-deploy-windows-amd64.exeThe deploy tool for Windows
*-gcp-deployment.txtA summary of this build and the manual commands
DEPLOY-README.txtQuick reference
deploy-to-gcp.sh, Deploy-To-GCP.ps1The previous scripts, still included during the transition

You need the Google Cloud CLI, which supplies both gcloud and gsutil, and you need to be signed in with gcloud auth login.

Three further things are required, and arrow-deploy handles all of them for you:

  • A project must be set. gcloud config set project <id> accepts either a project ID or a project number; both work here, because the tool resolves a number to an ID before calling Compute Engine.
  • Two APIs must be enabled on that project: compute.googleapis.com for creating the image and launching instances, and storage.googleapis.com for staging the tarball. import offers to enable a missing one.
  • A Cloud Storage bucket to stage the disk during import. With no --bucket, the tool lists your buckets to choose from and offers to create one if you have none.

doctor verifies your prerequisites and creates nothing:

Terminal window
chmod +x arrow-deploy-linux-amd64
./arrow-deploy-linux-amd64 doctor --cloud gcp

arrow-deploy doctor output showing the GCP prerequisites passing

Run it first. A disabled compute.googleapis.com fails at image creation, which is the very last step, so without doctor you find out after uploading 23 GB. Anything reported as FAIL names the exact command that fixes it.


Terminal window
./arrow-deploy-linux-amd64 import \
--cloud gcp \
--image disk.raw.tar.gz \
--image-name arrow-kali

The tool checks the APIs, resolves a staging bucket, uploads the tarball, and creates a custom image from it. The image is created with the guest OS features ARROW images need: GVNIC for high-performance networking, VIRTIO_SCSI_MULTIQUEUE for disk throughput, and MULTI_IP_SUBNET for multi-NIC layouts.

The upload is the slow part. The image name is printed at the end; you need it for the next step.

Terminal window
./arrow-deploy-linux-amd64 launch \
--cloud gcp \
--image-id arrow-kali \
--vm-name arrow-kali-01 \
--size e2-standard-4 \
--zone us-central1-a

The tool offers a machine type if you do not pass one, and prints the instance’s external and internal addresses when it is ready. With --non-interactive and no --size, it uses n2-standard-4.

The instance has two separate accounts, reached by different means.

AccountHow you get inPassword
Your Google accountgcloud compute sshNo password; key only
arrowPasswordUnique to this VM, shown in the ARROW Portal

ARROW GCP images install google-guest-agent, so the standard GCP access path works: gcloud compute ssh generates and injects a key for your own account, as it does for any Compute Engine instance.

Terminal window
gcloud compute ssh arrow-kali-01 --zone us-central1-a

The arrow account is for console access and manual configuration using the password from the Portal. Reach it through the serial console or over the ARROW VPN rather than by exposing SSH to the internet. Most of the time you do not need to sign in at all, because the instance connects back to ARROW on its own as soon as it has network access.


A deployed instance’s hostname is the name shown on its device record in the ARROW Portal, not the Compute Engine instance name. This is deliberate, because the Portal name is the identity your team works with, so the image keeps it.

Name the GCP instance whatever suits your project. It does not change the hostname inside the VM.


cleanup reports what it would remove and deletes nothing until you add --yes:

Terminal window
./arrow-deploy-linux-amd64 cleanup --cloud gcp --zone us-central1-a
./arrow-deploy-linux-amd64 cleanup --cloud gcp --zone us-central1-a --yes

It removes instances and custom images carrying its own arrow-managed label, so a resource this tool did not create is never touched, whatever it is called. Narrow it further with --name-prefix. Pass the --zone your instances are in, or the instance deletion has no zone to work in.


arrow-deploy help output listing the commands and common flags

CommandWhat it does
doctorChecks prerequisites, creates nothing
importStages the tarball in Cloud Storage and creates a custom image
launchCreates a Compute Engine instance from an image
cleanupRemoves instances and images the tool created
versionPrints the version
FlagApplies toMeaning
--cloud gcpallTarget cloud, always required
--imageimportPath to disk.raw.tar.gz
--image-nameimportName to register the custom image under
--bucketimportCloud Storage bucket used to stage the upload
--locationimportLocation for a bucket the tool creates
--projectimport, launch, cleanupProject to work in, when it is not your configured one
--image-idlaunchThe image that import created
--vm-namelaunchName for the instance
--sizelaunchMachine type, for example e2-standard-4
--zonelaunch, cleanupZone to launch into, or to clean up in
--network, --subnetlaunchExisting VPC network and subnetwork
--name-prefixcleanupRestrict cleanup to matching names
--yescleanupActually delete; without it cleanup only reports
FlagMeaning
--dry-runReport what would happen without changing anything
--jsonMachine-readable output, for scripting
--non-interactiveNever prompt; every value must be supplied as a flag
--no-colorDisable coloured output. NO_COLOR is also honoured

Under --non-interactive the tool enables no APIs and creates no bucket. It prints the exact gcloud commands to run instead.


TypevCPU / RAMUse
e2-standard-22 / 8 GBMinimum
e2-standard-44 / 16 GBRecommended for most work
e2-standard-88 / 32 GBHeavier workloads

doctor reports compute-api or storage-api FAIL. The API is not enabled on the project. Accept when import offers to enable it, or run the gcloud services enable command that doctor prints. It is a one-time change per project.

doctor reports no active account. Run gcloud auth login.

doctor reports no project configured. Run gcloud config set project <id>.

The import fails with a message about the core/project property being a project number. Newer builds of arrow-deploy resolve the number to a project ID and pass it explicitly, so this should not occur. If you are running an older copy, either set the project by ID or pass --project <id>.

Image creation fails saying the image already exists. A previous run created it. Either pass a different --image-name, or remove the old image with cleanup --yes before importing again.

The instance boots with no network. The image must carry net.ifnames=0 biosdevname=0 on its kernel command line so interface naming matches the profile inside it. Every ARROW GCP image is built that way, so a fresh artifact is not affected.

gcloud compute ssh times out. Confirm the instance has an external address and that a firewall rule allows TCP 22 from your address. On the instance, systemctl status google-guest-agent shows whether key injection is running.

The arrow password from the Portal does not work over SSH. The arrow account is a console and VPN account. Key-based SSH goes to your own Google account through the guest agent, not to arrow.


deploy-to-gcp.sh and Deploy-To-GCP.ps1 are still included in the download and still work:

Terminal window
chmod +x deploy-to-gcp.sh
./deploy-to-gcp.sh # import the tarball as a custom image
./deploy-to-gcp.sh --launch # launch from an existing ARROW image
./deploy-to-gcp.sh --cleanup # remove ARROW GCP resources
Terminal window
.\Deploy-To-GCP.ps1
.\Deploy-To-GCP.ps1 -Launch
.\Deploy-To-GCP.ps1 -Cleanup

New deployments should use arrow-deploy. It is the same flow on every platform, it supports --dry-run and --json, it checks your prerequisites before a long upload rather than after it, it removes the staged object the scripts leave behind, and it rolls back what it created if something fails partway.