Kubernetes Multi-Environment Setup
TODO: Work in Progress: Deze tutorial moet nog getest/gedebugged!
Het idee van deze tutorial is je te laten zien hoe je staging en productie omgevingen kunt draaien in aparte namespaces op je lokale Kubernetes cluster, met eenvoudige localhost URL's zonder poortnummers....
🎯 Doel
- Staging en productie als aparte namespaces
- Eenvoudige URL's:
staging.localhostenproduction.localhost - Geen poortnummers onthouden
- Verschillende configuraties per omgeving
🏗️ Architectuur
┌─────────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
├─────────────────────────────────────────────────────────────┤
│ Namespace: staging │ Namespace: production │
│ ┌─────────────────────────┐ │ ┌─────────────────────────┐ │
│ │ Deployment (2 replicas) │ │ │ Deployment (3 replicas) │ │
│ │ Service │ │ │ Service │ │
│ │ Ingress │ │ │ Ingress │ │
│ └─────────────────────────┘ │ └─────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ staging.localhost │ production.localhost │
└─────────────────────────────────────────────────────────────┘
🌐 Traffic Flow Diagram
┌─────────────┐ ┌────────────────────────────────────────────────────────────┐
│ Browser │ │ Kubernetes Cluster │
│ │ │ │
│ User visits │ │ ┌─────────────────┐ ┌─────────────────┐ │
│ staging. │───▶│ │ Ingress │ │ Ingress │ │
│ localhost │ │ │ Controller │ │ Controller │ │
│ │ │ │ (NGINX) │ │ (NGINX) │ │
│ │ │ └─────────────────┘ └─────────────────┘ │
│ │ │ │ │ │
│ │ │ ▼ ▼ │
│ │ │ ┌─────────────────┐ ┌─────────────────┐ │
│ │ │ │ Ingress │ │ Ingress │ │
│ │ │ │ staging │ │ production │ │
│ │ │ │ namespace │ │ namespace │ │
│ │ │ └─────────────────┘ └─────────────────┘ │
│ │ │ │ │ │
│ │ │ ▼ ▼ │
│ │ │ ┌─────────────────┐ ┌─────────────────┐ │
│ │ │ │ Service │ │ Service │ │
│ │ │ │ apache- │ │ apache- │ │
│ │ │ │ service- │ │ service- │ │
│ │ │ │ staging │ │ production │ │
│ │ │ └─────────────────┘ └─────────────────┘ │
│ │ │ │ │ │
│ │ │ ▼ ▼ │
│ │ │ ┌─────────────────┐ ┌─────────────────┐ │
│ │ │ │ Deployment │ │ Deployment │ │
│ │ │ │ (2 replicas) │ │ (3 replicas) │ │
│ │ │ │ Auto-restart │ │ Auto-restart │ │
│ │ │ │ Load balance │ │ Load balance │ │
│ │ │ └─────────────────┘ └─────────────────┘ │
│ │ │ │ │ │
│ │ │ ▼ ▼ │
│ │ │ ┌─────────────────┐ ┌─────────────────┐ │
│ │ │ │ Pods │ │ Pods │ │
│ │ │ │ Container 1 │ │ Container 1 │ │
│ │ │ │ Container 2 │ │ Container 2 │ │
│ │ │ │ │ │ Container 3 │ │
│ │ │ └─────────────────┘ └─────────────────┘ │
└─────────────┘ └────────────────────────────────────────────────────────────┘
Traffic Flow Uitleg:
- Browser → Gebruiker bezoekt
staging.localhostofproduction.localhost - Ingress Controller → NGINX controller routeert traffic naar juiste namespace
- Ingress → Specifieke ingress resource in staging/production namespace
- Service → Load balancer die traffic verdeelt over pods
- Deployment → Beheert replicas en zorgt voor auto-restart bij failures
- Pods → Actuele containers die de applicatie draaien
Auto-Restart Mechanismen:
- Deployment: Houdt gewenst aantal replicas in stand
- Health Checks: Kubernetes controleert pod health
- Rolling Updates: Zero-downtime deployments
- Load Balancing: Traffic verdeeld over gezonde pods
📁 YAML Configuraties
Namespaces
---
apiVersion: v1
kind: Namespace
metadata:
name: staging
labels:
environment: staging
---
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
environment: production
Staging Deployment
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world-staging
namespace: staging
labels:
app: apache
environment: staging
spec:
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app: apache
environment: staging
template:
metadata:
labels:
app: apache
environment: staging
spec:
containers:
- name: apache
image: "httpd"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
env:
- name: ENVIRONMENT
value: "staging"
Production Deployment
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world-production
namespace: production
labels:
app: apache
environment: production
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app: apache
environment: production
template:
metadata:
labels:
app: apache
environment: production
spec:
containers:
- name: apache
image: "httpd"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
env:
- name: ENVIRONMENT
value: "production"
Staging Service
---
kind: Service
apiVersion: v1
metadata:
name: apache-service-staging
namespace: staging
labels:
app: apache
environment: staging
spec:
selector:
app: apache
environment: staging
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
Production Service
---
kind: Service
apiVersion: v1
metadata:
name: apache-service-production
namespace: production
labels:
app: apache
environment: production
spec:
selector:
app: apache
environment: production
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
Staging Ingress
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: apache-ingress-staging
namespace: staging
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: staging.localhost
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: apache-service-staging
port:
number: 80
Production Ingress
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: apache-ingress-production
namespace: production
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: production.localhost
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: apache-service-production
port:
number: 80
🚀 Deployment Scripts
Deploy All Environments
#!/bin/bash
# Script om alle omgevingen te deployen
echo "🚀 Deploying all environments..."
# Namespaces aanmaken
echo "📦 Creating namespaces..."
kubectl apply -f 00-namespaces.yml
# Staging deployen
echo "🔧 Deploying staging environment..."
kubectl apply -f staging-deployment.yml
kubectl apply -f staging-service.yml
kubectl apply -f staging-ingress.yml
# Production deployen
echo "🏭 Deploying production environment..."
kubectl apply -f production-deployment.yml
kubectl apply -f production-service.yml
kubectl apply -f production-ingress.yml
echo "✅ All environments deployed!"
echo ""
echo "🌐 Access your applications:"
echo " Staging: http://staging.localhost"
echo " Production: http://production.localhost"
echo ""
echo "📊 Check status with:"
echo " kubectl get pods -n staging"
echo " kubectl get pods -n production"
Individual Environment Scripts
# Deploy alleen staging
#!/bin/bash
echo "🔧 Deploying staging environment..."
kubectl apply -f staging-deployment.yml
kubectl apply -f staging-service.yml
kubectl apply -f staging-ingress.yml
echo "✅ Staging deployed!"
echo "🌐 Access at: http://staging.localhost"
# Deploy alleen production
#!/bin/bash
echo "🏭 Deploying production environment..."
kubectl apply -f production-deployment.yml
kubectl apply -f production-service.yml
kubectl apply -f production-ingress.yml
echo "✅ Production deployed!"
echo "🌐 Access at: http://production.localhost"
Cleanup Script
#!/bin/bash
echo "🧹 Cleaning up all environments..."
kubectl delete -f staging-ingress.yml 2>/dev/null || true
kubectl delete -f staging-service.yml 2>/dev/null || true
kubectl delete -f staging-deployment.yml 2>/dev/null || true
kubectl delete -f production-ingress.yml 2>/dev/null || true
kubectl delete -f production-service.yml 2>/dev/null || true
kubectl delete -f production-deployment.yml 2>/dev/null || true
kubectl delete -f 00-namespaces.yml 2>/dev/null || true
echo "✅ Cleanup completed!"
🔧 Port Forwarding vs Ingress
Port Forwarding (Alternatief)
Als je geen Ingress Controller hebt, kun je ook port forwarding gebruiken:
# Staging
kubectl port-forward -n staging service/apache-service-staging 8080:80
# Production
kubectl port-forward -n production service/apache-service-production 8081:80
Toegang:
- Staging:
http://localhost:8080 - Production:
http://localhost:8081
Waarom Ingress Beter is voor Localhost
Port Forwarding nadelen:
- Je moet poortnummers onthouden (8080, 8081, etc.)
- Meerdere terminal sessies nodig
- Minder realistisch voor productie-achtige setup
- Geen load balancing mogelijkheden
Ingress voordelen:
- Eenvoudige URL's (
staging.localhost) - Eén ingress controller voor alle services
- Realistischere productie-achtige setup
- Load balancing en SSL mogelijkheden
📊 Monitoring en Troubleshooting
Status Controleren
# Alle pods bekijken
kubectl get pods -n staging
kubectl get pods -n production
# Services bekijken
kubectl get services -n staging
kubectl get services -n production
# Ingress bekijken
kubectl get ingress -n staging
kubectl get ingress -n production
# Alle resources in één overzicht
kubectl get all -n staging
kubectl get all -n production
Logs Bekijken
# Pod logs
kubectl logs -n staging deployment/hello-world-staging
kubectl logs -n production deployment/hello-world-production
# Ingress controller logs (als je problemen hebt)
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller
Troubleshooting
Probleem: staging.localhost werkt niet
# Controleer of ingress controller draait
kubectl get pods -n ingress-nginx
# Controleer ingress status
kubectl describe ingress -n staging apache-ingress-staging
# Test met port forwarding als fallback
kubectl port-forward -n staging service/apache-service-staging 8080:80
🛠️ Vereisten
- Kubernetes cluster (minikube, kind, Docker Desktop)
- NGINX Ingress Controller geïnstalleerd
- kubectl geconfigureerd
- Localhost DNS configuratie (zie hieronder)
🌐 Localhost DNS Configuratie
Automatisch (meestal)
De meeste moderne systemen behandelen .localhost automatisch als 127.0.0.1:
# Test of het werkt:
ping staging.localhost
ping production.localhost
Handmatig (als automatisch niet werkt)
macOS/Linux:
# Bewerk /etc/hosts
sudo nano /etc/hosts
# Voeg toe:
127.0.0.1 staging.localhost
127.0.0.1 production.localhost
Windows:
# Bewerk C:\Windows\System32\drivers\etc\hosts
127.0.0.1 staging.localhost
127.0.0.1 production.localhost
Alternatieve URL's (als .localhost niet werkt)
Je kunt ook andere lokale domeinen gebruiken:
# In je ingress bestanden, verander:
- host: staging.localhost
# Naar:
- host: staging.local
# Of:
- host: staging.test
Dan in /etc/hosts:
127.0.0.1 staging.local
127.0.0.1 production.local
Ingress Controller Installeren
# Voor minikube
minikube addons enable ingress
# Voor Docker Desktop (via Helm)
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx
# Voor kind
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
🎯 Verschillen tussen Omgevingen
| Aspect | Staging | Production |
|---|---|---|
| Replicas | 2 | 3 |
| Namespace | staging | production |
| URL | staging.localhost | production.localhost |
| Environment var | "staging" | "production" |
| Doel | Testing | Live traffic |
📝 Best Practices
- Namespace isolatie: Elke omgeving in eigen namespace
- Labeling: Consistente labels voor environment, app, etc.
- Resource naming: Duidelijke namen met environment prefix
- Configuratie: Environment-specifieke variabelen
- Monitoring: Aparte monitoring per omgeving
- Security: Network policies per namespace
🔄 CI/CD Integratie
Deze setup is perfect voor CI/CD pipelines:
# GitHub Actions voorbeeld
- name: Deploy to Staging
run: |
kubectl apply -f k8s/staging-deployment.yml
kubectl apply -f k8s/staging-service.yml
kubectl apply -f k8s/staging-ingress.yml
- name: Deploy to Production
run: |
kubectl apply -f k8s/production-deployment.yml
kubectl apply -f k8s/production-service.yml
kubectl apply -f k8s/production-ingress.yml
Deze setup geeft je een realistische multi-environment Kubernetes setup op localhost, perfect voor development en testing!