feat: Add deployment scripts and hard node affinity for nginx-load-balancer example

This commit is contained in:
mik-tf
2025-11-07 22:18:44 -05:00
parent 3028643a2c
commit 77e054cdea
6 changed files with 530 additions and 13 deletions

View File

@@ -0,0 +1,159 @@
#!/bin/bash
# Apply fixes for nginx-load-balancer
# Implements the configuration changes identified in the analysis
set -e
echo "🔧 nginx-load-balancer Fixes Application"
echo "========================================"
echo ""
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
RED='\033[0;31m'
NC='\033[0m' # No Color
echo "🚀 Applying fixes for nginx-load-balancer..."
echo ""
# Step 1: Apply the updated deployment (hard node affinity)
echo "🔍 Step 1: Applying updated deployment (hard node affinity)..."
echo " Changes:"
echo " • Changed from soft preferences to hard requirements"
echo " • Ensures pods only run on worker nodes (not masters)"
echo ""
if kubectl apply -f nginx-load-balancer-deployment.yaml; then
echo -e "${GREEN}✅ Deployment updated successfully${NC}"
else
echo -e "${RED}❌ Failed to update deployment${NC}"
exit 1
fi
echo ""
# Step 2: Apply the updated service (remove externalTrafficPolicy)
echo "🔍 Step 2: Applying updated service (LoadBalancer configuration)..."
echo " Changes:"
echo " • Removed externalTrafficPolicy: Local"
echo " • Fixes LoadBalancer IP accessibility issues"
echo ""
if kubectl apply -f nginx-load-balancer-service.yaml; then
echo -e "${GREEN}✅ Service updated successfully${NC}"
else
echo -e "${RED}❌ Failed to update service${NC}"
exit 1
fi
echo ""
# Step 3: Restart deployment to apply changes
echo "🔍 Step 3: Restarting deployment to apply changes..."
echo " This ensures all pods are recreated with the new configuration"
if kubectl rollout restart deployment/nginx-load-balancer; then
echo -e "${GREEN}✅ Deployment restart initiated${NC}"
else
echo -e "${RED}❌ Failed to restart deployment${NC}"
exit 1
fi
echo " Waiting for rollout to complete..."
if kubectl rollout status deployment/nginx-load-balancer --timeout=180s; then
echo -e "${GREEN}✅ Deployment rollout completed${NC}"
else
echo -e "${YELLOW}⚠️ Deployment rollout timed out (this is normal, pods may still be starting)${NC}"
fi
echo ""
# Step 4: Wait for pods to be ready
echo "🔍 Step 4: Waiting for pods to be ready..."
echo " This may take up to 60 seconds due to restart and node affinity changes"
if kubectl wait --for=condition=ready pod -l app=nginx-load-balancer --timeout=120s; then
echo -e "${GREEN}✅ All pods are ready${NC}"
else
echo -e "${YELLOW}⚠️ Some pods are still starting (this is normal)${NC}"
fi
echo ""
# Step 5: Verify the fixes
echo "🔍 Step 5: Running verification checks..."
echo ""
# Check pod distribution
echo "📊 Pod Distribution:"
PODS=$(kubectl get pods -l app=nginx-load-balancer -o wide)
echo "$PODS"
echo ""
# Count pods on master vs worker nodes
MASTER_PODS=$(echo "$PODS" | grep "master" | wc -l)
WORKER_PODS=$(echo "$PODS" | grep -v "master" | grep -v "NAME" | wc -l)
TOTAL_PODS=$(echo "$PODS" | grep -v "NAME" | wc -l)
echo "Pod distribution:"
echo " • Total pods: $TOTAL_PODS"
echo " • Master pods: $MASTER_PODS"
echo " • Worker pods: $WORKER_PODS"
if [ "$MASTER_PODS" -eq 0 ] && [ "$WORKER_PODS" -eq 3 ]; then
echo -e "${GREEN}✅ EXCELLENT: Pods only on worker nodes (3/3)${NC}"
elif [ "$MASTER_PODS" -eq 0 ]; then
echo -e "${GREEN}✅ GOOD: No pods on master nodes${NC}"
echo -e "${YELLOW} Note: Expected 3 pods, found $WORKER_PODS${NC}"
else
echo -e "${RED}❌ ISSUE: Pods found on master nodes (node affinity not working)${NC}"
fi
echo ""
# Check LoadBalancer service
echo "🌐 LoadBalancer Service Status:"
SERVICE=$(kubectl get svc nginx-load-balancer-service)
echo "$SERVICE"
echo ""
SERVICE_IP=$(kubectl get svc nginx-load-balancer-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
SERVICE_PORT=$(kubectl get svc nginx-load-balancer-service -o jsonpath='{.spec.ports[0].port}')
if [ -n "$SERVICE_IP" ]; then
echo -e "${GREEN}✅ LoadBalancer IP assigned: $SERVICE_IP${NC}"
echo " Service URL: http://$SERVICE_IP:$SERVICE_PORT"
else
echo -e "${YELLOW}⚠️ LoadBalancer IP not yet assigned (may take time)${NC}"
fi
echo ""
# Final summary
echo "========================================"
echo "🎉 FIXES APPLIED SUCCESSFULLY!"
echo "========================================"
echo ""
echo -e "${BLUE}📋 Summary of Changes Applied:${NC}"
echo "• ✅ Hard node affinity (pods on workers only)"
echo "• ✅ LoadBalancer service configuration (removed externalTrafficPolicy)"
echo "• ✅ Deployment restarted with new configuration"
echo ""
echo -e "${BLUE}🌐 Access Information:${NC}"
if [ -n "$SERVICE_IP" ]; then
echo "• LoadBalancer URL: http://$SERVICE_IP:$SERVICE_PORT"
echo "• Direct node access: http://[node-ip]:8080 (on nodes with pods)"
echo ""
echo -e "${BLUE}🧪 Test both access methods:${NC}"
echo " 1. LoadBalancer IP (load balancing): curl -6 'http://$SERVICE_IP:$SERVICE_PORT'"
echo " 2. Direct node access: kubectl get nodes -o wide"
fi
echo ""
echo -e "${BLUE}🔧 Next Steps:${NC}"
echo "1. Run verification: ./verify-fixes.sh"
echo "2. Test LoadBalancer: curl -6 'http://$SERVICE_IP:$SERVICE_PORT'"
echo "3. Test node access: Get node IPs with 'kubectl get nodes -o wide'"
echo "4. Monitor pods: kubectl get pods -l app=nginx-load-balancer -o wide"
echo ""
echo -e "${GREEN}✅ All fixes applied and verified!${NC}"

View File

@@ -0,0 +1,202 @@
#!/bin/bash
# Clean deploy script for nginx-load-balancer
# Removes existing resources and deploys with fixes applied
set -e
echo "🧹 Clean Deploy nginx-load-balancer"
echo "==================================="
echo ""
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
RED='\033[0;31m'
NC='\033[0m' # No Color
echo "🗑️ Step 1: Cleaning up existing resources..."
echo ""
# Delete existing resources if they exist
echo "Removing existing nginx-load-balancer resources..."
if kubectl get deployment nginx-load-balancer &> /dev/null; then
echo "• Deleting deployment..."
kubectl delete deployment nginx-load-balancer --ignore-not-found=true
fi
if kubectl get service nginx-load-balancer-service &> /dev/null; then
echo "• Deleting service..."
kubectl delete service nginx-load-balancer-service --ignore-not-found=true
fi
if kubectl get configmap nginx-load-balancer-content &> /dev/null; then
echo "• Deleting configmaps..."
kubectl delete configmap nginx-load-balancer-content --ignore-not-found=true
fi
if kubectl get configmap nginx-load-balancer-nginx-config &> /dev/null; then
kubectl delete configmap nginx-load-balancer-nginx-config --ignore-not-found=true
fi
echo -e "${GREEN}✅ Cleanup complete${NC}"
echo ""
# Wait a moment for resources to be fully cleaned up
echo "⏳ Waiting for cleanup to complete (5 seconds)..."
sleep 5
echo ""
echo "🚀 Step 2: Deploying with fixes applied..."
echo ""
# Deploy ConfigMaps
echo "📦 Deploying ConfigMaps..."
if kubectl apply -f nginx-load-balancer-configmaps.yaml; then
echo -e "${GREEN}✅ ConfigMaps deployed successfully${NC}"
else
echo -e "${RED}❌ Failed to deploy ConfigMaps${NC}"
exit 1
fi
echo ""
# Deploy Deployment (with hard node affinity)
echo "📦 Deploying nginx application (3 replicas, worker-only)..."
if kubectl apply -f nginx-load-balancer-deployment.yaml; then
echo -e "${GREEN}✅ Deployment created successfully${NC}"
echo " • Hard node affinity: Worker nodes only"
echo " • Replicas: 3"
echo " • Image: nginx:alpine"
else
echo -e "${RED}❌ Failed to create deployment${NC}"
exit 1
fi
echo ""
# Deploy Service (without externalTrafficPolicy: Local)
echo "📦 Creating LoadBalancer service..."
if kubectl apply -f nginx-load-balancer-service.yaml; then
echo -e "${GREEN}✅ LoadBalancer service created successfully${NC}"
echo " • Type: LoadBalancer"
echo " • ExternalTrafficPolicy: None (optimized for Mycelium)"
echo " • Dual-stack: IPv4 + IPv6"
else
echo -e "${RED}❌ Failed to create service${NC}"
exit 1
fi
echo ""
echo "⏳ Step 3: Waiting for deployment to be ready..."
echo " This may take up to 60 seconds..."
echo ""
# Wait for deployment to be ready
if kubectl wait --for=condition=available deployment/nginx-load-balancer --timeout=120s; then
echo -e "${GREEN}✅ Deployment is ready${NC}"
else
echo -e "${YELLOW}⚠️ Deployment not fully ready yet (pods may still be starting)${NC}"
fi
echo ""
# Check pod status
echo "🔍 Step 4: Checking pod distribution..."
PODS=$(kubectl get pods -l app=nginx-load-balancer -o wide)
if echo "$PODS" | grep -q "master"; then
echo -e "${RED}❌ ISSUE: Pods found on master nodes (this shouldn't happen with hard affinity)${NC}"
echo "$PODS"
else
echo -e "${GREEN}✅ EXCELLENT: No pods on master nodes (hard affinity working)${NC}"
fi
echo "$PODS"
echo ""
# Count pods
TOTAL_PODS=$(echo "$PODS" | grep -v "NAME" | wc -l)
echo "Total pods running: $TOTAL_PODS"
if [ "$TOTAL_PODS" -eq 3 ]; then
echo -e "${GREEN}✅ Perfect: 3/3 pods running${NC}"
elif [ "$TOTAL_PODS" -lt 3 ]; then
echo -e "${YELLOW}⚠️ Partial: $TOTAL_PODS/3 pods running (pods may still be starting)${NC}"
else
echo -e "${YELLOW}⚠️ Unexpected: $TOTAL_PODS pods running (expected 3)${NC}"
fi
echo ""
# Check LoadBalancer service
echo "🌐 Step 5: Checking LoadBalancer service..."
SERVICE=$(kubectl get svc nginx-load-balancer-service)
echo "$SERVICE"
echo ""
SERVICE_IP=$(kubectl get svc nginx-load-balancer-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
SERVICE_PORT=$(kubectl get svc nginx-load-balancer-service -o jsonpath='{.spec.ports[0].port}')
if [ -n "$SERVICE_IP" ]; then
echo -e "${GREEN}✅ LoadBalancer IP assigned: $SERVICE_IP${NC}"
echo " Service URL: http://$SERVICE_IP:$SERVICE_PORT"
# Test LoadBalancer access
echo ""
echo "🧪 Testing LoadBalancer IP access..."
if timeout 10 curl -s -f "http://$SERVICE_IP:$SERVICE_PORT" > /dev/null 2>&1; then
echo -e "${GREEN}✅ LoadBalancer IP is accessible!${NC}"
echo " Test command: curl -6 'http://$SERVICE_IP:$SERVICE_PORT'"
else
echo -e "${YELLOW}⚠️ LoadBalancer IP not yet accessible (may take time to propagate)${NC}"
echo " Try: curl -6 'http://$SERVICE_IP:$SERVICE_PORT'"
fi
else
echo -e "${YELLOW}⚠️ LoadBalancer IP not yet assigned (may take time)${NC}"
fi
echo ""
# Test direct node access
echo "🔗 Step 6: Testing direct node access..."
NODE_IPS=$(kubectl get nodes -o jsonpath='{range .items[*]}{.status.addresses[?@.type=="InternalIP"].address}{"\n"}{end}' | head -3)
for node_ip in $NODE_IPS; do
echo "Testing node: $node_ip"
if timeout 5 curl -s -f "http://$node_ip:8080" > /dev/null 2>&1; then
echo -e "${GREEN} ✅ Direct node access works${NC}"
break
else
echo -e "${YELLOW} ⚠️ Direct node access failed (no pod on this node)${NC}"
fi
done
echo ""
# Final summary
echo "==================================="
echo "🎉 CLEAN DEPLOY COMPLETE!"
echo "==================================="
echo ""
echo -e "${BLUE}📊 Deployment Summary:${NC}"
echo "• ✅ Clean deployment with fixes applied"
echo "• ✅ Hard node affinity (worker nodes only)"
echo "• ✅ LoadBalancer service (no externalTrafficPolicy)"
echo "• ✅ 3 nginx replicas"
echo ""
if [ -n "$SERVICE_IP" ]; then
echo -e "${BLUE}🌐 Access Information:${NC}"
echo "• LoadBalancer URL: http://$SERVICE_IP:$SERVICE_PORT"
echo " (This should do real load balancing across pods)"
echo ""
echo "• Direct node access: Get node IPs with 'kubectl get nodes -o wide'"
echo " (This bypasses load balancer, goes directly to pods)"
echo ""
echo -e "${BLUE}🧪 Test Commands:${NC}"
echo "• LoadBalancer (load balancing): curl -6 'http://$SERVICE_IP:$SERVICE_PORT'"
echo "• Node access: Get node IP and curl -6 'http://[node-ip]:8080'"
echo "• Monitor pods: kubectl get pods -l app=nginx-load-balancer -o wide"
echo "• Check service: kubectl get svc nginx-load-balancer-service"
fi
echo ""
echo -e "${GREEN}✅ Clean deploy with fixes completed successfully!${NC}"

View File

@@ -16,18 +16,14 @@ spec:
spec: spec:
hostNetwork: false hostNetwork: false
dnsPolicy: ClusterFirst dnsPolicy: ClusterFirst
# Prefer worker nodes only (not master nodes) # Hard requirement: worker nodes only (not master nodes)
affinity: affinity:
nodeAffinity: nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution: requiredDuringSchedulingIgnoredDuringExecution:
- weight: 100 nodeSelectorTerms:
preference: - matchExpressions:
matchExpressions:
- key: node-role.kubernetes.io/master - key: node-role.kubernetes.io/master
operator: DoesNotExist operator: DoesNotExist
- weight: 50
preference:
matchExpressions:
- key: node-role.kubernetes.io/control-plane - key: node-role.kubernetes.io/control-plane
operator: DoesNotExist operator: DoesNotExist
containers: containers:

View File

@@ -8,7 +8,6 @@ metadata:
description: "LoadBalancer service for nginx-load-balancer deployment with automatic IPv6 assignment" description: "LoadBalancer service for nginx-load-balancer deployment with automatic IPv6 assignment"
spec: spec:
type: LoadBalancer type: LoadBalancer
externalTrafficPolicy: Local
ipFamilies: ipFamilies:
- IPv4 - IPv4
- IPv6 - IPv6

View File

@@ -14,10 +14,11 @@ cd myceliumcloud-examples/examples/nginx-load-balancer
**What this script does:** **What this script does:**
1. ✅ Deploy 3 nginx replicas (production-ready scaling) 1. ✅ Deploy 3 nginx replicas (production-ready scaling)
2. ✅ Create LoadBalancer service with automatic IPv6 2. ✅ Create LoadBalancer service with automatic IPv6
3. ✅ Configure worker node preferences 3. ✅ Configure hard worker node affinity (ensures pods on workers only)
4.Update website content with service information 4.Support both LoadBalancer IP and direct node access
5.Verify load balancing functionality 5.Update website content with service information
6.Show you the automatic IPv6 assignment 6.Verify load balancing functionality
7. ✅ Show you the automatic IPv6 assignment
**Expected output:** **Expected output:**
``` ```
@@ -42,6 +43,7 @@ To access from a machine with Mycelium installed:
- **Traffic Distribution** - Automatic load balancing across 3 replicas - **Traffic Distribution** - Automatic load balancing across 3 replicas
- **Worker Node Preferences** - Deploy only on worker nodes (not masters) - **Worker Node Preferences** - Deploy only on worker nodes (not masters)
- **Production Patterns** - Real-world scaling and reliability - **Production Patterns** - Real-world scaling and reliability
- **Dual-Access Networking** - Both LoadBalancer IP and direct node access supported
--- ---

View File

@@ -0,0 +1,159 @@
#!/bin/bash
# Verification script for nginx-load-balancer fixes
# Tests the applied configuration changes
set -e
echo "🔍 nginx-load-balancer Fix Verification"
echo "======================================"
echo ""
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
RED='\033[0;31m'
NC='\033[0m' # No Color
echo "🔍 Checking if fixes were applied..."
echo ""
# Check 1: Verify current pods distribution
echo "📍 Step 1: Checking pod distribution..."
PODS=$(kubectl get pods -l app=nginx-load-balancer -o wide)
if echo "$PODS" | grep -q "master"; then
echo -e "${RED}❌ ISSUE: Pods found on master nodes (node affinity fix not working)${NC}"
echo "$PODS"
else
echo -e "${GREEN}✅ GOOD: No pods on master nodes (node affinity working)${NC}"
fi
echo "$PODS"
echo ""
# Check 2: Count pods per node type
echo "📊 Step 2: Analyzing pod distribution by node type..."
WORKER_PODS=$(echo "$PODS" | grep -v "master" | grep -v "NAME" | wc -l)
TOTAL_PODS=$(echo "$PODS" | grep -v "NAME" | wc -l)
echo "Total pods running: $TOTAL_PODS"
echo "Pods on worker nodes: $WORKER_PODS"
if [ "$WORKER_PODS" -eq 3 ] && [ "$TOTAL_PODS" -eq 3 ]; then
echo -e "${GREEN}✅ EXPECTED: 3 pods on 3 worker nodes only${NC}"
else
echo -e "${YELLOW}⚠️ UNEXPECTED: Expected 3 pods on 3 worker nodes${NC}"
fi
echo ""
# Check 3: Service configuration
echo "🔧 Step 3: Checking service configuration..."
SERVICE=$(kubectl get svc nginx-load-balancer-service -o yaml)
if echo "$SERVICE" | grep -q "externalTrafficPolicy: Local"; then
echo -e "${RED}❌ ISSUE: externalTrafficPolicy: Local still present${NC}"
echo " This may cause LoadBalancer IP issues"
else
echo -e "${GREEN}✅ GOOD: externalTrafficPolicy: Local removed${NC}"
fi
if echo "$SERVICE" | grep -q "type: LoadBalancer"; then
echo -e "${GREEN}✅ GOOD: Service type is LoadBalancer${NC}"
else
echo -e "${RED}❌ ISSUE: Service type is not LoadBalancer${NC}"
fi
echo ""
# Check 4: LoadBalancer IP availability
echo "🌐 Step 4: Checking LoadBalancer IP..."
SERVICE_STATUS=$(kubectl get svc nginx-load-balancer-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
SERVICE_PORT=$(kubectl get svc nginx-load-balancer-service -o jsonpath='{.spec.ports[0].port}')
if [ -n "$SERVICE_STATUS" ]; then
echo -e "${GREEN}✅ GOOD: LoadBalancer IP assigned: $SERVICE_STATUS${NC}"
echo " Full URL: http://$SERVICE_STATUS:$SERVICE_PORT"
# Test LoadBalancer IP
echo ""
echo "🧪 Testing LoadBalancer IP access..."
if timeout 10 curl -s -f "http://$SERVICE_STATUS:$SERVICE_PORT" > /dev/null 2>&1; then
echo -e "${GREEN}✅ GOOD: LoadBalancer IP is accessible${NC}"
else
echo -e "${RED}❌ ISSUE: LoadBalancer IP is not accessible${NC}"
echo " Try: curl -6 'http://[$SERVICE_STATUS]:$SERVICE_PORT'"
fi
else
echo -e "${YELLOW}⚠️ WAITING: LoadBalancer IP not yet assigned${NC}"
fi
echo ""
# Check 5: Node access (dual access pattern)
echo "🔗 Step 5: Testing dual access pattern..."
# Get a node IP for testing
NODE_IPS=$(kubectl get nodes -o jsonpath='{range .items[*]}{.status.addresses[?@.type=="InternalIP"].address}{"\n"}{end}' | head -3)
WORKER_COUNT=0
for node_ip in $NODE_IPS; do
echo "Testing node: $node_ip"
# Test direct node access
if timeout 5 curl -s -f "http://$node_ip:8080" > /dev/null 2>&1; then
echo -e "${GREEN} ✅ Direct node access works${NC}"
WORKER_COUNT=$((WORKER_COUNT + 1))
else
echo -e "${YELLOW} ⚠️ Direct node access failed${NC}"
fi
done
echo "Nodes with working direct access: $WORKER_COUNT"
echo ""
# Check 6: Deployment configuration
echo "⚙️ Step 6: Checking deployment configuration..."
DEPLOYMENT=$(kubectl get deployment nginx-load-balancer -o yaml)
if echo "$DEPLOYMENT" | grep -q "requiredDuringSchedulingIgnoredDuringExecution"; then
echo -e "${GREEN}✅ GOOD: Hard node affinity configured${NC}"
else
echo -e "${RED}❌ ISSUE: Hard node affinity not found${NC}"
fi
if echo "$DEPLOYMENT" | grep -q "node-role.kubernetes.io/master"; then
echo -e "${GREEN}✅ GOOD: Node role filtering configured${NC}"
else
echo -e "${YELLOW}⚠️ WARNING: Node role filtering may be missing${NC}"
fi
echo ""
# Summary
echo "======================================"
echo "📊 VERIFICATION SUMMARY"
echo "======================================"
echo ""
if echo "$PODS" | grep -q "master"; then
echo -e "${RED}❌ NODE AFFINITY: Pods on master nodes (need fix)${NC}"
else
echo -e "${GREEN}✅ NODE AFFINITY: Pods on worker nodes only${NC}"
fi
if [ -n "$SERVICE_STATUS" ]; then
echo -e "${GREEN}✅ LOADBALANCER: IP assigned ($SERVICE_STATUS)${NC}"
else
echo -e "${YELLOW}⚠️ LOADBALANCER: IP not assigned yet${NC}"
fi
echo -e "${BLUE}🎯 DUAL ACCESS: Both LoadBalancer IP and node access should work${NC}"
echo ""
echo "🔧 Next steps if issues found:"
echo "1. Apply fixes: kubectl apply -f nginx-load-balancer-deployment.yaml"
echo "2. Apply service: kubectl apply -f nginx-load-balancer-service.yaml"
echo "3. Restart deployment: kubectl rollout restart deployment/nginx-load-balancer"
echo "4. Re-run this verification script"
echo ""
echo "✅ Verification complete!"