.claude/skills/cloud-k8s-deployment/SKILL.md
Deploy to cloud Kubernetes clusters - DigitalOcean DOKS primary, with multi-cloud patterns for AWS EKS and GKE. Use when deploying Phase 5 to production cloud environments. (project)
npx skillsauth add maneeshanif/todo-spec-driven cloud-k8s-deploymentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
constitution-prompt-phase-5.md| Feature | DigitalOcean DOKS | AWS EKS | Google GKE | |---------|-------------------|---------|------------| | Cost | $$ (Cheapest) | $$$$ | $$$ | | Ease | Easy | Complex | Medium | | Managed | Yes | Yes | Yes | | Free Tier | None | Some | Some | | Best For | Startups, MVP | Enterprise | ML/AI |
# macOS
brew install doctl
# Linux
cd ~ && curl -OL https://github.com/digitalocean/doctl/releases/download/v1.104.0/doctl-1.104.0-linux-amd64.tar.gz
tar xf ~/doctl-1.104.0-linux-amd64.tar.gz
sudo mv ~/doctl /usr/local/bin
# Authenticate
doctl auth init
# Create cluster
doctl kubernetes cluster create todo-production \
--region nyc1 \
--version 1.29.1-do.0 \
--node-pool "name=default;size=s-2vcpu-4gb;count=3;auto-scale=true;min-nodes=2;max-nodes=5" \
--wait
# Get kubeconfig
doctl kubernetes cluster kubeconfig save todo-production
# Verify
kubectl get nodes
Create terraform/digitalocean/main.tf:
terraform {
required_providers {
digitalocean = {
source = "digitalocean/digitalocean"
version = "~> 2.0"
}
}
}
provider "digitalocean" {
token = var.do_token
}
resource "digitalocean_kubernetes_cluster" "todo" {
name = "todo-production"
region = "nyc1"
version = "1.29.1-do.0"
node_pool {
name = "default"
size = "s-2vcpu-4gb"
auto_scale = true
min_nodes = 2
max_nodes = 5
}
maintenance_policy {
start_time = "04:00"
day = "sunday"
}
}
resource "digitalocean_container_registry" "todo" {
name = "todo-registry"
subscription_tier_slug = "basic"
}
output "cluster_id" {
value = digitalocean_kubernetes_cluster.todo.id
}
output "kubeconfig" {
value = digitalocean_kubernetes_cluster.todo.kube_config[0].raw_config
sensitive = true
}
# Install via Helm
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace \
--set controller.publishService.enabled=true
# Install cert-manager
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--set installCRDs=true
# Create ClusterIssuer for Let's Encrypt
kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
EOF
# Install Dapr
helm repo add dapr https://dapr.github.io/helm-charts/
helm repo update
helm install dapr dapr/dapr \
--namespace dapr-system \
--create-namespace \
--wait
# Install Strimzi operator
helm repo add strimzi https://strimzi.io/charts/
helm repo update
helm install strimzi-kafka-operator strimzi/strimzi-kafka-operator \
--namespace kafka \
--create-namespace
Create helm/evolution-todo/values-production.yaml:
global:
environment: production
domain: todo.yourdomain.com
image:
registry: ghcr.io
repository: your-org/evolution-todo
tag: latest
pullPolicy: Always
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
hosts:
- host: todo.yourdomain.com
paths:
- path: /
pathType: Prefix
service: frontend
- path: /api
pathType: Prefix
service: backend
tls:
- secretName: todo-tls
hosts:
- todo.yourdomain.com
backend:
replicas: 3
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 70
frontend:
replicas: 2
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
kafka:
enabled: true
external: true
brokers: "redpanda-cloud-broker:9092"
redis:
enabled: true
cluster:
enabled: false
master:
persistence:
size: 5Gi
postgresql:
enabled: false # Using Neon
external:
host: "your-neon-host.neon.tech"
database: "todo_prod"
# Create namespace
kubectl create namespace todo-app
# Create secrets
kubectl create secret generic todo-secrets \
--namespace todo-app \
--from-literal=DATABASE_URL="postgresql://user:pass@host/db" \
--from-literal=GEMINI_API_KEY="your-key" \
--from-literal=BETTER_AUTH_SECRET="your-secret"
# Deploy with Helm
helm upgrade --install evolution-todo ./helm/evolution-todo \
--namespace todo-app \
--values ./helm/evolution-todo/values-production.yaml \
--wait
# Verify deployment
kubectl get pods -n todo-app
kubectl get ingress -n todo-app
After deployment, configure DNS:
# Get Load Balancer IP
kubectl get svc -n ingress-nginx ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
# Create A record:
# todo.yourdomain.com → <LOAD_BALANCER_IP>
Production (DOKS)
├── Namespace: todo-app
├── Domain: todo.yourdomain.com
├── Database: Neon (Production)
├── Kafka: Redpanda Cloud
└── Replicas: 3-10 (autoscaled)
Staging (DOKS)
├── Namespace: todo-staging
├── Domain: staging.todo.yourdomain.com
├── Database: Neon (Staging)
├── Kafka: Strimzi (in-cluster)
└── Replicas: 1-3
Development (Minikube)
├── Namespace: todo-dev
├── Domain: localhost
├── Database: PostgreSQL (in-cluster)
├── Kafka: Strimzi (single node)
└── Replicas: 1
# Install kube-prometheus-stack
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install monitoring prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace \
--set grafana.adminPassword=admin \
--set prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues=false
# Enable cluster monitoring
doctl kubernetes cluster update todo-production \
--enable-control-plane-monitoring
| Resource | Development | Staging | Production | |----------|-------------|---------|------------| | Nodes | 1 (s-1vcpu-2gb) | 2 (s-2vcpu-4gb) | 3-5 (s-2vcpu-4gb) | | Cost/month | ~$12 | ~$48 | ~$72-120 | | Load Balancer | None | 1 ($12) | 1 ($12) | | Block Storage | 10GB | 20GB | 50GB |
| Issue | Cause | Solution | |-------|-------|----------| | Pods pending | No nodes | Check node pool autoscaling | | TLS not working | Cert not issued | Check cert-manager logs | | Ingress 502 | Backend unhealthy | Check pod health | | DNS not resolving | A record missing | Add DNS record | | High latency | Region mismatch | Deploy closer to users |
tools
Implement WebSocket service for real-time task synchronization across clients. Use when building real-time updates for Phase 5. (project)
data-ai
Implement Urdu language support with RTL layout, translations, and AI responses in Urdu. Bonus feature (+100 points) for Phase 5. (project)
development
DEPRECATED - Use chatkit-backend skill instead. SSE streaming is now part of the chatkit-backend skill for ChatKit integration.
development
Install and configure Shadcn/ui component library with Radix UI primitives, Aceternity UI effects, set up components, and manage the component registry. Use when adding Shadcn/ui to a Next.js project or installing specific UI components for Phase 2.