Deploy to Kubernetes
Kubernetes (K8s) provides powerful orchestration for containerized Bunty applications, offering features like auto-scaling, rolling updates, and self-healing.
Prerequisites
- Docker image of your Bunty application
- Kubernetes cluster (local or cloud)
kubectlCLI installed
Quick Start
Basic Deployment
Create k8s/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: bunty-app
labels:
app: bunty-app
spec:
replicas: 3
selector:
matchLabels:
app: bunty-app
template:
metadata:
labels:
app: bunty-app
spec:
containers:
- name: bunty-app
image: your-registry/bunty-app:latest
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: "production"
- name: PORT
value: "3000"
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
Service
Create k8s/service.yaml:
apiVersion: v1
kind: Service
metadata:
name: bunty-app-service
spec:
selector:
app: bunty-app
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 3000
Deploy
# Apply configurations
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
# Check status
kubectl get deployments
kubectl get pods
kubectl get services
Complete Production Setup
1. Namespace
# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: bunty-production
2. ConfigMap
# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: bunty-config
namespace: bunty-production
data:
NODE_ENV: "production"
LOG_LEVEL: "info"
PORT: "3000"
3. Secrets
# k8s/secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: bunty-secrets
namespace: bunty-production
type: Opaque
data:
database-url: <base64-encoded-value>
redis-url: <base64-encoded-value>
jwt-secret: <base64-encoded-value>
Create secrets:
# Create from literal
kubectl create secret generic bunty-secrets \
--from-literal=database-url='postgresql://user:pass@host:5432/db' \
--from-literal=jwt-secret='your-secret-key' \
-n bunty-production
# Or from file
kubectl create secret generic bunty-secrets \
--from-env-file=.env.production \
-n bunty-production
4. Deployment with All Features
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: bunty-app
namespace: bunty-production
labels:
app: bunty-app
version: v1
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: bunty-app
template:
metadata:
labels:
app: bunty-app
version: v1
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "3000"
prometheus.io/path: "/metrics"
spec:
serviceAccountName: bunty-app
containers:
- name: bunty-app
image: your-registry/bunty-app:1.0.0
imagePullPolicy: Always
ports:
- name: http
containerPort: 3000
protocol: TCP
env:
- name: NODE_ENV
valueFrom:
configMapKeyRef:
name: bunty-config
key: NODE_ENV
- name: PORT
valueFrom:
configMapKeyRef:
name: bunty-config
key: PORT
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: bunty-secrets
key: database-url
- name: REDIS_URL
valueFrom:
secretKeyRef:
name: bunty-secrets
key: redis-url
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: bunty-secrets
key: jwt-secret
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 30
volumeMounts:
- name: config
mountPath: /app/config
readOnly: true
volumes:
- name: config
configMap:
name: bunty-config
imagePullSecrets:
- name: registry-secret
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- bunty-app
topologyKey: kubernetes.io/hostname
5. Horizontal Pod Autoscaler
# k8s/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: bunty-app-hpa
namespace: bunty-production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: bunty-app
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 15
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 15
- type: Pods
value: 2
periodSeconds: 15
selectPolicy: Max
6. Ingress
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: bunty-app-ingress
namespace: bunty-production
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rate-limit: "100"
spec:
tls:
- hosts:
- api.example.com
secretName: bunty-tls
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: bunty-app-service
port:
number: 80
7. Service with Multiple Ports
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
name: bunty-app-service
namespace: bunty-production
labels:
app: bunty-app
spec:
type: ClusterIP
selector:
app: bunty-app
ports:
- name: http
protocol: TCP
port: 80
targetPort: 3000
- name: metrics
protocol: TCP
port: 9090
targetPort: 3000
sessionAffinity: ClientIP
Database and Redis
PostgreSQL StatefulSet
# k8s/postgres.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: bunty-production
spec:
serviceName: postgres
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16-alpine
ports:
- containerPort: 5432
env:
- name: POSTGRES_DB
value: bunty
- name: POSTGRES_USER
value: bunty
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: bunty-secrets
key: postgres-password
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: postgres-storage
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: bunty-production
spec:
selector:
app: postgres
ports:
- port: 5432
clusterIP: None
Redis Deployment
# k8s/redis.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: bunty-production
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: bunty-production
spec:
selector:
app: redis
ports:
- port: 6379
Apply All Configurations
# Create namespace
kubectl apply -f k8s/namespace.yaml
# Create secrets and config
kubectl apply -f k8s/secret.yaml
kubectl apply -f k8s/configmap.yaml
# Deploy database and cache
kubectl apply -f k8s/postgres.yaml
kubectl apply -f k8s/redis.yaml
# Deploy application
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
kubectl apply -f k8s/hpa.yaml
kubectl apply -f k8s/ingress.yaml
# Or apply all at once
kubectl apply -f k8s/
Helm Chart
Create Helm Chart
helm create bunty-app
values.yaml
replicaCount: 3
image:
repository: your-registry/bunty-app
pullPolicy: IfNotPresent
tag: "1.0.0"
service:
type: ClusterIP
port: 80
targetPort: 3000
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: api.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: bunty-tls
hosts:
- api.example.com
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 70
targetMemoryUtilizationPercentage: 80
env:
- name: NODE_ENV
value: "production"
- name: PORT
value: "3000"
secrets:
- name: DATABASE_URL
value: "postgresql://user:pass@postgres:5432/bunty"
- name: REDIS_URL
value: "redis://redis:6379"
Install with Helm
# Install
helm install bunty-app ./bunty-app -n bunty-production
# Upgrade
helm upgrade bunty-app ./bunty-app -n bunty-production
# Rollback
helm rollback bunty-app -n bunty-production
Common Operations
Rolling Update
# Update image
kubectl set image deployment/bunty-app bunty-app=your-registry/bunty-app:2.0.0 -n bunty-production
# Check rollout status
kubectl rollout status deployment/bunty-app -n bunty-production
# Rollback
kubectl rollout undo deployment/bunty-app -n bunty-production
Scaling
# Manual scale
kubectl scale deployment bunty-app --replicas=5 -n bunty-production
# Check HPA status
kubectl get hpa -n bunty-production
Debugging
# View logs
kubectl logs -f deployment/bunty-app -n bunty-production
# Exec into pod
kubectl exec -it bunty-app-xxx -n bunty-production -- /bin/sh
# Port forward
kubectl port-forward deployment/bunty-app 3000:3000 -n bunty-production
# Describe pod
kubectl describe pod bunty-app-xxx -n bunty-production
Next Steps
- Set up CI/CD pipelines
- Configure monitoring with Prometheus
- Set up log aggregation
- Deploy to cloud EKS, GKE, or AKS