Kubernetes Deployment Guide¶
This guide explains how to deploy Cesivi Server to a Kubernetes cluster using raw Kubernetes manifests.
For Helm chart deployment (recommended), see HELM_CHART_GUIDE.md
Table of Contents¶
- Prerequisites
- Quick Start
- Architecture Overview
- Deployment Steps
- Configuration
- Monitoring
- Scaling
- Troubleshooting
- Production Recommendations
- Advanced Topics
Prerequisites¶
Required¶
- Kubernetes cluster (v1.24+)
- Local: minikube, kind, Docker Desktop
- Cloud: AKS, EKS, GKE
- kubectl (v1.24+) configured to access your cluster
- Container runtime supporting OCI images
- Storage provider with PersistentVolume support
Optional but Recommended¶
- nginx-ingress controller for ingress support
- cert-manager for automatic TLS certificate management
- Prometheus Operator for metrics collection
- Jaeger for distributed tracing
Verify Prerequisites¶
# Check Kubernetes version
kubectl version --short
# Check cluster access
kubectl cluster-info
# Check available storage classes
kubectl get storageclass
# Check if nginx-ingress is installed
kubectl get pods -n ingress-nginx
# Check if cert-manager is installed
kubectl get pods -n cert-manager
Quick Start¶
1. Deploy All Resources¶
# Clone repository
git clone https://github.com/your-org/cesivi.git
cd cesivi
# Deploy everything
kubectl apply -f k8s/
# Wait for deployment to complete
kubectl wait --for=condition=available --timeout=300s \
deployment/cesivi -n cesivi
2. Verify Deployment¶
# Check pod status
kubectl get pods -n cesivi
# Check all resources
kubectl get all -n cesivi
3. Access the Application¶
# Port-forward for local access
kubectl port-forward -n cesivi svc/cesivi 8080:80
# Open browser
open http://localhost:8080
# Or use ingress (if configured)
# https://cesivi.example.com
Architecture Overview¶
Deployment Architecture¶
┌─────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Ingress Controller (nginx-ingress) │ │
│ │ - TLS termination │ │
│ │ - Load balancing │ │
│ └────────────────┬─────────────────────────────────┘ │
│ │ │
│ ┌────────────────▼─────────────────────────────────┐ │
│ │ Service: cesivi (ClusterIP) │ │
│ └────────────────┬─────────────────────────────────┘ │
│ │ │
│ ┌─────────────┴──────────────┬──────────────┐ │
│ │ │ │ │
│ ┌──▼───┐ ┌────────┐ ┌────────▼┐ ┌─────────▼┐ │
│ │ SPM │ │ SPM │ │ SPM │ │ SPM │ │
│ │ Pod1 │ │ Pod2 │ │ Pod3 │ │ ... │ │
│ └──┬───┘ └────┬───┘ └────┬────┘ └─────┬────┘ │
│ │ │ │ │ │
│ └───────────┴───────────┴─────────────┘ │
│ │ │
│ ┌────────────────▼─────────────────────────────────┐ │
│ │ Redis StatefulSet │ │
│ │ - Session state │ │
│ │ - Cache │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ PostgreSQL StatefulSet │ │
│ │ - Persistent storage │ │
│ └──────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
Component Overview¶
| Component | Type | Replicas | Purpose |
|---|---|---|---|
| Cesivi Server | Deployment | 3+ | Main application |
| Redis | StatefulSet | 1 | Session state & cache |
| PostgreSQL | StatefulSet | 1 | Data persistence |
| Service | ClusterIP | 1 | Internal load balancing |
| Ingress | Ingress | 1 | External access & TLS |
| HPA | HorizontalPodAutoscaler | 1 | Auto-scaling |
| PDB | PodDisruptionBudget | 1 | High availability |
Deployment Steps¶
Step 1: Create Namespace¶
kubectl apply -f k8s/namespace.yaml
Verify:
kubectl get namespace cesivi
Step 2: Configure Secrets¶
IMPORTANT: Update passwords before deploying!
Edit k8s/secret.yaml and replace default passwords:
stringData:
REDIS_CONNECTION: "redis:6379,abortConnect=false"
SQL_CONNECTION: "Server=sqlserver;Database=Cesivi;User Id=sa;Password=YOUR_SECURE_PASSWORD;TrustServerCertificate=True"
Apply:
kubectl apply -f k8s/secret.yaml
Verify:
kubectl get secret spm-secrets -n cesivi
Alternative: Create secret via kubectl
kubectl create secret generic spm-secrets \
--from-literal=REDIS_CONNECTION="redis:6379,abortConnect=false" \
--from-literal=SQL_CONNECTION="Server=sqlserver;Database=Cesivi;User Id=sa;Password=YourStrong@Passw0rd;TrustServerCertificate=True" \
-n cesivi
Step 3: Create Configuration¶
kubectl apply -f k8s/configmap.yaml
Verify:
kubectl get configmap cesivi-config -n cesivi
kubectl describe configmap cesivi-config -n cesivi
Step 4: Deploy Redis¶
kubectl apply -f k8s/redis-deployment.yaml
kubectl apply -f k8s/redis-service.yaml
Wait for Redis to be ready:
kubectl wait --for=condition=ready pod \
-l app.kubernetes.io/name=redis \
-n cesivi \
--timeout=300s
Verify:
kubectl get pods -n cesivi -l app.kubernetes.io/name=redis
kubectl get svc -n cesivi -l app.kubernetes.io/name=redis
Step 5: Deploy SQL Server (Optional)¶
For production, use external managed database instead!
# Update secret with SQL Server SA password
kubectl create secret generic spm-secrets \
--from-literal=SQL_SA_PASSWORD="YourStrong@Passw0rd" \
--dry-run=client -o yaml | kubectl apply -f -
# Deploy SQL Server
kubectl apply -f k8s/sqlserver-deployment.yaml
Wait for SQL Server to be ready:
kubectl wait --for=condition=ready pod \
-l app.kubernetes.io/name=sqlserver \
-n cesivi \
--timeout=600s # SQL Server takes longer to start
Step 6: Deploy Cesivi Server¶
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
Wait for deployment:
kubectl wait --for=condition=available \
deployment/cesivi \
-n cesivi \
--timeout=300s
Verify:
kubectl get deployments -n cesivi
kubectl get pods -n cesivi
kubectl get svc -n cesivi
Step 7: Configure Ingress¶
Edit k8s/ingress.yaml to set your hostname:
spec:
tls:
- hosts:
- your-domain.com # Change this
secretName: cesivi-tls
rules:
- host: your-domain.com # Change this
Apply:
kubectl apply -f k8s/ingress.yaml
Verify:
kubectl get ingress -n cesivi
kubectl describe ingress cesivi -n cesivi
Step 8: Enable Auto-Scaling¶
kubectl apply -f k8s/hpa.yaml
kubectl apply -f k8s/pdb.yaml
Verify:
kubectl get hpa -n cesivi
kubectl get pdb -n cesivi
Configuration¶
Application Configuration¶
Configuration is managed via ConfigMap (k8s/configmap.yaml).
Key Settings¶
{
"Cesivi": {
"BaseUrl": "http://cesivi:5000",
"EnableSwagger": false,
"EnableHealthChecks": true,
"EnableMetrics": true,
"EnableTracing": true
},
"Storage": {
"Provider": "SqlServer", // or PostgreSQL
"EnableCaching": true,
"CacheExpiry": "00:05:00"
},
"DistributedState": {
"Provider": "Redis",
"KeyPrefix": "spm:",
"SessionExpiry": "08:00:00"
}
}
Update Configuration¶
- Edit
k8s/configmap.yaml - Apply changes:
kubectl apply -f k8s/configmap.yaml - Restart pods to pick up changes:
kubectl rollout restart deployment/cesivi -n cesivi
Secrets Management¶
Update Secrets¶
# Update Redis connection
kubectl create secret generic spm-secrets \
--from-literal=REDIS_CONNECTION="redis:6379,password=newpassword" \
--dry-run=client -o yaml | kubectl apply -n cesivi -f -
# Restart deployment
kubectl rollout restart deployment/cesivi -n cesivi
Best Practices¶
For production, use proper secret management: - Azure: Azure Key Vault with CSI driver - AWS: AWS Secrets Manager with external-secrets operator - GCP: Google Secret Manager - Universal: HashiCorp Vault, Sealed Secrets
Resource Limits¶
Edit k8s/deployment.yaml to adjust resources:
resources:
requests:
cpu: 500m # Increase for production
memory: 1Gi # Increase for production
limits:
cpu: 2000m
memory: 4Gi
Apply:
kubectl apply -f k8s/deployment.yaml
Ingress Configuration¶
Change Hostname¶
Edit k8s/ingress.yaml:
spec:
rules:
- host: sharepoint.your-company.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: cesivi
port:
number: 80
Enable TLS with Let's Encrypt¶
Ensure cert-manager is installed, then update k8s/ingress.yaml:
metadata:
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- sharepoint.your-company.com
secretName: cesivi-tls
cert-manager will automatically provision a TLS certificate.
Custom TLS Certificate¶
# Create TLS secret
kubectl create secret tls cesivi-tls \
--cert=path/to/tls.crt \
--key=path/to/tls.key \
-n cesivi
Monitoring¶
Health Checks¶
# Port-forward
kubectl port-forward -n cesivi svc/cesivi 8080:80
# Check health endpoints
curl http://localhost:8080/health # Overall health
curl http://localhost:8080/health/ready # Readiness
curl http://localhost:8080/health/live # Liveness
Prometheus Metrics¶
# Access metrics endpoint
curl http://localhost:8080/metrics
ServiceMonitor (for Prometheus Operator)¶
Create servicemonitor.yaml:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: cesivi
namespace: cesivi
spec:
selector:
matchLabels:
app.kubernetes.io/name: cesivi
endpoints:
- port: metrics
path: /metrics
interval: 30s
Apply:
kubectl apply -f servicemonitor.yaml
Logs¶
# All pods
kubectl logs -n cesivi -l app.kubernetes.io/name=cesivi --tail=100 -f
# Specific pod
kubectl logs -n cesivi <pod-name> -f
# Previous container (if crashed)
kubectl logs -n cesivi <pod-name> --previous
Events¶
# Recent events
kubectl get events -n cesivi --sort-by='.lastTimestamp'
# Watch events
kubectl get events -n cesivi --watch
Scaling¶
Manual Scaling¶
# Scale to 5 replicas
kubectl scale deployment cesivi --replicas=5 -n cesivi
# Verify
kubectl get pods -n cesivi
Auto-Scaling (HPA)¶
HPA is configured in k8s/hpa.yaml:
spec:
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Monitor HPA:
# Watch HPA status
kubectl get hpa -n cesivi --watch
# Describe HPA
kubectl describe hpa cesivi -n cesivi
Adjust Auto-Scaling¶
Edit k8s/hpa.yaml:
spec:
minReplicas: 5 # Minimum pods
maxReplicas: 20 # Maximum pods
targetCPUUtilizationPercentage: 60 # Scale when CPU > 60%
Apply:
kubectl apply -f k8s/hpa.yaml
Troubleshooting¶
Pods Not Starting¶
Symptom: Pods in Pending, CrashLoopBackOff, or ImagePullBackOff state.
Diagnosis:
kubectl describe pod <pod-name> -n cesivi
kubectl logs <pod-name> -n cesivi
Common Issues:
- Image Pull Error:
- Check image name in
deployment.yaml - Verify image exists and is accessible
-
Check imagePullSecrets if using private registry
-
Insufficient Resources:
- Check node resources:
kubectl describe nodes -
Reduce resource requests or add more nodes
-
Failed Health Checks:
- Check health check endpoints:
/health/ready,/health/live - Increase
initialDelaySecondsin probes
Database Connection Issues¶
Symptom: Pods running but app errors about database connection.
Diagnosis:
# Check if database pod is running
kubectl get pods -n cesivi | grep -E '(postgres|sqlserver)'
# Test connection from SPM pod
kubectl exec -it <spm-pod-name> -n cesivi -- /bin/sh
# Inside pod:
nc -zv sqlserver 1433
# or
nc -zv postgresql 5432
Solutions:
- Database not ready:
-
Wait for database pod:
kubectl wait --for=condition=ready pod ... -
Wrong connection string:
- Check secret:
kubectl get secret spm-secrets -n cesivi -o yaml -
Verify hostname, port, credentials
-
Network policy blocking:
- Check network policies:
kubectl get networkpolicies -n cesivi
Redis Connection Issues¶
Symptom: Session state not working across pods.
Diagnosis:
# Check Redis pod
kubectl get pods -n cesivi -l app.kubernetes.io/name=redis
# Test connection
kubectl exec -it <spm-pod-name> -n cesivi -- /bin/sh
nc -zv redis 6379
# Check Redis logs
kubectl logs -n cesivi -l app.kubernetes.io/name=redis
Ingress Not Working¶
Symptom: Cannot access app via ingress hostname.
Diagnosis:
# Check ingress status
kubectl get ingress -n cesivi
kubectl describe ingress cesivi -n cesivi
# Check ingress controller
kubectl get pods -n ingress-nginx
kubectl logs -n ingress-nginx <controller-pod>
Solutions:
- DNS not configured:
- Add DNS A record pointing to ingress external IP
-
Or add to
/etc/hostsfor testing -
TLS certificate issues:
- Check cert-manager logs
- Verify certificate:
kubectl get certificate -n cesivi - Check certificate status:
kubectl describe certificate cesivi-tls -n cesivi
Performance Issues¶
Symptom: Slow response times, high CPU/memory usage.
Diagnosis:
# Check resource usage
kubectl top pods -n cesivi
kubectl top nodes
# Check HPA status
kubectl get hpa -n cesivi
# Check metrics
kubectl port-forward -n cesivi svc/cesivi 8080:80
curl http://localhost:8080/metrics | grep -E '(request_duration|memory|cpu)'
Solutions:
- Increase resources:
- Edit
deployment.yamlresource limits -
Add more replicas
-
Enable caching:
- Verify Redis is working
-
Check cache hit ratio in metrics
-
Database slow:
- Check database resource usage
- Add indexes, optimize queries
Production Recommendations¶
1. Use External Managed Services¶
DO NOT use in-cluster databases for production!
Use managed services instead:
- Azure:
- Azure Database for PostgreSQL
- Azure Cache for Redis
-
Azure SQL Database
-
AWS:
- RDS for PostgreSQL
- ElastiCache for Redis
-
RDS for SQL Server
-
GCP:
- Cloud SQL for PostgreSQL
- Memorystore for Redis
- Cloud SQL for SQL Server
Update k8s/secret.yaml with external connection strings.
2. Persistent Storage¶
Use high-performance storage classes:
# In PVC or StatefulSet
storageClassName: "premium-ssd" # Azure
# or
storageClassName: "gp3" # AWS
# or
storageClassName: "pd-ssd" # GCP
3. High Availability¶
# Increase replicas
replicas: 5
# Update HPA
minReplicas: 3
maxReplicas: 20
# Update PDB
minAvailable: 3
4. Resource Limits¶
resources:
requests:
cpu: 1000m
memory: 2Gi
limits:
cpu: 4000m
memory: 8Gi
5. Pod Anti-Affinity¶
Add to deployment.yaml:
spec:
template:
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- cesivi
topologyKey: kubernetes.io/hostname
This ensures pods run on different nodes for HA.
6. Network Policies¶
Restrict network traffic:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: cesivi-network-policy
namespace: cesivi
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: cesivi
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 5000
egress:
- to:
- podSelector:
matchLabels:
app.kubernetes.io/name: redis
ports:
- protocol: TCP
port: 6379
- to:
- podSelector:
matchLabels:
app.kubernetes.io/name: postgresql
ports:
- protocol: TCP
port: 5432
7. Monitoring & Alerting¶
- Enable Prometheus ServiceMonitor
- Configure alerts for:
- Pod restarts
- High CPU/memory usage
- Failed health checks
- Slow response times
8. Backup & Disaster Recovery¶
# Backup database (PostgreSQL example)
kubectl exec -n cesivi postgresql-0 -- \
pg_dump -U sharepoint_mock Cesivi > backup.sql
# Backup Redis (if needed)
kubectl exec -n cesivi redis-0 -- \
redis-cli BGSAVE
# Backup entire namespace (using Velero)
velero backup create cesivi-backup \
--include-namespaces cesivi
Advanced Topics¶
Multi-Tenant Deployment¶
Deploy multiple isolated instances:
# Tenant 1
kubectl create namespace cesivi-tenant1
kubectl apply -f k8s/ -n cesivi-tenant1
# Tenant 2
kubectl create namespace cesivi-tenant2
kubectl apply -f k8s/ -n cesivi-tenant2
Use different ingress hostnames for each tenant.
GitOps with ArgoCD¶
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: cesivi
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/cesivi
targetRevision: main
path: k8s
destination:
server: https://kubernetes.default.svc
namespace: cesivi
syncPolicy:
automated:
prune: true
selfHeal: true
Service Mesh (Istio)¶
Add Istio sidecar injection:
metadata:
labels:
istio-injection: enabled
Configure VirtualService and DestinationRule for advanced traffic management.
Blue/Green Deployment¶
# Deploy green version
kubectl apply -f k8s-green/
# Test green version
kubectl port-forward -n cesivi-green svc/cesivi 9090:80
# Switch traffic (update ingress)
kubectl patch ingress cesivi -n cesivi \
--type=json -p='[{"op": "replace", "path": "/spec/rules/0/http/paths/0/backend/service/name", "value":"cesivi-green"}]'
# Cleanup blue version
kubectl delete -f k8s/
Canary Deployment¶
Use Flagger or Argo Rollouts for automated canary deployments.
Next Steps¶
- Helm Deployment: See HELM_CHART_GUIDE.md for easier deployment
- API Reference: See API_REFERENCE.md
- Observability: See OBSERVABILITY_GUIDE.md