From 9bc95df59154d90d0c58b59db39bcbce00fe9adb Mon Sep 17 00:00:00 2001 From: senke Date: Thu, 25 Dec 2025 21:37:06 +0100 Subject: [PATCH] [INFRA-008] infra: Set up environment management --- VEZA_COMPLETE_MVP_TODOLIST.json | 27 +- k8s/environments/README.md | 295 ++++++++++++++++++ k8s/environments/development/configmap.yaml | 16 + .../development/deployment-overrides.yaml | 54 ++++ k8s/environments/ingress-dev.yaml | 32 ++ k8s/environments/ingress-staging.yaml | 38 +++ k8s/environments/namespaces.yaml | 32 ++ k8s/environments/production/configmap.yaml | 22 ++ .../production/deployment-overrides.yaml | 52 +++ k8s/environments/staging/configmap.yaml | 20 ++ .../staging/deployment-overrides.yaml | 52 +++ 11 files changed, 637 insertions(+), 3 deletions(-) create mode 100644 k8s/environments/README.md create mode 100644 k8s/environments/development/configmap.yaml create mode 100644 k8s/environments/development/deployment-overrides.yaml create mode 100644 k8s/environments/ingress-dev.yaml create mode 100644 k8s/environments/ingress-staging.yaml create mode 100644 k8s/environments/namespaces.yaml create mode 100644 k8s/environments/production/configmap.yaml create mode 100644 k8s/environments/production/deployment-overrides.yaml create mode 100644 k8s/environments/staging/configmap.yaml create mode 100644 k8s/environments/staging/deployment-overrides.yaml diff --git a/VEZA_COMPLETE_MVP_TODOLIST.json b/VEZA_COMPLETE_MVP_TODOLIST.json index a1c34790b..5342498ae 100644 --- a/VEZA_COMPLETE_MVP_TODOLIST.json +++ b/VEZA_COMPLETE_MVP_TODOLIST.json @@ -11482,8 +11482,19 @@ "description": "Configure separate dev, staging, and production environments", "owner": "devops", "estimated_hours": 4, - "status": "todo", - "files_involved": [], + "status": "completed", + "files_involved": [ + "k8s/environments/namespaces.yaml", + "k8s/environments/development/configmap.yaml", + "k8s/environments/development/deployment-overrides.yaml", + "k8s/environments/staging/configmap.yaml", + "k8s/environments/staging/deployment-overrides.yaml", + "k8s/environments/production/configmap.yaml", + "k8s/environments/production/deployment-overrides.yaml", + "k8s/environments/ingress-dev.yaml", + "k8s/environments/ingress-staging.yaml", + "k8s/environments/README.md" + ], "implementation_steps": [ { "step": 1, @@ -11503,7 +11514,17 @@ "Unit tests", "Integration tests" ], - "notes": "" + "notes": "", + "completed_at": "2025-12-25T21:36:58.166183", + "validation": { + "yaml_syntax": "All manifests validated", + "environments": "Development, Staging, and Production environments configured", + "namespaces": "Separate namespaces for each environment with labels", + "configmaps": "Environment-specific ConfigMaps with different settings", + "deployment_overrides": "Environment-specific replica counts and resource limits", + "ingress": "Separate ingress configurations for dev (no SSL), staging (staging SSL), and production (production SSL)", + "documentation": "k8s/environments/README.md with deployment, promotion, and troubleshooting instructions" + } }, { "id": "INFRA-009", diff --git a/k8s/environments/README.md b/k8s/environments/README.md new file mode 100644 index 000000000..8d5cfaef3 --- /dev/null +++ b/k8s/environments/README.md @@ -0,0 +1,295 @@ +# Environment Management + +This directory contains Kubernetes configurations for managing separate development, staging, and production environments. + +## Overview + +The Veza platform uses three distinct environments: + +- **Development**: Local development and testing +- **Staging**: Pre-production testing and validation +- **Production**: Live production environment + +## Structure + +``` +k8s/environments/ +├── namespaces.yaml # Namespace definitions for all environments +├── development/ +│ ├── configmap.yaml # Development-specific configuration +│ └── deployment-overrides.yaml # Development deployment overrides +├── staging/ +│ ├── configmap.yaml # Staging-specific configuration +│ └── deployment-overrides.yaml # Staging deployment overrides +├── production/ +│ ├── configmap.yaml # Production-specific configuration +│ └── deployment-overrides.yaml # Production deployment overrides +├── ingress-dev.yaml # Development ingress (no SSL) +├── ingress-staging.yaml # Staging ingress (staging SSL) +└── README.md # This file +``` + +## Environment Differences + +### Development +- **Replicas**: 1 per service +- **Resources**: Minimal (for local development) +- **Logging**: DEBUG level +- **SSL**: Disabled +- **Rate Limiting**: Disabled +- **Profiling**: Enabled +- **CORS**: Localhost origins allowed + +### Staging +- **Replicas**: 2 per service +- **Resources**: Medium +- **Logging**: INFO level +- **SSL**: Let's Encrypt staging certificates +- **Rate Limiting**: Enabled (200 req/min) +- **Profiling**: Disabled +- **CORS**: Staging domains only +- **CDN**: Enabled (staging CDN) + +### Production +- **Replicas**: 3+ per service +- **Resources**: High (with autoscaling) +- **Logging**: WARN level +- **SSL**: Let's Encrypt production certificates +- **Rate Limiting**: Enabled (100 req/min) +- **Profiling**: Disabled +- **CORS**: Production domains only +- **CDN**: Enabled (production CDN) +- **Monitoring**: Full monitoring and alerting + +## Deployment + +### 1. Create Namespaces + +```bash +kubectl apply -f k8s/environments/namespaces.yaml +``` + +### 2. Deploy Environment-Specific ConfigMaps + +```bash +# Development +kubectl apply -f k8s/environments/development/configmap.yaml + +# Staging +kubectl apply -f k8s/environments/staging/configmap.yaml + +# Production +kubectl apply -f k8s/environments/production/configmap.yaml +``` + +### 3. Deploy Base Resources + +Deploy base resources (deployments, services) to each namespace: + +```bash +# Development +kubectl apply -f k8s/backend-api/ -n veza-development +kubectl apply -f k8s/frontend/ -n veza-development +kubectl apply -f k8s/chat-server/ -n veza-development + +# Staging +kubectl apply -f k8s/backend-api/ -n veza-staging +kubectl apply -f k8s/frontend/ -n veza-staging +kubectl apply -f k8s/chat-server/ -n veza-staging + +# Production +kubectl apply -f k8s/backend-api/ -n veza-production +kubectl apply -f k8s/frontend/ -n veza-production +kubectl apply -f k8s/chat-server/ -n veza-production +``` + +### 4. Apply Environment Overrides + +```bash +# Development +kubectl apply -f k8s/environments/development/deployment-overrides.yaml + +# Staging +kubectl apply -f k8s/environments/staging/deployment-overrides.yaml + +# Production +kubectl apply -f k8s/environments/production/deployment-overrides.yaml +``` + +### 5. Deploy Ingress + +```bash +# Development (no SSL) +kubectl apply -f k8s/environments/ingress-dev.yaml + +# Staging (staging SSL) +kubectl apply -f k8s/environments/ingress-staging.yaml + +# Production (production SSL - already in k8s/ingress.yaml) +kubectl apply -f k8s/ingress.yaml +``` + +## Configuration + +### Environment Variables + +Each environment has different configuration values: + +#### Development +- `APP_ENV=development` +- `LOG_LEVEL=DEBUG` +- `ENABLE_PROFILING=true` +- `RATE_LIMIT_ENABLED=false` + +#### Staging +- `APP_ENV=staging` +- `LOG_LEVEL=INFO` +- `ENABLE_PROFILING=false` +- `RATE_LIMIT_ENABLED=true` +- `RATE_LIMIT_LIMIT=200` + +#### Production +- `APP_ENV=production` +- `LOG_LEVEL=WARN` +- `ENABLE_PROFILING=false` +- `RATE_LIMIT_ENABLED=true` +- `RATE_LIMIT_LIMIT=100` + +### Secrets + +Each environment should have its own secrets: + +```bash +# Development secrets +kubectl create secret generic veza-secrets \ + --from-literal=database-url=postgres://dev_user:dev_pass@dev-db:5432/veza_dev \ + --from-literal=jwt-secret=dev-secret-key-min-32-chars \ + -n veza-development + +# Staging secrets +kubectl create secret generic veza-secrets \ + --from-literal=database-url=postgres://staging_user:staging_pass@staging-db:5432/veza_staging \ + --from-literal=jwt-secret=staging-secret-key-min-32-chars \ + -n veza-staging + +# Production secrets +kubectl create secret generic veza-secrets \ + --from-literal=database-url=postgres://prod_user:prod_pass@prod-db:5432/veza_prod \ + --from-literal=jwt-secret=production-secret-key-min-32-chars \ + -n veza-production +``` + +## Verification + +### Check Namespaces + +```bash +kubectl get namespaces | grep veza +``` + +### Check Resources per Environment + +```bash +# Development +kubectl get all -n veza-development + +# Staging +kubectl get all -n veza-staging + +# Production +kubectl get all -n veza-production +``` + +### Check ConfigMaps + +```bash +kubectl get configmap veza-config -n veza-development -o yaml +kubectl get configmap veza-config -n veza-staging -o yaml +kubectl get configmap veza-config -n veza-production -o yaml +``` + +## Environment Promotion + +### Promote from Development to Staging + +```bash +# Tag images +docker tag veza-backend-api:dev veza-backend-api:staging +docker tag veza-frontend:dev veza-frontend:staging + +# Push to registry +docker push veza-backend-api:staging +docker push veza-frontend:staging + +# Update deployments +kubectl set image deployment/veza-backend-api \ + backend-api=veza-backend-api:staging \ + -n veza-staging + +kubectl set image deployment/veza-frontend \ + frontend=veza-frontend:staging \ + -n veza-staging +``` + +### Promote from Staging to Production + +```bash +# Tag images +docker tag veza-backend-api:staging veza-backend-api:production +docker tag veza-frontend:staging veza-frontend:production + +# Push to registry +docker push veza-backend-api:production +docker push veza-frontend:production + +# Update deployments +kubectl set image deployment/veza-backend-api \ + backend-api=veza-backend-api:production \ + -n veza-production + +kubectl set image deployment/veza-frontend \ + frontend=veza-frontend:production \ + -n veza-production +``` + +## Best Practices + +1. **Separate Secrets**: Never share secrets between environments +2. **Resource Limits**: Set appropriate resource limits per environment +3. **Monitoring**: Enable monitoring in staging and production +4. **Backups**: Configure backups for staging and production +5. **SSL**: Use staging certificates in staging, production in production +6. **CORS**: Restrict CORS origins per environment +7. **Logging**: Use appropriate log levels per environment +8. **Rate Limiting**: Enable in staging and production, disable in dev + +## Troubleshooting + +### Check Environment Configuration + +```bash +# View environment config +kubectl get configmap veza-config -n veza-development -o jsonpath='{.data.app-env}' + +# Check pod environment variables +kubectl exec -it deployment/veza-backend-api -n veza-development -- env | grep APP_ENV +``` + +### Switch Between Environments + +```bash +# Set default namespace +kubectl config set-context --current --namespace=veza-development + +# Or use -n flag +kubectl get pods -n veza-staging +``` + +### Compare Configurations + +```bash +# Compare configmaps +diff <(kubectl get configmap veza-config -n veza-staging -o yaml) \ + <(kubectl get configmap veza-config -n veza-production -o yaml) +``` + diff --git a/k8s/environments/development/configmap.yaml b/k8s/environments/development/configmap.yaml new file mode 100644 index 000000000..b1c8dbb8a --- /dev/null +++ b/k8s/environments/development/configmap.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: veza-config + namespace: veza-development +data: + app-env: "development" + api-url: "http://veza-backend-api:8080" + cors-allowed-origins: "http://localhost:3000,http://localhost:5173,http://localhost:5176" + log-level: "DEBUG" + enable-debug: "true" + enable-profiling: "true" + rate-limit-enabled: "false" + database-pool-size: "5" + redis-ttl: "3600" # 1 hour + diff --git a/k8s/environments/development/deployment-overrides.yaml b/k8s/environments/development/deployment-overrides.yaml new file mode 100644 index 000000000..2f443ac75 --- /dev/null +++ b/k8s/environments/development/deployment-overrides.yaml @@ -0,0 +1,54 @@ +# Development environment overrides +# These values override the base deployment for development + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: veza-backend-api + namespace: veza-development +spec: + replicas: 1 # Single replica for dev + template: + spec: + containers: + - name: backend-api + env: + - name: APP_ENV + value: "development" + - name: LOG_LEVEL + value: "DEBUG" + - name: ENABLE_PROFILING + value: "true" + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "500m" + memory: "512Mi" + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: veza-frontend + namespace: veza-development +spec: + replicas: 1 # Single replica for dev + template: + spec: + containers: + - name: frontend + env: + - name: VITE_APP_ENV + value: "development" + - name: VITE_API_URL + value: "http://localhost:8080" + resources: + requests: + cpu: "50m" + memory: "64Mi" + limits: + cpu: "200m" + memory: "128Mi" + diff --git a/k8s/environments/ingress-dev.yaml b/k8s/environments/ingress-dev.yaml new file mode 100644 index 000000000..c585abe70 --- /dev/null +++ b/k8s/environments/ingress-dev.yaml @@ -0,0 +1,32 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: veza-ingress-dev + namespace: veza-development + annotations: + kubernetes.io/ingress.class: nginx + nginx.ingress.kubernetes.io/ssl-redirect: "false" # No SSL in dev + nginx.ingress.kubernetes.io/force-ssl-redirect: "false" +spec: + rules: + - host: dev.veza.local + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: veza-frontend + port: + number: 80 + - host: api-dev.veza.local + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: veza-backend-api + port: + number: 8080 + diff --git a/k8s/environments/ingress-staging.yaml b/k8s/environments/ingress-staging.yaml new file mode 100644 index 000000000..078cb85ce --- /dev/null +++ b/k8s/environments/ingress-staging.yaml @@ -0,0 +1,38 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: veza-ingress-staging + namespace: veza-staging + annotations: + kubernetes.io/ingress.class: nginx + cert-manager.io/cluster-issuer: letsencrypt-staging # Use staging issuer + nginx.ingress.kubernetes.io/ssl-redirect: "true" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" +spec: + tls: + - hosts: + - staging.veza.com + - api-staging.veza.com + secretName: veza-tls-staging + rules: + - host: staging.veza.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: veza-frontend + port: + number: 80 + - host: api-staging.veza.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: veza-backend-api + port: + number: 8080 + diff --git a/k8s/environments/namespaces.yaml b/k8s/environments/namespaces.yaml new file mode 100644 index 000000000..bbadd551e --- /dev/null +++ b/k8s/environments/namespaces.yaml @@ -0,0 +1,32 @@ +# Namespaces for different environments + +--- +apiVersion: v1 +kind: Namespace +metadata: + name: veza-development + labels: + name: veza-development + environment: development + tier: development + +--- +apiVersion: v1 +kind: Namespace +metadata: + name: veza-staging + labels: + name: veza-staging + environment: staging + tier: staging + +--- +apiVersion: v1 +kind: Namespace +metadata: + name: veza-production + labels: + name: veza-production + environment: production + tier: production + diff --git a/k8s/environments/production/configmap.yaml b/k8s/environments/production/configmap.yaml new file mode 100644 index 000000000..54025e5af --- /dev/null +++ b/k8s/environments/production/configmap.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: veza-config + namespace: veza-production +data: + app-env: "production" + api-url: "http://veza-backend-api:8080" + cors-allowed-origins: "https://app.veza.com,https://veza.com" + log-level: "WARN" + enable-debug: "false" + enable-profiling: "false" + rate-limit-enabled: "true" + rate-limit-limit: "100" + rate-limit-window: "60" + database-pool-size: "20" + redis-ttl: "86400" # 24 hours + cdn-enabled: "true" + cdn-base-url: "https://cdn.veza.com" + monitoring-enabled: "true" + alerting-enabled: "true" + diff --git a/k8s/environments/production/deployment-overrides.yaml b/k8s/environments/production/deployment-overrides.yaml new file mode 100644 index 000000000..5171abc9d --- /dev/null +++ b/k8s/environments/production/deployment-overrides.yaml @@ -0,0 +1,52 @@ +# Production environment overrides +# These values override the base deployment for production + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: veza-backend-api + namespace: veza-production +spec: + replicas: 3 # 3+ replicas for production + template: + spec: + containers: + - name: backend-api + env: + - name: APP_ENV + value: "production" + - name: LOG_LEVEL + value: "WARN" + resources: + requests: + cpu: "500m" + memory: "512Mi" + limits: + cpu: "2000m" + memory: "2Gi" + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: veza-frontend + namespace: veza-production +spec: + replicas: 3 # 3+ replicas for production + template: + spec: + containers: + - name: frontend + env: + - name: VITE_APP_ENV + value: "production" + - name: VITE_API_URL + value: "https://api.veza.com" + resources: + requests: + cpu: "100m" + memory: "128Mi" + limits: + cpu: "500m" + memory: "256Mi" + diff --git a/k8s/environments/staging/configmap.yaml b/k8s/environments/staging/configmap.yaml new file mode 100644 index 000000000..d4138fcd9 --- /dev/null +++ b/k8s/environments/staging/configmap.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: veza-config + namespace: veza-staging +data: + app-env: "staging" + api-url: "http://veza-backend-api:8080" + cors-allowed-origins: "https://staging.veza.com,https://staging-app.veza.com" + log-level: "INFO" + enable-debug: "false" + enable-profiling: "false" + rate-limit-enabled: "true" + rate-limit-limit: "200" + rate-limit-window: "60" + database-pool-size: "10" + redis-ttl: "7200" # 2 hours + cdn-enabled: "true" + cdn-base-url: "https://cdn-staging.veza.com" + diff --git a/k8s/environments/staging/deployment-overrides.yaml b/k8s/environments/staging/deployment-overrides.yaml new file mode 100644 index 000000000..39d34703e --- /dev/null +++ b/k8s/environments/staging/deployment-overrides.yaml @@ -0,0 +1,52 @@ +# Staging environment overrides +# These values override the base deployment for staging + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: veza-backend-api + namespace: veza-staging +spec: + replicas: 2 # 2 replicas for staging + template: + spec: + containers: + - name: backend-api + env: + - name: APP_ENV + value: "staging" + - name: LOG_LEVEL + value: "INFO" + resources: + requests: + cpu: "250m" + memory: "256Mi" + limits: + cpu: "1000m" + memory: "1Gi" + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: veza-frontend + namespace: veza-staging +spec: + replicas: 2 # 2 replicas for staging + template: + spec: + containers: + - name: frontend + env: + - name: VITE_APP_ENV + value: "staging" + - name: VITE_API_URL + value: "https://api-staging.veza.com" + resources: + requests: + cpu: "100m" + memory: "128Mi" + limits: + cpu: "500m" + memory: "256Mi" +