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.localhost en production.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:

  1. Browser → Gebruiker bezoekt staging.localhost of production.localhost
  2. Ingress Controller → NGINX controller routeert traffic naar juiste namespace
  3. Ingress → Specifieke ingress resource in staging/production namespace
  4. Service → Load balancer die traffic verdeelt over pods
  5. Deployment → Beheert replicas en zorgt voor auto-restart bij failures
  6. 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

  1. Kubernetes cluster (minikube, kind, Docker Desktop)
  2. NGINX Ingress Controller geïnstalleerd
  3. kubectl geconfigureerd
  4. 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

AspectStagingProduction
Replicas23
Namespacestagingproduction
URLstaging.localhostproduction.localhost
Environment var"staging""production"
DoelTestingLive traffic

📝 Best Practices

  1. Namespace isolatie: Elke omgeving in eigen namespace
  2. Labeling: Consistente labels voor environment, app, etc.
  3. Resource naming: Duidelijke namen met environment prefix
  4. Configuratie: Environment-specifieke variabelen
  5. Monitoring: Aparte monitoring per omgeving
  6. 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!

Last change: 2025-10-23