# Mycelium Cloud - Nginx NodePort Secure Website Hosting A complete, production-ready example for deploying a secure, globally accessible website on Mycelium Cloud using Kubernetes **NodePort** services with enhanced network isolation. This demonstrates **security-first IPv6 web hosting** with standard Kubernetes patterns. ## πŸ”‘ Key Concept: NodePort Access Pattern **Important:** With NodePort, you access the service via: - **Worker Node's Mycelium IPv6 address** + **NodePort 30091** - Example: `http://[worker-node-mycelium-ipv6]:30091/` **This is different from hostNetwork** where pods get direct Mycelium IPs: - **hostNetwork**: Pod has Mycelium IP β†’ Access: `http://[pod-mycelium-ip]:8080` - **NodePort**: Pod isolated network β†’ Access: `http://[node-mycelium-ip]:30091` The traffic flow is: `User β†’ Node:30091 β†’ Service:8080 β†’ Pod:8080` ## πŸ“ What This Contains This directory contains everything you need to deploy a secure website with global IPv6 accessibility: - **nginx-nodeport.md** - This comprehensive guide - **nginx-nodeport-deployment.yaml** - Secure deployment configuration - **nginx-nodeport-service.yaml** - NodePort service configuration - **nginx-nodeport-configmaps.yaml** - Website content and nginx configuration - **test-nodeport-ipv6.sh** - IPv6 testing and verification script - **update-content.sh** - Dynamic content update with IPv6 discovery - **compare-approaches.md** - Security and architecture comparison ## πŸš€ Quick Start (3 minutes) ```bash # 1. Deploy the ConfigMaps (content and nginx config) kubectl apply -f nginx-nodeport-configmaps.yaml # 2. Deploy the nginx application kubectl apply -f nginx-nodeport-deployment.yaml # 3. Create the NodePort service kubectl apply -f nginx-nodeport-service.yaml # 4. Wait for deployment to be ready kubectl wait --for=condition=ready pod -l app=nginx-nodeport --timeout=60s # 5. Get IPv6 address of the ACTUAL node where your pod is running POD_NODE=$(kubectl get pods -l app=nginx-nodeport -o jsonpath='{.items[0].spec.nodeName}') NODE_IPV6=$(kubectl get node $POD_NODE -o jsonpath='{range .status.addresses[?(@.type=="InternalIP")]}{.address}{"\n"}{end}' | grep -E '^[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+$' | head -1) echo "Your website is accessible at: http://[$NODE_IPV6]:30091" echo "NOTE: Pod is running on node: $POD_NODE" # 6. Test the website curl -6 "http://[$NODE_IPV6]:30091/" ``` **Alternative: Use the automated script for IPv6 discovery:** ```bash # Automatically discover IPv6 addresses and update content ./update-content.sh ``` **⚠️ Important: Worker Node vs Master Node Access** Unlike hostNetwork (which can be accessed from any node), NodePort services are **limited to the nodes where your pods are actually running**. Always check: ```bash # Check which node your pod is running on kubectl get pods -l app=nginx-nodeport -o wide # Get the IPv6 of the correct WORKER node (not master) NODE_IPV6=$(kubectl get nodes -l kubernetes.io/role!=master -o jsonpath='{range .items[0].status.addresses[?(@.type=="InternalIP")]}{.address}{"\n"}{end}' | grep -E '^[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+$' | head -1) ``` **Expected Result:** You'll see a professional website with NodePort security branding and IPv6 address detection. ## πŸ“‹ What You'll Learn - βœ… **Security-First IPv6 Web Hosting** - Enhanced network isolation - βœ… **Standard Kubernetes Service Patterns** - Industry best practices - βœ… **NodePort with External Traffic Policy** - Preserves IPv6 source IP - βœ… **ConfigMap-based Content Management** - Dynamic updates - βœ… **Production nginx Configuration** - Dual-stack (IPv4/IPv6) support - βœ… **Resource Management** - CPU/memory limits and health checks - βœ… **Security Comparison** - Understanding hostNetwork vs standard networking ## πŸ—οΈ Architecture This example uses **separate configuration files** for better organization and security: ### Component Overview ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Mycelium β”‚ β”‚ NodePort β”‚ β”‚ nginx Pod β”‚ β”‚ IPv6 Network │───▢│ Service │───▢│ (Isolated) β”‚ β”‚ :30090 β”‚ β”‚ :8080 β”‚ β”‚ :8080 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ConfigMaps β”‚ β”‚ β€’ HTML Content β”‚ β”‚ β€’ nginx Config β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### Network Flow (NodePort Pattern) ``` User with Mycelium ↓ http://[worker-node-mycelium-ipv6]:30091 ↓ Worker Node (kube-proxy forwards) ↓ NodePort 30091 β†’ Service port 8080 ↓ Kubernetes Service (load balances) ↓ Pod container port 8080 ↓ nginx β†’ HTML Content ``` ### 🚨 Critical: NodePort Access Pattern **With NodePort:** - Pods run in **isolated network** (no `hostNetwork`) - Pods do **NOT** have direct Mycelium IPv6 addresses - Access via **worker node's Mycelium IPv6** + NodePort - Service is accessible on **all worker nodes** at port 30091 - kube-proxy forwards traffic: `node:30091 β†’ service:8080 β†’ pod:8080` **Comparison:** - **hostNetwork (nginx-mycelium)**: Pod gets host's Mycelium IP β†’ Access: `http://[pod-ip]:8080` - **NodePort (nginx-nodeport)**: Pod isolated β†’ Access: `http://[node-ip]:30091` **Getting the right IPv6:** ```bash # Get worker node Mycelium IPv6 addresses kubectl get nodes -o wide # OR use the fetch-ip.sh script ../../scripts/fetch-ip.sh ``` ### Key Security Improvements - **Pod Isolation**: No `hostNetwork` access, pods run in isolated network namespace - **Standard Service Patterns**: Uses typical Kubernetes service discovery - **External Traffic Policy**: `Local` preserves IPv6 source IP for logging - **Resource Limits**: Prevents resource exhaustion attacks - **Health Checks**: Liveness and readiness probes for reliability ## πŸ“„ Configuration Files ### 1. nginx-nodeport-deployment.yaml **Secure pod deployment without hostNetwork:** ```yaml spec: hostNetwork: false # Key security improvement containers: - name: nginx image: nginx:alpine ports: - containerPort: 8080 # No hostPort needed resources: requests: memory: "64Mi" cpu: "100m" limits: memory: "128Mi" cpu: "200m" livenessProbe: httpGet: path: /health port: 8080 readinessProbe: httpGet: path: /health port: 8080 ``` **What it does:** - Creates 1 pod with nginx and custom website content - Uses **standard pod networking** (no direct host access) - Includes **resource limits** and **health checks** - Uses ConfigMaps for **dynamic content management** - **Dual-stack nginx** (IPv4 + IPv6) configuration ### 2. nginx-nodeport-service.yaml **NodePort service with IPv6 source IP preservation:** ```yaml spec: type: NodePort # ← Service type is NodePort externalTrafficPolicy: Local # Preserves IPv6 source IP ports: - port: 8080 targetPort: 8080 nodePort: 30091 # ← Explicitly set to 30091 (avoiding conflict with nginx-mycelium's 30090) protocol: TCP ``` **What it does:** - Exposes nginx on **NodePort 30091** on all worker nodes - **Preserves IPv6 source IP** for logging and security - Uses **standard Kubernetes service** patterns (not LoadBalancer) - Provides **load balancing** across pod replicas (when scaled) - Access via: `http://[worker-node-mycelium-ipv6]:30091/` **NodePort Range:** Kubernetes NodePorts use range 30000-32767 by default ### 3. nginx-nodeport-configmaps.yaml **Content and nginx configuration:** **HTML Content:** Professional website with NodePort security branding **nginx Configuration:** Dual-stack (IPv4/IPv6) with health endpoint ```nginx server { listen 8080; listen [::]:8080 ipv6only=on; # IPv6 support server_name _; location / { root /usr/share/nginx/html; index index.html; } location /health { access_log off; return 200 "healthy\n"; } } ``` ## πŸ” Verification and Testing ### Check pod status ```bash kubectl get pods -l app=nginx-nodeport kubectl describe pod -l app=nginx-nodeport ``` ### Check service configuration ```bash kubectl get svc nginx-nodeport-service -o yaml kubectl get endpoints nginx-nodeport-service ``` ### Test nginx configuration ```bash POD_NAME=$(kubectl get pods -l app=nginx-nodeport -o name | head -1) kubectl exec $POD_NAME -- nginx -t kubectl exec $POD_NAME -- nginx -s reload ``` ### Test health endpoint ```bash POD_NAME=$(kubectl get pods -l app=nginx-nodeport -o name | head -1) kubectl exec $POD_NAME -- curl -s http://localhost:8080/health ``` ### Test website content ```bash # Get node IPv6 address NODE_IPV6=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}') # Test from outside the cluster curl -6 "http://[$NODE_IPV6]:30091/" curl -6 "http://[$NODE_IPV6]:30091/health" ``` ### Verify ConfigMaps are mounted ```bash POD_NAME=$(kubectl get pods -l app=nginx-nodeport -o name | head -1) kubectl exec $POD_NAME -- ls -la /usr/share/nginx/html/ kubectl exec $POD_NAME -- cat /usr/share/nginx/html/index.html | head -10 ``` ## πŸ”„ Updating Content ### Update website content ```bash # Create new HTML file cat > new-index.html << 'EOF' Updated Site

Content Updated!

New content deployed at $(date)

EOF # Update ConfigMap kubectl create configmap nginx-nodeport-content \ --from-file=index.html=new-index.html \ --dry-run=client -o yaml | kubectl apply -f - # Reload nginx to pick up changes POD_NAME=$(kubectl get pods -l app=nginx-nodeport -o name | head -1) kubectl exec $POD_NAME -- nginx -s reload echo "βœ… Content updated! Access at: http://[$NODE_IPV6]:30091" ``` ### Update nginx configuration ```bash # Create custom nginx config cat > custom-nginx.conf << 'EOF' server { listen 8080; listen [::]:8080 ipv6only=on; server_name my-site.com; # Custom logging access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ =404; } location /health { access_log off; return 200 "healthy\n"; } } EOF # Update ConfigMap kubectl create configmap nginx-nodeport-nginx-config \ --from-file=default.conf=custom-nginx.conf \ --dry-run=client -o yaml | kubectl apply -f - # Reload nginx POD_NAME=$(kubectl get pods -l app=nginx-nodeport -o name | head -1) kubectl exec $POD_NAME -- nginx -s reload ``` ## πŸ” Troubleshooting ### Pod won't start ```bash # Check pod status and events kubectl describe pod -l app=nginx-nodeport # Check pod logs kubectl logs -f deployment/nginx-nodeport # Check resource availability kubectl top nodes kubectl describe nodes ``` ### Service not accessible ```bash # Verify service exists and has endpoints kubectl get svc nginx-nodeport-service kubectl get endpoints nginx-nodeport-service # Check if pod is ready kubectl get pods -l app=nginx-nodeport -o wide # Verify NodePort is open netstat -tulpn | grep 30091 ``` ### IPv6 connectivity issues ```bash # Test IPv6 on the node ping6 -c 3 $NODE_IPV6 # Check nginx is listening on IPv6 POD_NAME=$(kubectl get pods -l app=nginx-nodeport -o name | head -1) kubectl exec $POD_NAME -- netstat -tuln | grep 8080 # Verify nginx configuration kubectl exec $POD_NAME -- cat /etc/nginx/conf.d/default.conf ``` ### Performance issues ```bash # Check resource usage kubectl top pods -l app=nginx-nodeport # Check nginx status and connections POD_NAME=$(kubectl get pods -l app=nginx-nodeport -o name | head -1) kubectl exec $POD_NAME -- ps aux | grep nginx kubectl exec $POD_NAME -- netstat -an | grep :8080 | wc -l ``` ## πŸ—‘οΈ Cleanup ```bash # Remove all resources kubectl delete -f nginx-nodeport-deployment.yaml -f nginx-nodeport-service.yaml # Remove ConfigMaps kubectl delete configmap nginx-nodeport-content nginx-nodeport-nginx-config # Verify cleanup kubectl get all -l app=nginx-nodeport # Should return nothing ``` ## πŸ“Š Nginx Deployment Variants Comparison ### Complete Overview: 4 Ways to Deploy Nginx on Mycelium Cloud | Feature | hostNetwork | NodePort | LoadBalancer | Ingress | |---------|-------------|----------|--------------|---------| | **Example** | nginx-mycelium | nginx-nodeport | (Future) | (Future) | | **Pod Network** | ❌ Host | βœ… Isolated | βœ… Isolated | βœ… Isolated | | **Security** | ⚠️ Low | βœ… Medium | βœ… Medium | βœ… High | | **Access Pattern** | `[pod-ip]:8080` | `[node-ip]:30091` | `[lb-ip]:80` | `domain.com` | | **Port Range** | Any | 30000-32767 | 80, 443 | 80, 443 | | **Mycelium Access** | Direct pod | Via node | Via LB | Via ingress | | **Use Case** | Demo/POC | Testing/Dev | Production | Web apps | | **Scalability** | ❌ Limited | βœ… Good | βœ… Excellent | βœ… Excellent | | **Load Balancing** | Manual | K8s Service | Cloud LB | Ingress controller | | **SSL/TLS** | Manual | Manual | Possible | Native | | **DNS Support** | No | No | Possible | Yes | | **Production Ready** | ⚠️ No | βœ… Yes | βœ… Yes | βœ… Yes | ### Key Differences: hostNetwork vs NodePort | Feature | hostNetwork (nginx-mycelium) | NodePort (nginx-nodeport) | |---------|------------------------------|---------------------------| | **Security** | ⚠️ Direct host access | βœ… Isolated pod network | | **Network Isolation** | ❌ Uses host interfaces | βœ… Pod namespace isolation | | **Port Conflicts** | ❌ Limited by host ports | βœ… No port conflicts | | **Debugging** | πŸ”„ Host-level tools | βœ… Standard K8s patterns | | **Monitoring** | πŸ”„ Host monitoring | βœ… Pod-level monitoring | | **Scalability** | ❌ Single instance per node | βœ… Multiple replicas | | **Production Ready** | ⚠️ Demo/POC only | βœ… Production patterns | | **Access URL** | `http://[pod-mycelium-ip]:8080` | `http://[node-mycelium-ip]:30091` | | **Port Used** | 8080 (+ NodePort 30090) | NodePort 30091 | ## πŸ“ˆ Scaling and High Availability ### Scale to multiple replicas ```bash # Scale deployment kubectl scale deployment nginx-nodeport --replicas=3 # Verify scaling kubectl get pods -l app=nginx-nodeport # Check load balancing NODE_IPV6=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}') for i in {1..5}; do curl -6 "http://[$NODE_IPV6]:30091/" | grep -o "nginx-nodeport-[a-z0-9]*-[a-z0-9]*" | head -1 done ``` ### Add resource limits for better performance ```yaml # Update deployment with enhanced resources resources: requests: memory: "128Mi" cpu: "200m" limits: memory: "256Mi" cpu: "500m" ``` ## 🎯 Best Practices 1. **Security First**: Always prefer standard pod networking over hostNetwork 2. **Resource Management**: Set appropriate requests and limits 3. **Health Checks**: Use liveness and readiness probes 4. **Monitoring**: Implement proper logging and metrics collection 5. **Updates**: Use rolling updates for zero-downtime deployments 6. **Configuration**: Store configuration in ConfigMaps for flexibility ## πŸ”„ Complete NodePort Flow Explained ### Understanding the Full Request Path ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Step 1: User with Mycelium Network β”‚ β”‚ β€’ Has Mycelium client running β”‚ β”‚ β€’ Can reach Mycelium IPv6 addresses globally β”‚ β”‚ β€’ Accesses: http://[worker-node-mycelium-ipv6]:30091 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Step 2: Mycelium Network Routes to Worker Node β”‚ β”‚ β€’ Peer-to-peer IPv6 routing β”‚ β”‚ β€’ No traditional DNS needed β”‚ β”‚ β€’ Direct encrypted connection β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Step 3: Worker Node Receives Request on Port 30091 β”‚ β”‚ β€’ kube-proxy listens on NodePort 30091 β”‚ β”‚ β€’ Forwards to Service cluster IP β”‚ β”‚ β€’ Preserves source IPv6 (externalTrafficPolicy: Local) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Step 4: Kubernetes Service Load Balances β”‚ β”‚ β€’ Service receives on port 8080 β”‚ β”‚ β€’ Selects backend pod (app=nginx-nodeport) β”‚ β”‚ β€’ Routes to targetPort 8080 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Step 5: nginx Pod Processes Request β”‚ β”‚ β€’ Pod in isolated network namespace β”‚ β”‚ β€’ nginx listens on container port 8080 β”‚ β”‚ β€’ Serves HTML from ConfigMap β”‚ β”‚ β€’ Returns response β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Step 6: Response Returns to User β”‚ β”‚ β€’ Same path in reverse β”‚ β”‚ β€’ User sees website in browser β”‚ β”‚ β€’ Access logs show original IPv6 (source IP preserved) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### Why NodePort is Better for Production **Security Benefits:** 1. Pods cannot access host network interfaces 2. Network policies can restrict pod-to-pod traffic 3. Resource limits prevent resource exhaustion 4. Health checks ensure reliability **Operational Benefits:** 1. Standard Kubernetes debugging tools work 2. Can scale horizontally (multiple replicas) 3. Service provides automatic load balancing 4. Compatible with monitoring stacks (Prometheus, etc.) 5. Can evolve to LoadBalancer or Ingress later **Mycelium Integration:** - Worker nodes have Mycelium IPv6 addresses - NodePort makes service accessible via these IPs - No need for traditional cloud load balancers - Perfect for decentralized web hosting ## οΏ½ Learning Outcomes After completing this example, you understand: - **NodePort Services** - Kubernetes service exposure patterns - **Network Security** - Pod isolation vs hostNetwork trade-offs - **Production Patterns** - Resource management and health checks - **IPv6 Networking** - Dual-stack nginx configuration - **ConfigMap Management** - Dynamic content and configuration updates - **Service Discovery** - Kubernetes service networking - **Load Balancing** - Service-level load distribution ## πŸš€ Next Steps - **Multi-Replica Deployment**: Scale to 3+ replicas for high availability - **LoadBalancer Service**: Move to cloud LoadBalancer for production - **Ingress Controller**: Implement advanced routing and SSL termination - **Monitoring**: Add Prometheus metrics and Grafana dashboards - **SSL/TLS**: Implement HTTPS with Let's Encrypt certificates --- **Success Criteria**: You'll know everything is working when: - βœ… `kubectl get pods` shows nginx-nodeport pod in "Running" status - βœ… `kubectl get svc` shows nginx-nodeport-service with NodePort 30091 - βœ… `curl -6 "http://[$NODE_IPV6]:30091"` returns your secure website - βœ… Website displays "NODEPORT SECURE" and "ENHANCED SECURITY" badges - βœ… `kubectl logs deployment/nginx-nodeport` shows nginx access logs **Access URL**: `http://[NODE-IPV6]:30091` (replace NODE-IPV6 with your node's IPv6 address)