Skip to content
Learni
View all tutorials
Cloud

How to Deploy an App on Google Kubernetes Engine (GKE) in 2026

Lire en français

Introduction

Google Kubernetes Engine (GKE) is Google Cloud's managed service for orchestrating containers with Kubernetes. It simplifies cluster management by handling updates, scalability, and security, so you can focus on your code. Why GKE in 2026? With the rise of microservices and AI, cloud-native apps demand robust orchestration. This beginner tutorial guides you through creating a cluster, deploying a simple Nginx app, exposing it via a service, and scaling it. By the end, you'll master the basics for production-ready deployments. Think of Kubernetes as a conductor: GKE is the theater that handles the lights and sound.

Prerequisites

  • A free Google Cloud Platform (GCP) account with billing enabled.
  • Terminal with gcloud CLI and kubectl installed (instructions below).
  • Basic knowledge of Docker and YAML.
  • GCP region enabled (e.g., us-central1).

Install gcloud and kubectl

install-tools.sh
#!/bin/bash

# Download and install gcloud CLI (2026 edition)
curl https://sdk.cloud.google.com | bash
exec -l $SHELL

gcloud init

gcloud components install kubectl

gcloud components update

This script installs the gcloud CLI and kubectl, essential for interacting with GKE. Run it once. Pitfall: Check your PATH after installation with gcloud version to avoid 'command not found' errors.

GCP Authentication

Before creating a cluster, authenticate and set up your project. This generates an OAuth token for GCP APIs.

Authenticate and configure the project

auth-gcp.sh
#!/bin/bash

# Interactive authentication
gcloud auth login

# List available projects
gcloud projects list

# Set the project (replace PROJECT_ID with yours)
gcloud config set project my-gke-project-2026

gcloud config list

These commands connect you to GCP and select your project. Copy the project ID from the GCP console. Warning: Without billing enabled, GKE clusters will fail silently.

Create the GKE Cluster

create-cluster.sh
#!/bin/bash

# Create a standard cluster (3 nodes, e2-medium machine type)
gcloud container clusters create my-gke-cluster \
    --zone=us-central1-a \
    --num-nodes=3 \
    --machine-type=e2-medium \
    --enable-ip-alias

# Get kubectl credentials for this cluster
gcloud container clusters get-credentials my-gke-cluster --zone=us-central1-a

# Verify the connection
kubectl get nodes

This script provisions a managed cluster ready in 5-10 minutes. --enable-ip-alias enables VPC-native networking for scalability. Pitfall: Change the zone if unavailable; check with kubectl get nodes that all 3 nodes are 'Ready'.

Deploy the Application

Now, let's deploy an Nginx pod via a Kubernetes Deployment. This is the heart of orchestration: replication, rolling updates, and self-healing.

Create the Nginx Deployment

nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.27-alpine
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"

This YAML manifest creates 2 Nginx replicas with resource limits to prevent OOM kills. Copy it to a file and apply it. Analogy: Like a blueprint for identical clones of your container.

Apply the Deployment

apply-deployment.sh
#!/bin/bash

# Create the YAML file (or copy manually)
cat > nginx-deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.27-alpine
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
EOF

# Apply the Deployment
kubectl apply -f nginx-deployment.yaml

# Check the status
kubectl get deployments
kubectl get pods

Applies the YAML and verifies pods are 'Running'. Pitfall: If image pull fails, check the public registry; use kubectl describe pod for debugging.

Expose the Application

To access Nginx from outside, create a LoadBalancer Service. GKE automatically provisions an external IP.

Create the LoadBalancer Service

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

This Service routes external traffic to Nginx pods. LoadBalancer type is ideal for GKE (free for basic ingress). Tip: The IP appears after kubectl get svc.

Apply the Service and Test

apply-service.sh
#!/bin/bash

# Apply the Service
kubectl apply -f nginx-service.yaml

# Wait for the external IP (1-2 min)
kubectl get services nginx-service

# Get the IP
EXTERNAL_IP=$(kubectl get service nginx-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo "External IP: $EXTERNAL_IP"

# Test with curl (or browser)
curl http://$EXTERNAL_IP

# Alternative port-forward for local testing
kubectl port-forward service/nginx-service 8080:80

Exposes the app publicly and tests connectivity. Port-forward is great for dev without a public IP. Pitfall: GCP firewall blocks by default; allow port 80 in the console.

Scale the Application

scale-app.sh
#!/bin/bash

# Scale to 5 replicas
kubectl scale deployment nginx-deployment --replicas=5

# Watch new pods
kubectl get pods -w

# HPA autoscaling (optional, for production)
cat > hpa.yaml << EOF
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-deployment
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
EOF
kubectl apply -f hpa.yaml
kubectl get hpa

Scale manually or auto with HPA based on CPU. -w watches in real-time. GKE Advantage: Cluster autoscaling handles nodes automatically.

Best Practices

  • Use namespaces: kubectl create namespace prod to isolate environments.
  • Limit resources: Always set requests/limits to avoid noisy neighbors.
  • Enable Workload Identity: For pod security without Service Account keys.
  • Monitor with Cloud Monitoring: Built into GKE, enable via console.
  • Use vulnerability-scanned images: With Artifact Registry.

Common Errors to Avoid

  • Forgetting get-credentials: kubectl can't see the cluster.
  • GCP quota exhausted: Check limits in console before creating.
  • Pods Pending: Image not public or insufficient nodes (scale cluster).
  • LoadBalancer IP not assigned: Wait 2-5 min or use Ingress.

Next Steps

Master Helm for complex charts, Istio for service mesh, or Anthos for multi-cloud. Check out our Learni Kubernetes and GKE training courses for a certified CKA/CKAD path.