# How to Design a Production-Grade Google Cloud Landing Zone with Terraform

Before you deploy applications to Google Cloud, you need clear boundaries. You need to know which project each resource lives in, which network it uses, who can access it, and which security controls apply.

A landing zone gives you that foundation. It separates shared platform resources from application workloads. It also sets clear boundaries between production and non-production environments.

This guide shows you how to design a production-grade landing zone using Organizations, Folders, Projects, IAM, Shared VPC, Network Connectivity Center (NCC), centralized egress, and Terraform.

### Problem Statement

A growing Google Cloud environment holds two kinds of resources. Networking, DNS, logging, security services, and artifact repositories usually support many teams. Databases, application workloads, and workload-specific service accounts usually belong to one application.

Treating both kinds the same way causes problems. Putting production and development in the same project makes access control harder. Giving every application its own VPC fragments IP planning and duplicates firewall rules. Letting every team manage shared networking raises the risk that one team’s change breaks another team’s workload.

**A good landing zone answers four questions:**

*   Which resources are shared?
    
*   Which resources belong to one workload?
    
*   Which boundaries separate production from non-production?
    
*   Which controls should apply everywhere?
    

### What You Will Build

The landing zone uses five management areas.

*   **Bootstrap:** Terraform state, Workload Identity Federation, CI/CD identities.
    
*   **Security:** Key management, audit logging, security controls.
    
*   **Networking:** Shared VPC host projects, NCC, routing, centralized egress.
    
*   **Common Services:** Monitoring, billing exports, artifact repositories.
    
*   **Workloads:** Application and platform projects, split by environment.
    

![](https://cdn.hashnode.com/uploads/covers/62d3d92a2f40e31decd8c583/26495247-fb84-42e0-9a74-ab7b1d4ab3a1.png align="center")

This structure separates shared platform responsibilities from workload ownership.

### The Resource Hierarchy

Google Cloud offers an organization hierarchy to help you group and manage resources effectively.

**The main levels are:**

*   **Organization:** Represents the company or Google Cloud resource owner.
    
*   **Folders:** Group projects by environment, team, business unit, or security requirements.
    
*   **Projects:** Provide a management and isolation boundary for cloud resources.
    
*   **Resources:** Include services like Compute Engine, GKE, Cloud Storage, Cloud SQL, Pub/Sub, Cloud Run, and more.
    

The hierarchy matters for IAM and organization policies because you can apply controls at different levels. For example, a policy set on a production folder will affect all projects and resources within it.

![](https://cdn.hashnode.com/uploads/covers/62d3d92a2f40e31decd8c583/7f9a5322-99f2-446b-ba3a-9994f0f651a4.png align="center")

### Bootstrap: Build the Management Foundation First

The bootstrap layer contains the essentials for managing your environment. This includes Terraform state storage, Workload Identity Federation, CI/CD identities, initial management projects, and bootstrap policies.

Keep this layer simple and minimal. Changes here can affect your ability to manage the rest of your environment.

*   **Terraform state:** Use a remote backend such as Cloud Storage. Avoid storing state files on developer machines. Separate state files by boundary networking, security, and workloads; each should have its own.
    

```plaintext
terraform {
  backend "gcs" {
    bucket = "YOUR_TERRAFORM_STATE_BUCKET"
    prefix = "foundation"
  }
}
```

*   **Workload Identity Federation:** The CI/CD pipeline doesn’t need to store long-lived service account keys. Instead, an external identity provider like GitHub Actions can exchange a short-lived token for Google Cloud credentials.
    

```plaintext
resource "google_iam_workload_identity_pool" "cicd" {
  project                   = var.bootstrap_project_id
  workload_identity_pool_id = "cicd-pool"
  display_name              = "CI/CD Identity Pool"
}
```

### Security: Set Up Central Controls Early

Put security controls in place before deploying any workloads. This covers Cloud KMS, key rings and crypto keys, audit logging, security monitoring, VPC Service Controls as needed, and security policies.

Assign a single owner for these controls. Avoid duplicating them in every workload project.

```plaintext
resource "google_kms_key_ring" "platform" {
  name     = "platform-keyring"
  location = var.region
  project  = var.security_project_id
}

resource "google_kms_crypto_key" "workload" {
  name            = "workload-key"
  key_ring        = google_kms_key_ring.platform.id
  rotation_period = "7776000s"

  lifecycle {
    prevent_destroy = true
  }
}
```

## Networking: Separate Ownership from Use

The networking team owns VPCs, subnets, routes, firewall policies, Cloud Routers, NCC, Shared VPC, and centralized egress. Application teams use these approved resources but do not own the shared infrastructure.

*   **Shared VPC** allows a host project to provide network resources to service projects. The host project manages the VPC and its settings, while service projects contain workload resources that use the approved subnets.
    
*   **Production vs. non-production.** Use separate Shared VPC host projects for each environment. Each one gets its own IAM policy, firewall rules, routes, and egress policy. Production should not depend on the same network state as development when you need real isolation.
    
*   **Deciding what to share.** Base the decision on ownership, security, lifecycle, and failure impact, not on convenience. A Shared VPC helps many teams under one owner. Keep a database used by one application with that application.
    

### Workloads: Give Applications Their Own Boundaries

Each workload project should have its own ownership, lifecycle, and access rules. Separate them by application and environment. This approach makes it easier to manage IAM, billing, quotas, and deployment access.

![](https://cdn.hashnode.com/uploads/covers/62d3d92a2f40e31decd8c583/295fa57b-4af9-46ec-9bfc-5e88116851d2.png align="center")

### Network Connectivity Center

When you have many VPCs, point-to-point connections become hard to scale. Network Connectivity Center (NCC) offers a hub-and-spoke model to simplify this.

```plaintext
resource "google_network_connectivity_hub" "platform" {
  project         = var.network_hub_project_id
  name            = "platform-hub"
  policy_mode     = "PRESET"
  preset_topology = "STAR"
}

resource "google_network_connectivity_spoke" "production" {
  project  = var.network_hub_project_id
  name     = "production-network"
  location = "global"
  hub      = google_network_connectivity_hub.platform.id

  linked_vpc_network {
    uri = google_compute_network.production_vpc.self_link
  }
}
```

### Centralized Internet Egress

Send outbound internet traffic through a dedicated egress VPC. This centralizes control and auditing, rather than allowing each VPC to create its own route.

```plaintext
resource "google_compute_network" "egress" {
  project                 = var.egress_project_id
  name                    = "egress-vpc"
  auto_create_subnetworks = false
}

resource "google_compute_router" "egress" {
  project = var.egress_project_id
  name    = "egress-router"
  region  = var.region
  network = google_compute_network.egress.id
}

resource "google_compute_router_nat" "egress" {
  project                            = var.egress_project_id
  name                               = "egress-nat"
  router                             = google_compute_router.egress.name
  region                             = var.region
  nat_ip_allocate_option             = "AUTO_ONLY"
  source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"

  log_config {
    enable = true
    filter = "ERRORS_ONLY"
  }
}
```

Cloud NAT by itself does not automatically route traffic from every VPC through it. You need to design the routing, peering, and firewall policies to direct packets as needed.

For Google APIs and Google Cloud services, use Private Google Access when appropriate, instead of routing that traffic through internet NAT.

### IAM, Billing, and Organization Policy

*   **IAM:** Roles should follow ownership. Use groups instead of individual users, keep production access restricted, and use dedicated CI/CD identities for production deployments.
    
*   **Billing:** Set up billing ownership, budgets, and alerts from day one. Use consistent project names and labels for cost tracking. Remember that budgets alert you but do not stop spending.
    
*   **Organization Policies:** Enforce common rules across the hierarchy, such as resource locations and external IP restrictions. Test restrictive policies in non-production before applying them to production.
    

### Common Mistakes

*   Putting unrelated workloads in one project.
    
*   Granting broad permissions instead of least privilege.
    
*   Using personal or long-lived credentials for workloads.
    
*   Letting application teams control shared networking.
    
*   Sharing production and non-production networks.
    
*   Applying restrictive organization policies without testing them first.
    

### Conclusion

A Google Cloud landing zone creates clear boundaries for teams, workloads, networking, security, and shared services. By separating bootstrap, security, networking, common services, and workloads and using Shared VPC and NCC for connectivity, you build a foundation that’s easy to manage and repeat with Terraform. The aim isn’t complexity, but a simple structure with clear ownership, controlled access, and flexibility to grow as more teams and workloads join.
