GCP for DevOps — GKE Workloads

2 minute read

GKE Workloads

This page covers deploying production workloads on GKE — Deployments, Services, Ingress, ConfigMaps, Secrets, and health checks.

Deployment with Health Checks

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
  labels:
    app: api-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api-server
  template:
    metadata:
      labels:
        app: api-server
    spec:
      serviceAccountName: app-ksa
      containers:
        - name: api
          image: us-central1-docker.pkg.dev/my-project/my-repo/api:v1.0.0
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: "250m"
              memory: "256Mi"
            limits:
              cpu: "500m"
              memory: "512Mi"
          readinessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 15
            periodSeconds: 20
          startupProbe:
            httpGet:
              path: /healthz
              port: 8080
            failureThreshold: 30
            periodSeconds: 10

Services

# ClusterIP (internal only)
apiVersion: v1
kind: Service
metadata:
  name: api-server
spec:
  type: ClusterIP
  selector:
    app: api-server
  ports:
    - port: 80
      targetPort: 8080
---
# LoadBalancer (external)
apiVersion: v1
kind: Service
metadata:
  name: api-server-external
spec:
  type: LoadBalancer
  selector:
    app: api-server
  ports:
    - port: 443
      targetPort: 8080
---
# NodePort
apiVersion: v1
kind: Service
metadata:
  name: api-server-nodeport
spec:
  type: NodePort
  selector:
    app: api-server
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 30080

GKE Ingress (HTTP/S Load Balancer)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress
  annotations:
    kubernetes.io/ingress.class: "gce"
    kubernetes.io/ingress.global-static-ip-name: "api-ip"
    networking.gke.io/managed-certificates: "api-cert"
spec:
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-server
                port:
                  number: 80
---
# Managed SSL Certificate
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: api-cert
spec:
  domains:
    - api.example.com
# Reserve a static IP for the Ingress
$ gcloud compute addresses create api-ip --global

# Get the IP
$ gcloud compute addresses describe api-ip --global \
    --format="value(address)"

ConfigMaps

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  DATABASE_HOST: "10.0.1.5"
  DATABASE_PORT: "5432"
  LOG_LEVEL: "info"
  config.yaml: |
    server:
      port: 8080
      timeout: 30s
    features:
      cache: true
# Use ConfigMap in a Deployment
containers:
  - name: api
    image: my-api:v1.0.0
    envFrom:
      - configMapRef:
          name: app-config
    volumeMounts:
      - name: config-volume
        mountPath: /etc/config
volumes:
  - name: config-volume
    configMap:
      name: app-config
      items:
        - key: config.yaml
          path: config.yaml

Kubernetes Secrets

# Create a secret from literal values
$ kubectl create secret generic db-credentials \
    --from-literal=username=admin \
    --from-literal=password=s3cur3p@ss

# Create from file
$ kubectl create secret generic tls-secret \
    --from-file=tls.crt=server.crt \
    --from-file=tls.key=server.key
# Use secrets in a Deployment
containers:
  - name: api
    image: my-api:v1.0.0
    env:
      - name: DB_USER
        valueFrom:
          secretKeyRef:
            name: db-credentials
            key: username
      - name: DB_PASS
        valueFrom:
          secretKeyRef:
            name: db-credentials
            key: password

Network Policies

Restrict pod-to-pod communication.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-allow-frontend
spec:
  podSelector:
    matchLabels:
      app: api-server
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8080

Pod Disruption Budgets

Ensure availability during voluntary disruptions (node upgrades, scaling).

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: api-server

Common Mistakes

Mistake Why It’s Wrong Fix
No readiness probe Traffic sent to unready pods Always configure readiness probes
No resource requests/limits OOM kills, noisy neighbors Set appropriate resources
Secrets in ConfigMaps Not encrypted Use K8s Secrets or Secret Manager
No PodDisruptionBudget All pods evicted during upgrade Set PDB with minAvailable
Single replica in production No availability if pod crashes Use at least 3 replicas with PDB

Quick Reference

Resource Purpose
Deployment Manage replica sets, rolling updates
Service (ClusterIP) Internal load balancing
Service (LoadBalancer) External L4 load balancer
Ingress External L7 HTTP/S load balancer
ConfigMap Non-sensitive configuration
Secret Sensitive data (base64 encoded)
NetworkPolicy Pod-to-pod firewall rules
PodDisruptionBudget Availability during disruptions

Next → Container CI/CD

Updated: