Private GKE Clusters: Private Nodes and Control Plane Access Explained

Standard GKE clusters give every node a public IP address. That simplifies outbound access, but it also puts every node directly on the internet. A misconfigured service or a debug port left open is reachable by anyone. A private GKE cluster removes public IP addresses from nodes entirely. Your workloads run on the same infrastructure, but nodes are only reachable through your VPC.

The short version

Analogy

A standard GKE cluster is like an office building with its front door on a public street. Anyone walking past can try the handle. A private cluster moves that same building into a gated campus. It works identically on the inside, but nobody from the street can reach it directly.

In practice there are two independent things you can make private:

  • Private nodes: Each node gets a private IP like 10.0.0.x instead of a public internet IP. Nothing on the internet can initiate a connection to your nodes.
  • Private control plane (optional): The Kubernetes API server can also be made private. By default, even a private cluster still has a public endpoint for the API server. You can remove that public endpoint so kubectl only works from within your VPC or a connected network.

The trade-off is real: outbound internet access from nodes and inbound access from CI/CD systems both require deliberate configuration. You cannot run kubectl apply from your laptop if the control plane is fully private, unless you have planned for it.

What a private GKE cluster is

A private GKE cluster is a cluster where every node has only a private RFC 1918 IP address. Nodes have no ephemeral external IP and cannot receive inbound connections from the internet.

Three things are worth distinguishing clearly:

Private nodes (--enable-private-nodes) removes public IPs from the worker nodes that run your workloads. This is the core of a private cluster. Even a misconfigured Service or Ingress cannot be reached from the internet at the node level.

Private endpoint (--enable-private-endpoint) is an additional, optional step that also removes the public IP from the Kubernetes API server. Without this flag, even a private cluster still exposes the API server publicly. It is protected by authentication and optionally by authorized networks, but it is still reachable from the internet.

VPC-native vs private cluster are different concepts. A VPC-native cluster refers to how pod IPs are allocated using alias IP ranges on your subnet. A private cluster refers to whether nodes have external IPs. Every private cluster is VPC-native, but a VPC-native cluster is not necessarily private.

How private GKE clusters work

When you create a private cluster, GKE provisions several things behind the scenes.

Node IP assignment. Nodes receive their primary IP from your subnet. The subnet has no external IPs enabled. Nodes have no internet-routable address and exist only on your VPC.

Control plane VPC peering. The Kubernetes API server runs in a Google-managed VPC that is not visible in your project. GKE automatically creates a VPC peering connection between your VPC and Google’s control plane VPC. Node-to-control-plane traffic travels over this peering link using private IPs.

Control plane CIDR (--master-ipv4-cidr). You specify a /28 IP range for the VPC peering link to the control plane. This range must not overlap with any subnet in your VPC, any peered VPC, or any on-premises ranges connected via Cloud VPN or Cloud Interconnect. A common non-overlapping choice is 172.16.0.0/28.

Public endpoint (default on). Unless you pass --enable-private-endpoint, the API server still has a public IP. You can lock it down further with --enable-master-authorized-networks to whitelist specific CIDRs.

Outbound internet. Private nodes have no external IP, so they cannot initiate outbound internet connections directly. Workloads that need internet access require Cloud NAT. For traffic to Google APIs and Artifact Registry, Private Google Access avoids the internet entirely.

Warning

The —master-ipv4-cidr range is permanent. It cannot be changed after cluster creation. Overlapping ranges cause VPC peering failures that can appear as confusing cluster creation errors. Plan your IP space before you run the command.

When to use private GKE clusters

Tip

Private clusters are a good fit when you are running production workloads with sensitive data, working in a regulated environment, or your organisation already has private networking in place. The extra setup cost is lower when the network foundation already exists.

Good fits:

  • Production workloads with sensitive data. If your cluster handles customer data, financial transactions, or credentials, removing nodes from direct internet exposure is a sensible baseline.
  • Regulated environments. Many frameworks (PCI DSS, HIPAA, ISO 27001) require that systems holding sensitive data not be directly reachable from the internet. Private nodes satisfy that requirement at the node level.
  • Teams already using private networking. If your organisation already has Cloud VPN, Cloud Interconnect, or a Shared VPC setup, the additional complexity is minimal because the connectivity already exists.
  • Reducing the blast radius of misconfigurations. A misconfigured NodePort, a debug endpoint left open, or a service inadvertently exposed — with private nodes, none of these are reachable from the internet. It is a useful safety net on top of NetworkPolicy and RBAC.
When private clusters may be overkill

If you are learning GKE, building a proof of concept, or running short-lived dev clusters that handle no sensitive data, the extra networking setup adds friction without much benefit. A standard cluster with —enable-master-authorized-networks restricting control plane access is often simpler and sufficient. Do not reach for private clusters before you have a plan for how CI/CD pipelines and operators will reach the API server.

Private vs public clusters: comparison

Public cluster vs private cluster:

Public clusterPrivate cluster
Node internet exposureNodes have public IPs; reachable from internetNodes have only private IPs; not reachable from internet
Outbound internet from nodesDirect, no extra configRequires Cloud NAT (or Private Google Access for Google APIs)
Image pulls from Docker HubDirectVia Cloud NAT
Image pulls from Artifact RegistryDirectVia Private Google Access (no internet needed)
Control plane accessPublic IP, optionally restricted by authorized networksPublic or private IP depending on flags
CI/CD complexityLow, any runner worksHigher, private pool or VPN or bastion required for private endpoint
Compliance suitabilityLowerHigher

--enable-private-nodes vs --enable-private-endpoint:

FlagWhat it affectsEffect
--enable-private-nodesWorker nodes (data plane)Removes public IPs from nodes. Nodes are not reachable from the internet.
--enable-private-endpointAPI server (control plane)Removes the public IP from the Kubernetes API server. kubectl only works from inside the VPC or a connected network.

You can use --enable-private-nodes without --enable-private-endpoint. This is the most common starting point: nodes are private, but you can still run kubectl from your laptop or a CI/CD runner on the public internet with authorized networks restricting access.

Adding --enable-private-endpoint on top locks down the control plane too, but requires planning for how operators and pipelines will reach it.

Creating a private GKE cluster

Private nodes only (control plane still has a public endpoint):

gcloud container clusters create my-private-cluster \
  --region=europe-west2 \
  --network=my-vpc \
  --subnetwork=my-private-subnet \
  --enable-private-nodes \
  --master-ipv4-cidr=172.16.0.0/28 \
  --enable-ip-alias
  • --enable-private-nodes: removes public IPs from nodes
  • --master-ipv4-cidr: the /28 range for the control plane peering link; must not overlap any other range in your VPC
  • --enable-ip-alias: required for VPC-native networking (alias IPs for pods and services)

Private nodes with authorized networks (recommended middle ground):

gcloud container clusters create my-private-cluster \
  --region=europe-west2 \
  --network=my-vpc \
  --subnetwork=my-private-subnet \
  --enable-private-nodes \
  --master-ipv4-cidr=172.16.0.0/28 \
  --enable-master-authorized-networks \
  --master-authorized-networks=203.0.113.0/24 \
  --enable-ip-alias

--enable-master-authorized-networks restricts which external IP ranges can reach the public control plane endpoint. Replace 203.0.113.0/24 with your office or CI/CD runner IP range. This is often the right balance for teams that need both node isolation and straightforward kubectl access from known locations.

Private nodes and private endpoint (fully private):

gcloud container clusters create my-private-cluster \
  --region=europe-west2 \
  --network=my-vpc \
  --subnetwork=my-private-subnet \
  --enable-private-nodes \
  --master-ipv4-cidr=172.16.0.0/28 \
  --enable-private-endpoint \
  --enable-ip-alias
Danger

With —enable-private-endpoint, the Kubernetes API server has no public IP. If you run this command without first setting up a Cloud Build private pool, VPN, Interconnect, or bastion host, you will have no way to run kubectl. Verify your access path before enabling a private endpoint.

Note

If you are creating a private cluster inside a Shared VPC, additional IAM permissions are required on the host project. The GKE service account in the service project needs the roles/container.hostServiceAgentUser role in the host project.

Cloud NAT for outbound internet access

Private nodes have no external IP, so they cannot initiate outbound connections to the internet. Cloud NAT is a Google-managed service that provides outbound internet connectivity for VMs with only private IPs, without allowing any inbound connections.

Cloud NAT is required if your nodes or workloads need to reach anything on the public internet: pulling images from Docker Hub, calling an external API, fetching package updates.

Setting up Cloud NAT requires a Cloud Router in the same region as the cluster:

# Create a Cloud Router
gcloud compute routers create my-nat-router \
  --region=europe-west2 \
  --network=my-vpc

# Create a Cloud NAT config on the router
gcloud compute routers nats create my-nat-config \
  --router=my-nat-router \
  --region=europe-west2 \
  --auto-allocate-nat-external-ips \
  --nat-all-subnet-ip-ranges

--auto-allocate-nat-external-ips provisions external IPs automatically. If you need stable outbound IPs, for example to whitelist with an external API provider, reserve static IPs first and pass them with --nat-external-ip-pool.

Tip

If you store all container images in Artifact Registry, you may not need Cloud NAT for image pulls at all. Enable Private Google Access on the node subnet and nodes will reach Artifact Registry, Secret Manager, Cloud Logging, and other Google APIs over Google’s internal network without touching the internet.

Enable Private Google Access on a subnet:

gcloud compute networks subnets update my-private-subnet \
  --region=europe-west2 \
  --enable-private-ip-google-access

Accessing private clusters from CI/CD pipelines

When --enable-private-endpoint is used, the API server has no public IP. CI/CD runners on the public internet cannot reach kubectl directly. Here are the main options.

Cloud Build private pools (recommended for GCP-native CI/CD). Cloud Build Private Pools run workers inside your VPC. A worker in the same VPC as the cluster can reach the private control plane endpoint without any extra networking.

# Configure kubectl to use the internal control plane IP
gcloud container clusters get-credentials my-private-cluster \
  --region=europe-west2 \
  --internal-ip

The --internal-ip flag tells gcloud to write the private control plane IP into your kubeconfig rather than the public one.

Bastion host. A small VM in the same VPC serves as a jump host. Operators SSH in and run kubectl from there. This is the simplest option for ad-hoc access.

Cloud VPN or Cloud Interconnect. If your organisation has Cloud VPN or Cloud Interconnect linking your on-premises network to the GKE VPC, operators and CI/CD systems on-premises can reach the private endpoint over the private link.

GitHub Actions or other external CI/CD. Without one of the above options, external CI/CD runners cannot reach a fully private control plane. The recommended pattern is to connect GitHub Actions through a self-hosted runner inside the VPC, or use a VPN gateway to bridge the runner network.

Note

CI/CD pipelines deploying to private clusters still need the right Google Cloud IAM permissions regardless of how they reach the control plane. Use Workload Identity for GCP-native pipelines rather than long-lived service account keys.

Common mistakes

  1. Forgetting Cloud NAT before the first node pool comes up. After creating a private cluster, the most common immediate problem is that nodes cannot pull container images. Nodes have no internet route. Set up a Cloud Router and Cloud NAT gateway before creating the cluster, or use Artifact Registry with Private Google Access so image pulls never require internet access.
  2. Choosing a —master-ipv4-cidr that overlaps with existing ranges. This range must be a /28 and must not overlap with any subnet in your VPC, any peered VPC, or any on-premises ranges connected via VPN or Interconnect. Overlapping ranges cause VPC peering failures that can appear as confusing cluster creation errors. This cannot be changed after cluster creation.
  3. Enabling —enable-private-endpoint without a plan for kubectl access. Once the public endpoint is removed, you cannot run kubectl from outside the VPC. If you do this without first setting up a private pool, VPN, Interconnect, or bastion, you lose access to the cluster’s API server.
  4. Assuming private nodes make the cluster fully isolated. Private nodes prevent inbound internet connections to nodes, but they do not control pod-to-pod traffic, RBAC permissions, or secrets access. NetworkPolicy, Workload Identity, and RBAC are still necessary. Private nodes complement those controls rather than replacing them.
  5. Not accounting for peered VPC range conflicts. If your VPC is peered to other VPCs (including through Shared VPC), the —master-ipv4-cidr range must not overlap ranges in those peered networks. Transitive peering is not supported in GCP, but the direct peering link can still conflict.

Frequently asked questions

What is a private GKE cluster?

A private GKE cluster is a cluster where every node has only a private RFC 1918 IP address, with no public internet IP. Nodes cannot receive unsolicited inbound connections from the internet. The Kubernetes API server (control plane) can optionally also be made private-only, so kubectl only works from within your VPC or a connected network.

Can I make an existing GKE cluster private?

Some private networking settings can be enabled on existing clusters after creation. However, for significant changes like enabling private nodes or a private endpoint on a busy production cluster, creating a new private cluster and migrating workloads is usually safer and less likely to cause disruption.

Do private GKE nodes need Cloud NAT?

Only if they need to reach the public internet, for example to pull images from Docker Hub or call external APIs. If you store all images in Artifact Registry and enable Private Google Access on the node subnet, nodes can reach Google APIs and Artifact Registry internally without Cloud NAT. Cloud NAT becomes necessary only when workloads need outbound internet access beyond Google's network.

What is the difference between --enable-private-nodes and --enable-private-endpoint?

--enable-private-nodes removes public IP addresses from the nodes (the data plane). --enable-private-endpoint additionally removes the public IP from the Kubernetes API server (the control plane), making it accessible only from within the VPC or a connected network. You can use --enable-private-nodes without --enable-private-endpoint if you want private nodes but still need to reach the control plane from outside the VPC.

When should I avoid private GKE clusters?

Private clusters add operational overhead: Cloud NAT for outbound internet access, private connectivity for CI/CD pipelines, and planning for kubectl access. For learning environments, short-lived dev clusters, or teams without existing private networking, a standard cluster with authorized networks restricting control plane access is often simpler and sufficient.

Last verified: 23 March 2026 Cloud services change frequently. Verify details against official documentation before making infrastructure decisions.