GCP Provider Setup
Why GCP with Pulumi?
The Problem: Google Cloud's Deployment Manager uses YAML/Jinja templates that lack type safety and are difficult to test or refactor.
The Solution: Pulumi provides first-class GCP support with auto-generated types from the Google Cloud API, giving you complete coverage and type safety.
Real Impact: Pulumi's GCP Native provider covers 100% of Google Cloud resources on day one of their release, keeping your IaC always up to date.
Real-World Analogy
Think of GCP with Pulumi as a smart factory automation system:
- Projects = Factory buildings that isolate different product lines
- VPC Networks = Internal conveyor belt systems connecting machines
- Compute Engine = Heavy-duty machines on the factory floor
- Cloud Functions = Automated sensors that trigger actions on demand
- Cloud Storage = Warehouses that store raw materials and finished goods
Key GCP Concepts in Pulumi
Project-Based Organization
GCP organizes resources into projects. Configure the project and region in Pulumi config for consistent deployments.
GCP Native Provider
Auto-generated from Google's API discovery documents, providing 100% resource coverage with accurate types.
Service Account Auth
Use service accounts with JSON key files or workload identity for secure authentication in CI/CD pipelines.
Labels Strategy
Apply consistent labels across all GCP resources for cost allocation, environment tracking, and team ownership.
Installing the GCP Provider
# Create a new Pulumi GCP project
pulumi new gcp-typescript
# Install the GCP provider
npm install @pulumi/gcp
# Configure project and region
pulumi config set gcp:project my-gcp-project-id
pulumi config set gcp:region us-central1
# Authenticate with gcloud CLI
gcloud auth application-default login
VPC & Networking
Creating VPC and Subnets
import * as gcp from "@pulumi/gcp";
// Create a custom VPC network
const network = new gcp.compute.Network("app-network", {
autoCreateSubnetworks: false,
description: "Main application VPC",
});
// Create subnets in different regions
const subnetCentral = new gcp.compute.Subnetwork("central-subnet", {
network: network.id,
ipCidrRange: "10.0.1.0/24",
region: "us-central1",
privateIpGoogleAccess: true,
});
const subnetEast = new gcp.compute.Subnetwork("east-subnet", {
network: network.id,
ipCidrRange: "10.0.2.0/24",
region: "us-east1",
});
// Firewall rule for HTTP traffic
const httpFirewall = new gcp.compute.Firewall("allow-http", {
network: network.id,
allows: [{ protocol: "tcp", ports: ["80", "443"] }],
sourceRanges: ["0.0.0.0/0"],
targetTags: ["web-server"],
});
// Cloud Router for NAT
const router = new gcp.compute.Router("nat-router", {
network: network.id,
region: "us-central1",
});
const nat = new gcp.compute.RouterNat("cloud-nat", {
router: router.name,
region: "us-central1",
natIpAllocateOption: "AUTO_ONLY",
sourceSubnetworkIpRangesToNat: "ALL_SUBNETWORKS_ALL_IP_RANGES",
});
Compute (GCE & Cloud Functions)
Compute Engine Instance
// Create a Compute Engine instance
const instance = new gcp.compute.Instance("web-server", {
machineType: "e2-medium",
zone: "us-central1-a",
bootDisk: {
initializeParams: {
image: "debian-cloud/debian-11",
size: 20,
},
},
networkInterfaces: [{
network: network.id,
subnetwork: subnetCentral.id,
accessConfigs: [{}], // Gives external IP
}],
metadataStartupScript: `#!/bin/bash
apt-get update
apt-get install -y nginx
echo "Hello from Pulumi on GCP!" > /var/www/html/index.html
systemctl start nginx`,
tags: ["web-server"],
labels: { environment: pulumi.getStack() },
});
export const instanceIp = instance.networkInterfaces[0].accessConfigs[0].natIp;
Cloud Functions
// Cloud Storage bucket for function source
const sourceBucket = new gcp.storage.Bucket("func-source", {
location: "US",
uniformBucketLevelAccess: true,
});
// Upload function source code
const sourceArchive = new gcp.storage.BucketObject("func-zip", {
bucket: sourceBucket.name,
source: new pulumi.asset.FileArchive("./function-source"),
});
// Create the Cloud Function
const func = new gcp.cloudfunctions.Function("api-function", {
runtime: "nodejs18",
entryPoint: "handler",
sourceArchiveBucket: sourceBucket.name,
sourceArchiveObject: sourceArchive.name,
triggerHttp: true,
availableMemoryMb: 256,
environmentVariables: {
STAGE: pulumi.getStack(),
},
});
// Allow public invocation
const invoker = new gcp.cloudfunctions.FunctionIamMember("invoker", {
cloudFunction: func.name,
role: "roles/cloudfunctions.invoker",
member: "allUsers",
});
export const functionUrl = func.httpsTriggerUrl;
Storage (GCS & Firestore)
Cloud Storage and Firestore
// Cloud Storage bucket with lifecycle rules
const dataBucket = new gcp.storage.Bucket("data-bucket", {
location: "US",
storageClass: "STANDARD",
uniformBucketLevelAccess: true,
versioning: { enabled: true },
lifecycleRules: [{
action: { type: "SetStorageClass", storageClass: "NEARLINE" },
condition: { age: 30 },
}, {
action: { type: "Delete" },
condition: { age: 365 },
}],
labels: { environment: pulumi.getStack() },
});
// Firestore database (Native mode)
const firestore = new gcp.firestore.Database("app-db", {
locationId: "us-central",
type: "FIRESTORE_NATIVE",
});
export const bucketUrl = dataBucket.url;
IAM & Service Accounts
Service Accounts and IAM Bindings
// Create a service account for the application
const appSa = new gcp.serviceaccount.Account("app-sa", {
accountId: "app-service-account",
displayName: "Application Service Account",
});
// Grant Storage Object Viewer role
new gcp.storage.BucketIAMMember("bucket-viewer", {
bucket: dataBucket.name,
role: "roles/storage.objectViewer",
member: appSa.email.apply(e => `serviceAccount:${e}`),
});
// Grant Firestore User role at project level
new gcp.projects.IAMMember("firestore-user", {
role: "roles/datastore.user",
member: appSa.email.apply(e => `serviceAccount:${e}`),
});
export const serviceAccountEmail = appSa.email;
Quick Reference
GCP Resource Cheat Sheet
| Resource | Pulumi Class | Key Properties |
|---|---|---|
| VPC Network | gcp.compute.Network |
autoCreateSubnetworks, description |
| Subnet | gcp.compute.Subnetwork |
ipCidrRange, region, network |
| GCE Instance | gcp.compute.Instance |
machineType, zone, bootDisk |
| Cloud Function | gcp.cloudfunctions.Function |
runtime, entryPoint, triggerHttp |
| Cloud Storage | gcp.storage.Bucket |
location, storageClass, versioning |
| Firestore | gcp.firestore.Database |
locationId, type |
| Service Account | gcp.serviceaccount.Account |
accountId, displayName |
GCP Authentication Methods
Authentication Options
gcloud auth application-default login- Interactive login for development- Service Account Key - Set GOOGLE_CREDENTIALS env var with JSON key file path
- Workload Identity - Federate with GitHub Actions or other OIDC providers
- GCE Metadata - Automatic when running on Compute Engine or GKE