Skip to main content
Google Cloud · lesson 3 of 10
Google Cloud beginner Lesson 3 of 10

Compute Engine Fundamentals

Create a Compute Engine VM from the command line, open a firewall rule for SSH, and connect to it — the smallest complete GCP virtual machine workflow.

By SkillByExample · Published

gcp compute-engine vm networking

Compute Engine is GCP’s raw virtual machine service — the layer everything more managed (Cloud Run, GKE, Cloud SQL) is ultimately built on. This lesson creates a VM, opens exactly the firewall hole it needs, and connects to it, which is the smallest loop that touches all three things Compute Engine actually is: an instance, a disk, and a network.

Enabling the API

gcloud services enable compute.googleapis.com
Operation "operations/acat.p2-918273645102-4f3a2b1c-9e8d-4a3b" finished successfully.

Every GCP service is an API that must be explicitly turned on per project — this is a one-time step per project, not per VM.

Creating a VM

gcloud compute instances create web-1 \
    --machine-type=e2-micro \
    --zone=us-central1-a \
    --image-family=debian-12 \
    --image-project=debian-cloud \
    --tags=http-server
Created [https://www.googleapis.com/compute/v1/projects/skillbyexample-437219/zones/us-central1-a/instances/web-1].
NAME   ZONE           MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
web-1  us-central1-a  e2-micro                   10.128.0.2   34.121.55.207  RUNNING

e2-micro is the machine type covered by the Always Free tier in this region — worth knowing before the cost lesson later in this track. --tags=http-server doesn’t open any ports by itself; a network tag only becomes meaningful once a firewall rule targets it.

The SSH attempt that fails first

gcloud compute ssh web-1 --zone=us-central1-a
Updating project ssh metadata...done.
Waiting for SSH key to propagate.
ssh: connect to host 34.121.55.207 port 22: Connection timed out
ERROR: (gcloud.compute.ssh) [/usr/bin/ssh] exited with return code [255].

The key propagated fine — the timeout is a network-level refusal, not an authentication one. gcloud compute firewall-rules list shows why:

gcloud compute firewall-rules list
NAME  NETWORK  DIRECTION  PRIORITY  ALLOW  DENY  DISABLED

An empty list. This project’s default network has no firewall rules at all yet — every port, including 22, is closed to everything outside the VPC.

Opening the port

gcloud compute firewall-rules create allow-ssh \
    --network=default \
    --direction=INGRESS \
    --action=ALLOW \
    --rules=tcp:22 \
    --source-ranges=0.0.0.0/0
Creating firewall...done.
NAME       NETWORK  DIRECTION  PRIORITY  ALLOW   DENY  DISABLED
allow-ssh  default  INGRESS    1000      tcp:22        False

source-ranges=0.0.0.0/0 means “from anywhere” — fine for a lesson VM, deliberately too broad for anything real; the VPC lesson ahead narrows this to a specific IP range.

gcloud compute ssh web-1 --zone=us-central1-a
Updating project ssh metadata...done.
Waiting for SSH key to propagate.
Linux web-1 6.1.0-18-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1 (2024-02-01) x86_64

you@web-1:~$

Same command, same VM — only the firewall changed, and the exact same timeout became an immediate connection.

Practice

1. Restrict allow-ssh to your own IP instead of the whole internet.
gcloud compute firewall-rules update allow-ssh --source-ranges=203.0.113.42/32
gcloud compute firewall-rules describe allow-ssh --format="value(sourceRanges)"
Updated [allow-ssh].
['203.0.113.42/32']

/32 means exactly one address. This is the realistic version of the rule from a laptop with a stable IP; a dynamic home IP would need a wider range or a VPN-based approach instead.

2. Stop the VM and confirm its billing state changes.
gcloud compute instances stop web-1 --zone=us-central1-a
gcloud compute instances describe web-1 --zone=us-central1-a --format="value(status)"
Updating instance...done.
TERMINATED

TERMINATED (not STOPPED, oddly enough — that’s the actual API status string) means vCPU and memory billing stops, but the boot disk keeps accruing storage charges until it’s deleted.

3. Reserve a static external IP and attach it after restarting.
gcloud compute addresses create web-1-ip --region=us-central1
gcloud compute instances start web-1 --zone=us-central1-a
gcloud compute instances add-access-config web-1 \
    --zone=us-central1-a --address=$(gcloud compute addresses describe web-1-ip --region=us-central1 --format="value(address)")
Created [https://www.googleapis.com/compute/v1/projects/skillbyexample-437219/regions/us-central1/addresses/web-1-ip].
Updating instance...done.
Updating instance...done.

Now web-1 keeps the same external IP across future stop/start cycles, instead of getting a new ephemeral one each time.

4. List all firewall rules and confirm only allow-ssh exists.
gcloud compute firewall-rules list --format="table(name,sourceRanges.list(),allowed[].map().firewall_rule().list())"
NAME       SRC_RANGES         ALLOW
allow-ssh  ['203.0.113.42/32']  tcp:22

One narrowly-scoped rule — this is the state to leave a lesson VM in, and the state the VPC lesson deliberately breaks next by removing outbound internet access.

5. Delete the instance and its disk together to stop all billing.
gcloud compute instances delete web-1 --zone=us-central1-a --quiet
Deleted [https://www.googleapis.com/compute/v1/projects/skillbyexample-437219/zones/us-central1-a/instances/web-1].

By default instances delete also deletes the boot disk, since it was created with autoDelete=true (the default for a disk created alongside its instance) — no separate disk cleanup step needed for this VM.

Next: Cloud Storage — buckets, gsutil vs gcloud storage, and storage classes.

Frequently Asked Questions

What is a Compute Engine machine type?
A named bundle of vCPU count and memory, like e2-micro (2 shared vCPUs, 1 GB RAM) or e2-medium (2 vCPUs, 4 GB RAM). The e2 family is cost-optimized general purpose; e2-micro specifically is the shape covered by the Always Free tier in us-west1, us-central1, and us-east1.
Why can't I SSH into a new Compute Engine VM by default?
A fresh VPC's default-allow-ssh style rules may not exist, or SSH traffic simply isn't allowed to your instance's network tag yet. Compute Engine VMs have no open ingress except what a firewall rule explicitly permits — SSH included — so a rule allowing TCP 22 has to be created first.
What does gcloud compute ssh actually do?
It generates an SSH keypair if you don't have one, pushes the public key to the project or instance metadata, waits for it to propagate, then opens a normal SSH connection through the instance's external IP. It's a convenience wrapper — the underlying transport is ordinary SSH.
Do I get charged for a stopped VM?
You stop paying for vCPU and memory the moment an instance is stopped, but its attached persistent disk keeps billing by the GB-month until you delete the disk too. Deleting the instance without explicitly deleting the boot disk is a common source of surprise charges.
What's the difference between an ephemeral and a static external IP?
An ephemeral IP is assigned when the VM starts and released — and can change — when it stops; a static IP is reserved and keeps the same address across stop/start cycles, but Google bills a small hourly fee for a static IP that is reserved and not attached to a running instance.