Creating Your First GKE Cluster: Step-by-Step Guide

This walkthrough takes you from a fresh GCP project to a running workload on GKE Autopilot. You will enable the required API, create an Autopilot cluster, configure kubectl, deploy an nginx pod, verify it is running, expose it with a Service, and confirm it is reachable from the internet. If you want background on what GKE is before diving in, read the GKE Overview first.

Prerequisites

Before starting, make sure you have:

  • A GCP project with billing enabled. GKE clusters cannot be created without a billing account attached.
  • The gcloud CLI installed and authenticated. Run gcloud auth login and gcloud config set project YOUR_PROJECT_ID to set your active project.
  • kubectl installed. The easiest way is through the gcloud components manager: gcloud components install kubectl.

Verify your setup before proceeding:

gcloud config get-value project
kubectl version --client

The first command should print your project ID. The second should print the kubectl client version without errors.

Step 1: Enable the Kubernetes Engine API

GKE is not enabled by default in a new GCP project. Enable the Kubernetes Engine API before you can create clusters:

gcloud services enable container.googleapis.com

This command takes about 30 seconds. You only need to run this once per project.

Confirm the API is enabled:

gcloud services list --enabled --filter="name:container.googleapis.com"
Note

Enabling the Kubernetes Engine API also automatically enables several dependent APIs, including the Compute Engine API and the Cloud Resource Manager API. You do not need to enable these separately.

Step 2: Create an Autopilot cluster

Create a GKE Autopilot cluster using the create-auto subcommand. Autopilot clusters are always regional — the control plane runs across three zones within the region for high availability.

gcloud container clusters create-auto my-cluster \
  --region=us-central1

What happens during cluster creation:

  1. GKE provisions the Kubernetes control plane in Google-managed infrastructure across three zones in us-central1. You do not see these as VMs in your project.
  2. The cluster’s API server is assigned an external IP address and an SSL certificate is generated.
  3. GKE configures the default node service account and sets up Workload Identity Federation for GKE if enabled.
  4. The cluster is enrolled in the Regular release channel by default.
  5. Cluster networking is configured in your VPC (or the default VPC if you did not specify one).

Cluster creation typically completes in three to five minutes. When control returns to your prompt, the cluster is operational.

Creating cluster my-cluster in us-central1...done.

List your clusters at any time:

gcloud container clusters list

Step 3: Connect kubectl to the cluster

Creating a cluster does not automatically configure kubectl. You must fetch credentials separately. This command retrieves the cluster’s API endpoint and authentication credentials and writes them into your local kubeconfig file (~/.kube/config):

gcloud container clusters get-credentials my-cluster \
  --region=us-central1

Expected output:

Fetching cluster endpoint and auth data.
kubeconfig entry generated for my-cluster.

Verify the connection:

kubectl cluster-info

This prints the addresses of the Kubernetes API server and the DNS service. On an Autopilot cluster, kubectl get nodes may return an empty list — this is expected. Autopilot does not provision nodes until workloads are scheduled.

Analogy

Think of get-credentials as adding a new entry to your contacts app. The cluster already exists and is running, but your phone (kubectl) does not know how to reach it yet. Running get-credentials saves the cluster’s address and the key to authenticate with it.

Step 4: Deploy a sample nginx pod

You can create resources in Kubernetes imperatively (using a single command) or declaratively (by applying a YAML manifest). For learning and production use, the declarative approach is better practice because it produces a file you can version-control and reapply. See Deploying Containers with kubectl for a full explanation of both styles.

Create a file called nginx-pod.yaml with the following content:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
    - name: nginx
      image: nginx:1.27
      ports:
        - containerPort: 80
      resources:
        requests:
          cpu: "250m"
          memory: "128Mi"
        limits:
          cpu: "500m"
          memory: "256Mi"

Apply the manifest to the cluster:

kubectl apply -f nginx-pod.yaml

Expected output:

pod/nginx created
Note

Resource requests and limits are required in GKE Autopilot. Without them, Autopilot cannot determine how much capacity to provision and will reject the pod. This is one of the security and consistency policies Autopilot enforces automatically.

Step 5: Verify the pod is running

Check the status of the pod:

kubectl get pods

When you first run this, the pod may show a status of Pending. On Autopilot, this is expected — GKE is provisioning a node to run the pod. Within a minute or two, the status transitions to Running:

NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          90s

1/1 means one container is running out of one defined in the pod spec. If the pod does not reach Running within a few minutes, inspect it for errors:

kubectl describe pod nginx

kubectl describe prints detailed information about the pod: its scheduled node, the events that occurred during startup, resource usage, and any error messages. The Events section at the bottom is usually the most useful for diagnosing problems. A pod stuck in CrashLoopBackOff indicates the container is starting but crashing repeatedly — the logs are the next thing to check.

To view the logs from the nginx container:

kubectl logs nginx

Step 6: Expose the pod with a Service

The nginx pod has a cluster-internal IP address, but you cannot reach it from the internet directly. You need a Kubernetes Service of type LoadBalancer to expose it. A LoadBalancer Service tells GKE to provision an external GCP load balancer and route traffic to your pod. See Services in Kubernetes for all four service types and when to use each.

Create a file called nginx-service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer

The selector field (app: nginx) matches the label on the pod you created. The Service routes incoming traffic on port 80 to port 80 on any pod with that label.

Apply the Service:

kubectl apply -f nginx-service.yaml

Watch for the external IP address to be assigned:

kubectl get services --watch

Initially the EXTERNAL-IP column shows <pending>. GKE is provisioning a GCP external load balancer in the background. After about 30 to 60 seconds, a public IP address appears:

NAME            TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
nginx-service   LoadBalancer   10.96.120.45    34.102.56.78    80:32456/TCP   90s

Press Ctrl+C to stop watching.

Step 7: Test the deployment

With the external IP address in hand, test that the nginx server is reachable. Replace 34.102.56.78 with the actual IP from your kubectl get services output:

curl http://34.102.56.78

You should receive the default nginx HTML welcome page. You can also open the IP address in a web browser.

Note

This walkthrough deploys a bare pod for simplicity. In production you would deploy a Deployment (not a bare pod) so that Kubernetes can reschedule the workload if the pod or node fails. A bare pod with no owning controller is not rescheduled if its node goes away.

Bonus: Running a command inside a pod

You can execute commands inside a running container with kubectl exec. This is useful for debugging — inspecting configuration files, testing network connectivity, or running diagnostic tools.

Start an interactive shell inside the nginx container:

kubectl exec -it nginx -- /bin/bash

From inside the container you can run commands such as cat /etc/nginx/nginx.conf, curl localhost, or env to inspect environment variables. Type exit to leave the shell.

To run a single command non-interactively:

kubectl exec nginx -- nginx -v

Cleaning up

When you have finished, delete the resources you created to avoid ongoing charges.

Delete the Service (this also de-provisions the external load balancer):

kubectl delete service nginx-service

Delete the pod:

kubectl delete pod nginx

Delete the cluster itself:

gcloud container clusters delete my-cluster \
  --region=us-central1
Warning

Deleting the cluster removes all workloads, services, and persistent volumes associated with it. Make sure you do not need anything running in the cluster before deleting it.

Common beginner mistakes

  1. Not running get-credentials before using kubectl. Creating a cluster with gcloud container clusters create-auto does not update your kubeconfig. Until you run gcloud container clusters get-credentials, every kubectl command will fail with a connection error or target a different cluster entirely.
  2. Expecting nodes immediately on Autopilot. After cluster creation, running kubectl get nodes on an Autopilot cluster returns an empty list. This is not an error — Autopilot provisions nodes only when you schedule a workload. Many beginners assume the cluster is broken and try to recreate it.
  3. Omitting resource requests on Autopilot. GKE Autopilot requires CPU and memory requests on every container. If you apply a pod spec without resource requests, Autopilot rejects the pod with an admission webhook error. Always include resources.requests in your container specs.
  4. Forgetting to delete the Service before the cluster. A LoadBalancer Service provisions an external GCP load balancer. Always delete Services of type LoadBalancer before deleting the cluster to ensure the load balancer is properly de-provisioned.

Frequently asked questions

How long does it take to create a GKE cluster?

A GKE Autopilot cluster typically takes three to five minutes to provision. The control plane must be initialised and the cluster API endpoint must become reachable before you can connect with kubectl. Standard clusters take a similar amount of time, with additional time if many nodes need to be bootstrapped.

Why does kubectl get nodes show no output on an Autopilot cluster?

In GKE Autopilot, nodes are provisioned on demand when you schedule workloads. An empty Autopilot cluster has no nodes running yet, so kubectl get nodes returns an empty list. Once you deploy a pod, GKE provisions the necessary node capacity and the node appears. This is expected behaviour, not an error.

What is a kubeconfig file and where is it stored?

The kubeconfig file (stored at ~/.kube/config by default) holds the API endpoint, credentials, and context information for every Kubernetes cluster kubectl knows about. The gcloud container clusters get-credentials command adds an entry for your GKE cluster. You can inspect the file with kubectl config view and switch between clusters using kubectl config use-context.

My pod is stuck in Pending status. What does that mean?

On Autopilot, Pending is normal for the first minute or two after creating a pod — GKE is provisioning a node to run it. If a pod stays Pending for more than five minutes, run kubectl describe pod POD_NAME and check the Events section. Common causes include missing resource requests (required on Autopilot), insufficient quota, or node pool constraints.

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