Skip to content

Create Private GKE Autopilot Cluster using gcloud CLI

This tutorial guides you through creating a Private, VPC-native GKE Autopilot cluster. Private clusters isolate nodes from the public internet, enhancing security.

What is GKE Autopilot?

GKE Autopilot is a mode of operation in Google Kubernetes Engine (GKE) that manages the underlying infrastructure for you. Unlike the Standard mode, where you manage the nodes (VMs), Autopilot automatically provisions and scales the compute resources based on your workload's requirements.

It adheres to Kubernetes best practices and offers a hands-off experience, allowing you to focus on your applications rather than cluster management.

Pod Isolation vs. AWS Fargate

In GKE Autopilot, pods run on shared nodes (VMs) by default, similar to standard Kubernetes. They share the same kernel. This is different from AWS Fargate for EKS, where each pod runs in its own isolated micro-VM.

If you need stronger isolation (sandbox), you can use GKE Sandbox (gVisor), but standard Autopilot pods are not VM-isolated from each other on the same node.

GKE Autopilot vs. Standard

Feature GKE Autopilot GKE Standard
Management Fully managed (Nodes & Control Plane) Control Plane managed, Nodes user-managed
Pricing Pay for Pod requests (vCPU, Memory) Pay for Nodes (VMs)
SLA 99.95% (Regional) Depends on configuration
Node Access Locked down (No SSH) Full access (SSH allowed)
Best Practices Enforced by default User responsibility
Operational Overhead Low Medium/High

What is a Private Cluster?

A Private Cluster in GKE is a cluster where the nodes do not have public IP addresses. This means the nodes are isolated from the internet and can only be accessed through the Virtual Private Cloud (VPC) network or via an authorized proxy/bastion.

This significantly reduces the attack surface of your cluster, as the nodes are not directly exposed to external threats.

Why Private Endpoint Matters?

The Private Endpoint controls access to the cluster's control plane (master).

  • Public Endpoint (Default): The control plane has a public IP address. You can access it from anywhere (e.g., your laptop) if you have the correct credentials and your IP is authorized.
  • Private Endpoint: The control plane has only a private IP address within your VPC. You can only access it from within the VPC (e.g., from a bastion host or via VPN/Interconnect).

Disabling access to the public endpoint (setting private endpoint to true) is the most secure configuration, but it makes accessing the cluster for management more complex (requires a bastion).

Prerequisites

  1. GCP Project: Billing enabled.
  2. gcloud CLI: Installed and authorized.
  3. Permissions: roles/container.admin, roles/compute.networkAdmin.

Network Requirements

GKE Autopilot clusters are VPC-native. This means pods and services get IP addresses from the VPC.

For a small cluster with ~3 deployments (scaling up to a few dozen pods), we need:

  • Subnet Primary Range (Nodes): /24 (256 IPs, nodes need IPs).
  • Pod Secondary Range: /21 (2048 IPs). Autopilot allocates full ranges to nodes, so we need a generous range even for few pods.
  • Service Secondary Range: /20 (4096 IPs).

Plan IP Ranges Carefully

Once a VPC or Subnet ranges are assigned, primary ranges cannot be easily modified. Ensure your ranges are large enough for future growth to avoid IP exhaustion.

Step 1: Network Setup

Create a dedicated VPC and Subnet.

  1. Create VPC:

    export PROJECT_ID=$(gcloud config get-value project)
    export REGION=us-central1
    export NETWORK_NAME=gke-private-net
    export SUBNET_NAME=gke-private-subnet
    
    gcloud compute networks create $NETWORK_NAME \
        --subnet-mode=custom \
        --bgp-routing-mode=regional
    

  2. Create Subnet with Secondary Ranges:

    gcloud compute networks subnets create $SUBNET_NAME \
        --network=$NETWORK_NAME \
        --region=$REGION \
        --range=10.0.0.0/24 \
        --secondary-range=pods=10.1.0.0/21,services=10.2.0.0/20 \
        --enable-private-ip-google-access
    

    • --enable-private-ip-google-access: Required for private nodes to reach Google APIs (like Artifact Registry).
  3. Create Firewall Rule (Optional): Allow internal communication (useful for testing later).

    gcloud compute firewall-rules create allow-internal-gke \
        --network=$NETWORK_NAME \
        --allow=tcp,udp,icmp \
        --source-ranges=10.0.0.0/8
    

Step 2: Create GKE Autopilot Cluster

Create the cluster with private nodes.

  • --enable-private-nodes: Nodes have only internal IPs.
  • --master-ipv4-cidr: A /28 range for the control plane (must not overlap with other ranges).

Autopilot Mode

The command gcloud container clusters create-auto automatically creates an Autopilot cluster. If you were using the standard create command, you would need to pass the --enable-autopilot flag to enable this mode.

export CLUSTER_NAME=my-private-autopilot

gcloud container clusters create-auto $CLUSTER_NAME \
    --region=$REGION \
    --network=$NETWORK_NAME \
    --subnetwork=$SUBNET_NAME \
    --cluster-secondary-range-name=pods \
    --services-secondary-range-name=services \
    --enable-private-nodes \
    --enable-private-endpoint \
    --master-authorized-networks=10.0.0.0/24 \
    --master-ipv4-cidr=172.16.0.0/28
  • --enable-private-endpoint: The control plane has only a private IP address. It is not accessible from the public internet.
  • --master-authorized-networks: Restricts access to the control plane to specific IP ranges. We allow the subnet range (10.0.0.0/24) where our Bastion Host will reside.

Understanding Private Cluster Flags

  • Private Cluster (--enable-private-nodes): Makes the Worker Nodes private (no public IPs). This is the main requirement for a "Private Cluster".
  • Private Endpoint (--enable-private-endpoint): Makes the Control Plane private. If omitted (defaults to false), the Control Plane remains accessible via a Public Endpoint.

Step 3: Create Bastion Host

Since the cluster control plane is private, we need a Bastion Host (a VM inside the VPC) to run kubectl commands.

  1. Create the VM:

    gcloud compute instances create gke-bastion \
        --zone=${REGION}-a \
        --network=$NETWORK_NAME \
        --subnet=$SUBNET_NAME \
        --machine-type=e2-micro \
        --tags=bastion
    

  2. Allow SSH Access: Create a firewall rule to allow SSH (port 22) into the Bastion Host (via IAP).

    gcloud compute firewall-rules create allow-ssh-bastion \
        --network=$NETWORK_NAME \
        --allow=tcp:22 \
        --source-ranges=35.235.240.0/20 \
        --target-tags=bastion
    

    • 35.235.240.0/20: The IP range used by Identity-Aware Proxy (IAP) for TCP forwarding.

Step 4: Access the Cluster

Now, we will log in to the Bastion Host and access the cluster.

  1. SSH into Bastion:

    gcloud compute ssh gke-bastion --zone=${REGION}-a --tunnel-through-iap
    

  2. Install kubectl and Auth Plugin (Inside the Bastion):

    sudo apt-get update
    sudo apt-get install -y kubectl google-cloud-sdk-gke-gcloud-auth-plugin
    

  3. Get Credentials:

    export CLUSTER_NAME=my-private-autopilot
    export REGION=us-central1
    
    gcloud container clusters get-credentials $CLUSTER_NAME --region $REGION --internal-ip
    

    • --internal-ip: Tells kubectl to communicate with the cluster's private IP address.

Step 5: Verify Cluster (From Bastion)

  1. Check Nodes:

    kubectl get nodes -o wide
    
    You should see nodes with INTERNAL-IP but no EXTERNAL-IP.

  2. Deploy a Test App:

    kubectl create deployment nginx --image=nginx
    
    Autopilot will automatically provision resources.

    Provisioning Time

    Since Autopilot provisions nodes dynamically based on your workloads, the first deployment might take a few minutes while the necessary compute infrastructure is spun up.

  3. Check Pods:

    kubectl get pods -w
    
    Wait for the pod to become Running.

Quiz

#

In a Private GKE Cluster, what does the --enable-private-nodes flag ensure?

#

Which flag is required to make the GKE Control Plane private (accessible only within the VPC)?

#

How can you access a GKE cluster that has a private control plane?

Cleanup

gcloud container clusters delete $CLUSTER_NAME --region=$REGION --quiet
gcloud compute networks subnets delete $SUBNET_NAME --region=$REGION --quiet
gcloud compute networks delete $NETWORK_NAME --quiet

📬 DevopsPilot Weekly — Learn DevOps, Cloud & Gen AI the simple way.
👉 Subscribe here