Skip to main content

Kubernetes Deployment Guide for GKE

Overview

Production-ready Kubernetes manifests for deploying CODITECT Dev Context v2.0 to Google Kubernetes Engine (GKE).

Architecture:

  • Django REST API backend with gunicorn
  • PostgreSQL 15 (Cloud SQL with Cloud SQL Proxy sidecar)
  • Redis for caching and Celery broker
  • HTTPS with Google-managed SSL certificates
  • Horizontal auto-scaling (3-20 pods)
  • Multi-tenant support with row-level security

Prerequisites

Required Tools

  • gcloud CLI (v450.0.0+)
  • kubectl (v1.28+)
  • Docker (for building images)
  • GCP project with billing enabled

Required GCP APIs

Enable these APIs in your GCP project:

gcloud services enable \
container.googleapis.com \
sqladmin.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
secretmanager.googleapis.com \
storage-api.googleapis.com

Quick Start (15 minutes)

1. Set Environment Variables

export PROJECT_ID="your-gcp-project-id"
export REGION="us-central1"
export CLUSTER_NAME="coditect-gke-cluster"
export DB_INSTANCE="coditect-postgres"

2. Create GKE Cluster

gcloud container clusters create $CLUSTER_NAME \
--project=$PROJECT_ID \
--region=$REGION \
--num-nodes=3 \
--machine-type=n1-standard-2 \
--enable-autoscaling \
--min-nodes=3 \
--max-nodes=10 \
--enable-autorepair \
--enable-autoupgrade \
--enable-stackdriver-kubernetes \
--workload-pool=$PROJECT_ID.svc.id.goog \
--addons=HttpLoadBalancing,HorizontalPodAutoscaling

3. Configure kubectl

gcloud container clusters get-credentials $CLUSTER_NAME \
--region=$REGION \
--project=$PROJECT_ID

4. Create Cloud SQL Instance

gcloud sql instances create $DB_INSTANCE \
--project=$PROJECT_ID \
--database-version=POSTGRES_15 \
--tier=db-f1-micro \
--region=$REGION \
--root-password=$(openssl rand -base64 32)

5. Build and Push Docker Image

# Build production image
docker build -f dockerfile.production \
-t gcr.io/$PROJECT_ID/coditect-backend:2.0.0 .

# Push to Google Container Registry
docker push gcr.io/$PROJECT_ID/coditect-backend:2.0.0

6. Update Manifests

Edit these files and replace placeholders:

  1. 04-deployment.yaml:

    • PROJECT_ID → Your GCP project ID
    • REGION → Your Cloud SQL region
    • INSTANCE_NAME → Your Cloud SQL instance name
  2. 06-ingress.yaml:

    • Reserve static IP first (see below)

7. Create Secrets in Google Secret Manager

# Django secret key
python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())' | \
gcloud secrets create django-secret-key --data-file=-

# Database password
gcloud sql users set-password postgres \
--instance=$DB_INSTANCE \
--password=$(openssl rand -base64 32)

# Store DB password in Secret Manager
gcloud sql users describe postgres --instance=$DB_INSTANCE | \
grep password | awk '{print $2}' | \
gcloud secrets create db-password --data-file=-

8. Reserve Static IP

gcloud compute addresses create coditect-backend-ip --global
gcloud compute addresses describe coditect-backend-ip --global

9. Deploy to GKE

kubectl apply -f k8s/01-namespace.yaml
kubectl apply -f k8s/02-configmap.yaml
kubectl apply -f k8s/03-secrets.yaml
kubectl apply -f k8s/04-deployment.yaml
kubectl apply -f k8s/05-service.yaml
kubectl apply -f k8s/06-ingress.yaml
kubectl apply -f k8s/07-hpa.yaml

10. Run Database Migrations

# Get a pod name
POD=$(kubectl get pods -n coditect-dev-context -l app=coditect-backend -o jsonpath='{.items[0].metadata.name}')

# Run migrations
kubectl exec -it $POD -n coditect-dev-context -- python manage.py migrate

# Create superuser
kubectl exec -it $POD -n coditect-dev-context -- python manage.py createsuperuser

11. Configure DNS

Point your domain to the static IP:

# Get IP address
gcloud compute addresses describe coditect-backend-ip --global --format="value(address)"

# In your DNS provider, create:
# A Record: api.coditect.ai → <STATIC_IP>
# A Record: *.coditect.ai → <STATIC_IP>

12. Wait for SSL Certificate

# Check certificate status
kubectl describe managedcertificate coditect-ssl-cert -n coditect-dev-context

# This can take 5-20 minutes

13. Verify Deployment

# Check pods
kubectl get pods -n coditect-dev-context

# Check service
kubectl get svc -n coditect-dev-context

# Check ingress
kubectl get ingress -n coditect-dev-context

# Test API
curl https://api.coditect.ai/health/

Manifest Files

FileDescription
01-namespace.yamlIsolated namespace for all resources
02-configmap.yamlNon-sensitive configuration
03-secrets.yamlSensitive credentials (use Secret Manager)
04-deployment.yamlMain application deployment with Cloud SQL Proxy
05-service.yamlInternal load balancer
06-ingress.yamlExternal HTTPS access with SSL
07-hpa.yamlHorizontal pod autoscaler

Monitoring & Operations

View Logs

# All pods
kubectl logs -f -n coditect-dev-context -l app=coditect-backend

# Specific pod
kubectl logs -f POD_NAME -n coditect-dev-context

# Cloud SQL Proxy logs
kubectl logs POD_NAME -n coditect-dev-context -c cloud-sql-proxy

Shell Access

kubectl exec -it POD_NAME -n coditect-dev-context -- /bin/bash

Database Access

# Via Cloud SQL Proxy in pod
kubectl exec -it POD_NAME -n coditect-dev-context -- \
psql -h 127.0.0.1 -U postgres -d coditect_dev_context

Scale Manually

# Scale to 5 replicas
kubectl scale deployment coditect-backend \
-n coditect-dev-context \
--replicas=5

Update Deployment

# Build new image
docker build -f dockerfile.production -t gcr.io/$PROJECT_ID/coditect-backend:2.0.1 .
docker push gcr.io/$PROJECT_ID/coditect-backend:2.0.1

# Update deployment
kubectl set image deployment/coditect-backend \
backend=gcr.io/$PROJECT_ID/coditect-backend:2.0.1 \
-n coditect-dev-context

# Watch rollout
kubectl rollout status deployment/coditect-backend -n coditect-dev-context

Rollback Deployment

# View rollout history
kubectl rollout history deployment/coditect-backend -n coditect-dev-context

# Rollback to previous version
kubectl rollout undo deployment/coditect-backend -n coditect-dev-context

# Rollback to specific revision
kubectl rollout undo deployment/coditect-backend \
-n coditect-dev-context \
--to-revision=2

Security Best Practices

1. Use Workload Identity

Enable Workload Identity for secure GCP service account access:

# Create GCP service account
gcloud iam service-accounts create coditect-backend \
--display-name="CODITECT Backend Service Account"

# Bind to Kubernetes service account
gcloud iam service-accounts add-iam-policy-binding \
coditect-backend@$PROJECT_ID.iam.gserviceaccount.com \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:$PROJECT_ID.svc.id.goog[coditect-dev-context/coditect-backend-sa]"

# Grant necessary permissions
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:coditect-backend@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/cloudsql.client"

gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:coditect-backend@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"

gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:coditect-backend@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/storage.admin"

2. Enable Cloud Armor

DDoS protection and rate limiting:

gcloud compute security-policies create coditect-armor-policy \
--description="DDoS protection for CODITECT"

# Rate limiting rule
gcloud compute security-policies rules create 1000 \
--security-policy=coditect-armor-policy \
--expression="true" \
--action="rate-based-ban" \
--rate-limit-threshold-count=100 \
--rate-limit-threshold-interval-sec=60 \
--ban-duration-sec=600

3. Network Policies

Restrict pod-to-pod communication (optional):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: coditect-backend-netpol
namespace: coditect-dev-context
spec:
podSelector:
matchLabels:
app: coditect-backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 8000

Cost Optimization

Right-Size Resources

Monitor actual usage and adjust:

# View resource usage
kubectl top pods -n coditect-dev-context
kubectl top nodes

# Update resource requests/limits in 04-deployment.yaml

Use Preemptible Nodes

For non-critical workloads:

gcloud container node-pools create preemptible-pool \
--cluster=$CLUSTER_NAME \
--region=$REGION \
--preemptible \
--num-nodes=2 \
--machine-type=n1-standard-2

Cleanup Unused Resources

# Delete unused images
gcloud container images list --repository=gcr.io/$PROJECT_ID
gcloud container images delete gcr.io/$PROJECT_ID/coditect-backend:old-tag

Troubleshooting

Pods Not Starting

# Check pod events
kubectl describe pod POD_NAME -n coditect-dev-context

# Common issues:
# - Image pull errors → Check GCR permissions
# - CrashLoopBackOff → Check logs
# - Pending state → Insufficient cluster resources

Database Connection Failures

# Check Cloud SQL Proxy logs
kubectl logs POD_NAME -n coditect-dev-context -c cloud-sql-proxy

# Verify Cloud SQL instance is running
gcloud sql instances describe $DB_INSTANCE

# Check firewall rules
gcloud compute firewall-rules list

SSL Certificate Not Provisioning

# Check certificate status
kubectl describe managedcertificate coditect-ssl-cert -n coditect-dev-context

# Verify DNS is pointing to static IP
dig api.coditect.ai

# Certificate provisioning can take up to 20 minutes

Production Readiness Checklist

  • GKE cluster created with autoscaling
  • Cloud SQL instance provisioned
  • Static IP reserved and DNS configured
  • Secrets stored in Google Secret Manager
  • Workload Identity configured
  • Docker image built and pushed
  • All manifests applied
  • Database migrations run
  • SSL certificate provisioned
  • API health check passing
  • Monitoring and logging configured
  • Backup strategy implemented
  • Disaster recovery plan documented
  • Load testing completed
  • Security scan passed

Version: 2.0.0 Last Updated: 2025-11-26 Maintainer: AZ1.AI Development Team