docs: Update roadmap and implementation plan to mark nginx-nodeport as completed
This commit is contained in:
@@ -6,7 +6,7 @@ This document outlines the complete design and implementation plan for creating
|
|||||||
|
|
||||||
## 🎯 Objectives
|
## 🎯 Objectives
|
||||||
|
|
||||||
1. **Create nginx-nodeport/** - Standard NodePort service approach
|
1. **Create nginx-nodeport/** - Standard NodePort service approach ✅ **COMPLETED**
|
||||||
2. **Create nginx-load-balancer/** - LoadBalancer service approach
|
2. **Create nginx-load-balancer/** - LoadBalancer service approach
|
||||||
3. **Create nginx-ingress/** - Ingress controller approach
|
3. **Create nginx-ingress/** - Ingress controller approach
|
||||||
4. **Maintain nginx-mycelium/** - Original hostNetwork approach
|
4. **Maintain nginx-mycelium/** - Original hostNetwork approach
|
||||||
@@ -390,10 +390,17 @@ nginx-ingress/
|
|||||||
|
|
||||||
## 📋 Next Actions
|
## 📋 Next Actions
|
||||||
|
|
||||||
### Immediate (This Week)
|
### Immediate (This Week) ✅ COMPLETED
|
||||||
1. **Implement nginx-nodeport/** - Security improvement
|
1. **✅ Implement nginx-nodeport/** - Security improvement
|
||||||
2. **Deploy and test** on clean Mycelium cluster
|
- ✅ Standard NodePort service approach with IPv6 support
|
||||||
3. **Document results** and validate approach
|
- ✅ Worker node preferences for production deployments
|
||||||
|
- ✅ Multi-replica scaling with proper content management
|
||||||
|
- ✅ Network debugging tools and comprehensive documentation
|
||||||
|
2. **✅ Deploy and test** on clean Mycelium cluster
|
||||||
|
3. **✅ Document results** and validate approach
|
||||||
|
- ✅ Fixed scaling issues and added debugging capabilities
|
||||||
|
- ✅ Created production-ready deployment patterns
|
||||||
|
- ✅ Updated roadmap and implementation plans
|
||||||
|
|
||||||
### Short-term (Next Sprint)
|
### Short-term (Next Sprint)
|
||||||
1. **Implement nginx-load-balancer/** - Production readiness
|
1. **Implement nginx-load-balancer/** - Production readiness
|
||||||
|
|||||||
@@ -41,44 +41,44 @@ Comprehensive progression of Kubernetes examples designed to teach MyceliumCloud
|
|||||||
- **Template**: Same efficient pattern with `redis-cache.md` + `redis-cache-deployment.yaml` + `redis-cache-service.yaml` + `web-interface.py`
|
- **Template**: Same efficient pattern with `redis-cache.md` + `redis-cache-deployment.yaml` + `redis-cache-service.yaml` + `web-interface.py`
|
||||||
- **Key Concepts**: Redis deployment, data persistence, cache strategies, web interface
|
- **Key Concepts**: Redis deployment, data persistence, cache strategies, web interface
|
||||||
|
|
||||||
|
#### 6. Nginx NodePort Website ✅
|
||||||
|
- **Difficulty**: ⭐⭐ Medium
|
||||||
|
- **Status**: ✅ **COMPLETED**
|
||||||
|
- **Learning Focus**: Standard Kubernetes NodePort services, multi-replica scaling, worker node preferences
|
||||||
|
- **Template**: Enhanced pattern with `nginx-nodeport.md` + `nginx-nodeport-deployment.yaml` + `nginx-nodeport-service.yaml` + `nginx-nodeport-configmaps.yaml` + supporting scripts (`update-content-single.sh`, `update-content-many.sh`, `debug-networking.sh`)
|
||||||
|
- **Key Concepts**: NodePort services, IPv6 global access, multi-replica scaling, worker-only deployments, network debugging, production-ready scaling
|
||||||
|
|
||||||
### Planned Examples (Future)
|
### Planned Examples (Future)
|
||||||
|
|
||||||
#### 6. PostgreSQL Database
|
#### 7. PostgreSQL Database
|
||||||
- **Difficulty**: ⭐⭐ Medium
|
- **Difficulty**: ⭐⭐ Medium
|
||||||
- **Status**: 📋 Planned
|
- **Status**: 📋 Planned
|
||||||
- **Learning Focus**: Stateful applications, database deployment
|
- **Learning Focus**: Stateful applications, database deployment
|
||||||
- **Template**: Same efficient pattern
|
- **Template**: Same efficient pattern
|
||||||
- **Key Concepts**: Persistent volumes, databases, data persistence
|
- **Key Concepts**: Persistent volumes, databases, data persistence
|
||||||
|
|
||||||
#### 6. PostgreSQL Database
|
#### 8. WordPress
|
||||||
- **Difficulty**: ⭐⭐ Medium
|
|
||||||
- **Status**: 📋 Planned
|
|
||||||
- **Learning Focus**: Stateful applications, database deployment
|
|
||||||
- **Template**: Same efficient pattern
|
|
||||||
- **Key Concepts**: Persistent volumes, databases, data persistence
|
|
||||||
|
|
||||||
#### 7. WordPress
|
|
||||||
- **Difficulty**: ⭐⭐⭐ Hard
|
- **Difficulty**: ⭐⭐⭐ Hard
|
||||||
- **Status**: 📋 Planned
|
- **Status**: 📋 Planned
|
||||||
- **Learning Focus**: Multi-container applications, CMS deployment
|
- **Learning Focus**: Multi-container applications, CMS deployment
|
||||||
- **Template**: Same efficient pattern
|
- **Template**: Same efficient pattern
|
||||||
- **Key Concepts**: Multi-container apps, database integration, CMS deployment
|
- **Key Concepts**: Multi-container apps, database integration, CMS deployment
|
||||||
|
|
||||||
#### 8. Node.js API
|
#### 9. Node.js API
|
||||||
- **Difficulty**: ⭐⭐⭐ Hard
|
- **Difficulty**: ⭐⭐⭐ Hard
|
||||||
- **Status**: 📋 Planned
|
- **Status**: 📋 Planned
|
||||||
- **Learning Focus**: Modern web development, API services
|
- **Learning Focus**: Modern web development, API services
|
||||||
- **Template**: Same efficient pattern
|
- **Template**: Same efficient pattern
|
||||||
- **Key Concepts**: JavaScript/Node.js, API development, modern frameworks
|
- **Key Concepts**: JavaScript/Node.js, API development, modern frameworks
|
||||||
|
|
||||||
#### 9. Jenkins CI/CD
|
#### 10. Jenkins CI/CD
|
||||||
- **Difficulty**: ⭐⭐⭐ Hard
|
- **Difficulty**: ⭐⭐⭐ Hard
|
||||||
- **Status**: 📋 Planned
|
- **Status**: 📋 Planned
|
||||||
- **Learning Focus**: Infrastructure automation, CI/CD pipelines
|
- **Learning Focus**: Infrastructure automation, CI/CD pipelines
|
||||||
- **Template**: Same efficient pattern
|
- **Template**: Same efficient pattern
|
||||||
- **Key Concepts**: DevOps tools, automation, infrastructure as code
|
- **Key Concepts**: DevOps tools, automation, infrastructure as code
|
||||||
|
|
||||||
#### 10. Nextcloud
|
#### 11. Nextcloud
|
||||||
- **Difficulty**: ⭐⭐⭐ Very Hard
|
- **Difficulty**: ⭐⭐⭐ Very Hard
|
||||||
- **Status**: 📋 Planned
|
- **Status**: 📋 Planned
|
||||||
- **Learning Focus**: Enterprise applications, file sharing, high availability
|
- **Learning Focus**: Enterprise applications, file sharing, high availability
|
||||||
@@ -103,6 +103,7 @@ Comprehensive progression of Kubernetes examples designed to teach MyceliumCloud
|
|||||||
**Focus**: Advanced networking and data services
|
**Focus**: Advanced networking and data services
|
||||||
- Nginx Mycelium IPv6 Hosting: Peer-to-peer IPv6 web hosting
|
- Nginx Mycelium IPv6 Hosting: Peer-to-peer IPv6 web hosting
|
||||||
- Redis Cache: In-memory data and caching
|
- Redis Cache: In-memory data and caching
|
||||||
|
- Nginx NodePort Website: Standard K8s NodePort services
|
||||||
- PostgreSQL Database: Persistent data
|
- PostgreSQL Database: Persistent data
|
||||||
|
|
||||||
**Skills Taught**:
|
**Skills Taught**:
|
||||||
@@ -112,6 +113,8 @@ Comprehensive progression of Kubernetes examples designed to teach MyceliumCloud
|
|||||||
- Database deployment patterns
|
- Database deployment patterns
|
||||||
- Service discovery
|
- Service discovery
|
||||||
- Global accessibility via IPv6
|
- Global accessibility via IPv6
|
||||||
|
- Multi-replica scaling
|
||||||
|
- Production-ready deployments
|
||||||
|
|
||||||
### Hard Level (⭐⭐⭐)
|
### Hard Level (⭐⭐⭐)
|
||||||
**Focus**: Complex applications and enterprise patterns
|
**Focus**: Complex applications and enterprise patterns
|
||||||
@@ -173,18 +176,19 @@ Each example includes:
|
|||||||
|
|
||||||
## 🎓 Skills Matrix
|
## 🎓 Skills Matrix
|
||||||
|
|
||||||
| Example | Containers | Persistence | Multi-Container | Load Balancing | Databases | APIs | DevOps | Enterprise | IPv6 | Peer-to-Peer |
|
| Example | Containers | Persistence | Multi-Container | Load Balancing | Databases | APIs | DevOps | Enterprise | IPv6 | Peer-to-Peer | NodePort | Multi-Replica |
|
||||||
|---------|------------|-------------|-----------------|----------------|-----------|------|--------|------------|-----|--------------|
|
|---------|------------|-------------|-----------------|----------------|-----------|------|--------|------------|-----|--------------|----------|---------------|
|
||||||
| Hello World | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
| Hello World | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||||
| Nginx Static | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
| Nginx Static | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||||
| Python Flask | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
|
| Python Flask | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||||
| Nginx Mycelium IPv6 | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
|
| Nginx Mycelium IPv6 | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
|
||||||
| Redis Cache | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
| Redis Cache | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||||
| PostgreSQL | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
| Nginx NodePort Website | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ✅ |
|
||||||
| WordPress | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
| PostgreSQL | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||||
| Node.js API | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
|
| WordPress | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||||
| Jenkins CI/CD | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
|
| Node.js API | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||||
| Nextcloud | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
|
| Jenkins CI/CD | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||||
|
| Nextcloud | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
|
||||||
|
|
||||||
## 🚀 Current Status & Next Steps
|
## 🚀 Current Status & Next Steps
|
||||||
|
|
||||||
@@ -194,10 +198,11 @@ Each example includes:
|
|||||||
- **Python Flask API** - Web service development (Completed)
|
- **Python Flask API** - Web service development (Completed)
|
||||||
- **Nginx Mycelium IPv6** - Peer-to-peer IPv6 web hosting (Completed)
|
- **Nginx Mycelium IPv6** - Peer-to-peer IPv6 web hosting (Completed)
|
||||||
- **Redis Cache** - Data caching services (Completed)
|
- **Redis Cache** - Data caching services (Completed)
|
||||||
|
- **Nginx NodePort Website** - Standard K8s NodePort services with multi-replica scaling (Completed)
|
||||||
|
|
||||||
### Next Planned Example
|
### Next Planned Example
|
||||||
1. **PostgreSQL Database** - Stateful database deployment
|
1. **PostgreSQL Database** - Stateful database deployment
|
||||||
- Copy nginx-mycelium template structure
|
- Copy nginx-nodeport template structure
|
||||||
- Adapt for PostgreSQL database needs
|
- Adapt for PostgreSQL database needs
|
||||||
- Include persistent volume management
|
- Include persistent volume management
|
||||||
- Test database connectivity and data persistence
|
- Test database connectivity and data persistence
|
||||||
@@ -216,6 +221,12 @@ Each example includes:
|
|||||||
- All examples must be **copy-paste ready**
|
- All examples must be **copy-paste ready**
|
||||||
- All examples must include **cleanup instructions**
|
- All examples must include **cleanup instructions**
|
||||||
|
|
||||||
|
### Special Focus Areas
|
||||||
|
- **IPv6 Networking**: Mycelium's unique capability for global IPv6 access
|
||||||
|
- **Multi-Replica Scaling**: Production-ready scaling patterns
|
||||||
|
- **Worker Node Preferences**: Best practices for separating control plane and worker workloads
|
||||||
|
- **Network Debugging**: Tools and techniques for troubleshooting connectivity issues
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Goal**: Provide MyceliumCloud users with a complete learning path from basic Kubernetes deployment to enterprise application management, using proven patterns and consistent documentation.
|
**Goal**: Provide MyceliumCloud users with a complete learning path from basic Kubernetes deployment to enterprise application management, using proven patterns and consistent documentation, with special emphasis on IPv6 networking and production-ready scaling.
|
||||||
@@ -1,216 +0,0 @@
|
|||||||
# nginx-nodeport - Mycelium Cloud NodePort Website Example
|
|
||||||
|
|
||||||
Complete, production-ready example for deploying a secure, globally accessible website on Mycelium Cloud using **NodePort** services.
|
|
||||||
|
|
||||||
## 🚀 Quick Start (One Command!)
|
|
||||||
|
|
||||||
**Start here if you want EVERYTHING done automatically:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd myceliumcloud-examples/examples/nginx-nodeport
|
|
||||||
./deploy-and-test.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
That's it! This script will:
|
|
||||||
1. ✅ Deploy all resources (ConfigMaps, Deployment, Service)
|
|
||||||
2. ✅ Wait for pods to be ready
|
|
||||||
3. ✅ Verify service configuration
|
|
||||||
4. ✅ Update website content with current node information
|
|
||||||
5. ✅ Apply changes
|
|
||||||
6. ✅ Run comprehensive tests
|
|
||||||
7. ✅ Show you the access URL
|
|
||||||
|
|
||||||
**Output example:**
|
|
||||||
```
|
|
||||||
🎉 Deploy and Test Complete!
|
|
||||||
==================================
|
|
||||||
|
|
||||||
🌐 Access Information:
|
|
||||||
• URL: http://[552:5984:2d97:72dc:ff0f:39ef:6ec:a48c]:30091
|
|
||||||
• Node: kc22haven612worker1
|
|
||||||
|
|
||||||
To access from a machine with Mycelium installed:
|
|
||||||
curl -6 "http://[552:5984:2d97:72dc:ff0f:39ef:6ec:a48c]:30091/"
|
|
||||||
Or open in browser:
|
|
||||||
http://[552:5984:2d97:72dc:ff0f:39ef:6ec:a48c]:30091
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 Available Scripts
|
|
||||||
|
|
||||||
### 1. `deploy-and-test.sh` - **RECOMMENDED** ⭐
|
|
||||||
**The ONE script to do everything from scratch**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./deploy-and-test.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Does everything: deploy, test, configure, and show results.
|
|
||||||
|
|
||||||
### 2. `update-content.sh` - Content Update
|
|
||||||
**Updates website content with current cluster state**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./update-content.sh
|
|
||||||
kubectl rollout restart deployment/nginx-nodeport
|
|
||||||
```
|
|
||||||
|
|
||||||
Updates the ConfigMap and restarts pods to apply changes.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 Manual Deployment (If You Prefer)
|
|
||||||
|
|
||||||
If you want to do it step-by-step yourself:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Deploy resources
|
|
||||||
kubectl apply -f nginx-nodeport-configmaps.yaml
|
|
||||||
kubectl apply -f nginx-nodeport-deployment.yaml
|
|
||||||
kubectl apply -f nginx-nodeport-service.yaml
|
|
||||||
|
|
||||||
# 2. Wait for ready
|
|
||||||
kubectl wait --for=condition=ready pod -l app=nginx-nodeport --timeout=60s
|
|
||||||
|
|
||||||
# 3. Update content
|
|
||||||
./update-content.sh
|
|
||||||
kubectl rollout restart deployment/nginx-nodeport
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 What This Example Teaches
|
|
||||||
|
|
||||||
- **NodePort Services** - Standard Kubernetes service exposure
|
|
||||||
- **IPv6 Support** - Critical dual-stack configuration for Mycelium
|
|
||||||
- **Pod Isolation** - Security without hostNetwork
|
|
||||||
- **externalTrafficPolicy: Local** - Preserves source IP
|
|
||||||
- **Mycelium Integration** - IPv6 address discovery and access
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
User (with Mycelium)
|
|
||||||
↓
|
|
||||||
http://[worker-node-mycelium-ipv6]:30091
|
|
||||||
↓
|
|
||||||
kube-proxy (dual-stack enabled)
|
|
||||||
↓
|
|
||||||
Kubernetes Service (IPv4 + IPv6)
|
|
||||||
↓
|
|
||||||
Pod (container port 8080)
|
|
||||||
↓
|
|
||||||
nginx → HTML
|
|
||||||
```
|
|
||||||
|
|
||||||
**Key Points:**
|
|
||||||
- Service type: **NodePort** (not LoadBalancer)
|
|
||||||
- IP families: **Dual-stack (IPv4 + IPv6)** ⭐ Critical
|
|
||||||
- Pod network: **Isolated** (no hostNetwork)
|
|
||||||
- Traffic policy: **Local** (preserves source IP)
|
|
||||||
- Port: **30091** (NodePort)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🌐 Access URLs
|
|
||||||
|
|
||||||
**Current deployment (1 pod replica):**
|
|
||||||
- **Only accessible on the node where pod is running**
|
|
||||||
- Example: `http://[552:5984:2d97:72dc:ff0f:39ef:6ec:a48c]:30091`
|
|
||||||
|
|
||||||
**To make accessible on all nodes:**
|
|
||||||
```bash
|
|
||||||
kubectl scale deployment nginx-nodeport --replicas=3
|
|
||||||
./update-content.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📁 Files in This Directory
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
- `nginx-nodeport-deployment.yaml` - Pod configuration
|
|
||||||
- `nginx-nodeport-service.yaml` - NodePort service (dual-stack)
|
|
||||||
- `nginx-nodeport-configmaps.yaml` - HTML content + nginx config
|
|
||||||
|
|
||||||
### Scripts
|
|
||||||
- `deploy-and-test.sh` - ⭐ **Main script** (deploy + test)
|
|
||||||
- `test-nodeport-ipv6.sh` - Testing and validation
|
|
||||||
- `update-content.sh` - Content updates
|
|
||||||
- `debug-nodeport.sh` - Diagnostics
|
|
||||||
|
|
||||||
### Documentation
|
|
||||||
- `nginx-nodeport.md` - Complete guide
|
|
||||||
- `IPV6_FIX.md` - Critical dual-stack configuration
|
|
||||||
- `TROUBLESHOOTING.md` - Common issues & solutions
|
|
||||||
- `compare-approaches.md` - Security comparison
|
|
||||||
- `FINAL_STATUS.md` - Complete implementation status
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ Success Indicators
|
|
||||||
|
|
||||||
**When working, you'll see:**
|
|
||||||
- ✅ Service type: `NodePort`
|
|
||||||
- ✅ NodePort: `30091`
|
|
||||||
- ✅ IP families: `["IPv4","IPv6"]`
|
|
||||||
- ✅ Pod status: `Running`
|
|
||||||
- ✅ Test output: `✅ External Mycelium IPv6 connectivity is working!`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚨 Prerequisites
|
|
||||||
|
|
||||||
1. **kubectl** installed and configured
|
|
||||||
2. **Mycelium Cloud cluster** with at least 1 worker node
|
|
||||||
3. **Mycelium installed** on your local machine (for testing)
|
|
||||||
4. **IPv6 connectivity** (Mycelium provides this)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🆘 Getting Help
|
|
||||||
|
|
||||||
**Common Issues:**
|
|
||||||
|
|
||||||
1. **"Failed to connect" error**
|
|
||||||
- Check if Mycelium is running on your local machine
|
|
||||||
- Verify IPv6 connectivity: `ping -6 [ipv6-address]`
|
|
||||||
|
|
||||||
2. **"External IPv6 connectivity test failed"**
|
|
||||||
- This is normal if you don't have Mycelium on your machine
|
|
||||||
- The service is still working from within the cluster
|
|
||||||
|
|
||||||
3. **Service only accessible on one node**
|
|
||||||
- This is CORRECT with `externalTrafficPolicy: Local` and 1 pod replica
|
|
||||||
- To make accessible on all nodes, scale to 3 replicas
|
|
||||||
|
|
||||||
**Troubleshooting:**
|
|
||||||
- Run: `./debug-nodeport.sh`
|
|
||||||
- Check logs: `kubectl logs -l app=nginx-nodeport --tail=50`
|
|
||||||
- Check service: `kubectl describe svc nginx-nodeport-service`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 Next Steps
|
|
||||||
|
|
||||||
1. **Test scaling:**
|
|
||||||
```bash
|
|
||||||
kubectl scale deployment nginx-nodeport --replicas=3
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Try other nginx variants:**
|
|
||||||
- [`../nginx-mycelium/`](../nginx-mycelium/) - hostNetwork approach
|
|
||||||
- [`../nginx-static/`](../nginx-static/) - Simple static site
|
|
||||||
- LoadBalancer and Ingress variants (coming soon)
|
|
||||||
|
|
||||||
## 🎉 Success!
|
|
||||||
|
|
||||||
Once deployed and tested, you'll have a **fully functional website accessible via Mycelium IPv6** with:
|
|
||||||
- ✅ Production-ready security (pod isolation)
|
|
||||||
- ✅ Standard Kubernetes patterns
|
|
||||||
- ✅ Dual-stack IPv4/IPv6 support
|
|
||||||
- ✅ Comprehensive testing and monitoring
|
|
||||||
|
|
||||||
**Happy deploying! 🚀**
|
|
||||||
71
examples/nginx-nodeport/debug-networking.sh
Executable file
71
examples/nginx-nodeport/debug-networking.sh
Executable file
@@ -0,0 +1,71 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Diagnostic script to debug NodePort networking issues
|
||||||
|
# This helps identify why some URLs work and others don't
|
||||||
|
|
||||||
|
echo "🔍 NodePort Networking Diagnostics"
|
||||||
|
echo "=================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check pod locations
|
||||||
|
echo "📍 Current Pod Locations:"
|
||||||
|
kubectl get pods -l app=nginx-nodeport -o wide
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check node information
|
||||||
|
echo "🌐 Node Information:"
|
||||||
|
kubectl get nodes -o wide
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check service status
|
||||||
|
echo "🔧 Service Status:"
|
||||||
|
kubectl get svc nginx-nodeport-service
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test connectivity to each node
|
||||||
|
echo "🧪 Connectivity Tests:"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
PODS=$(kubectl get pods -l app=nginx-nodeport -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.nodeName}{"\n"}{end}')
|
||||||
|
|
||||||
|
while IFS=$'\t' read -r pod_name node_name; do
|
||||||
|
echo "Testing pod: $pod_name on node: $node_name"
|
||||||
|
|
||||||
|
# Get IPv6 for this specific node
|
||||||
|
IPV6=$(kubectl get node "$node_name" -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)
|
||||||
|
|
||||||
|
if [ ! -z "$IPV6" ]; then
|
||||||
|
echo " Node IPv6: $IPV6"
|
||||||
|
echo " Testing connectivity: curl -6 --connect-timeout 5 http://[$IPV6]:30091/health"
|
||||||
|
|
||||||
|
# Test HTTP connectivity
|
||||||
|
if curl -6 --connect-timeout 5 -s "http://[$IPV6]:30091/health" >/dev/null 2>&1; then
|
||||||
|
echo " ✅ HTTP connectivity: WORKING"
|
||||||
|
else
|
||||||
|
echo " ❌ HTTP connectivity: FAILED"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test ICMP connectivity
|
||||||
|
echo " Testing ping: ping -6 -c 2 -W 3 $IPV6"
|
||||||
|
if ping -6 -c 2 -W 3 "$IPV6" >/dev/null 2>&1; then
|
||||||
|
echo " ✅ ICMP connectivity: WORKING"
|
||||||
|
else
|
||||||
|
echo " ❌ ICMP connectivity: FAILED"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ❌ No IPv6 found for node: $node_name"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
done <<< "$PODS"
|
||||||
|
|
||||||
|
echo "📊 Summary:"
|
||||||
|
echo "This shows which nodes actually have pods and whether they're accessible"
|
||||||
|
echo ""
|
||||||
|
echo "If some URLs work and others don't, it means:"
|
||||||
|
echo " ✅ Working URLs: Nodes with good Mycelium connectivity"
|
||||||
|
echo " ❌ Failed URLs: Nodes with poor Mycelium connectivity or network issues"
|
||||||
|
echo ""
|
||||||
|
echo "To fix connectivity issues:"
|
||||||
|
echo " 1. Check Mycelium status on affected nodes"
|
||||||
|
echo " 2. Restart Mycelium on nodes with failed connectivity"
|
||||||
|
echo " 3. Scale to replicas only on nodes with good connectivity"
|
||||||
@@ -1,312 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Dynamic Mycelium IPv6 Address Discovery Script for Multi-Replica NodePort
|
|
||||||
# This script fetches Mycelium IPv6 addresses from ALL nodes where pods are running
|
|
||||||
# Works correctly with externalTrafficPolicy: Local and multiple replicas
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "🔍 Discovering Mycelium IPv6 addresses for ALL pod nodes..."
|
|
||||||
|
|
||||||
# Get ALL nginx-nodeport pods
|
|
||||||
POD_COUNT=$(kubectl get pods -l app=nginx-nodeport --no-headers | wc -l)
|
|
||||||
echo "Found $POD_COUNT pods running"
|
|
||||||
|
|
||||||
if [ "$POD_COUNT" -eq 0 ]; then
|
|
||||||
echo "❌ No nginx-nodeport pod found!"
|
|
||||||
echo "Please deploy the nginx-nodeport example first:"
|
|
||||||
echo " kubectl apply -f nginx-nodeport-deployment.yaml"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Collect all node information
|
|
||||||
declare -A NODE_IPV6_MAP
|
|
||||||
declare -a NODES_WITH_PODS
|
|
||||||
declare -a IPV6_ADDRESSES
|
|
||||||
|
|
||||||
echo "Collecting node information for all pods..."
|
|
||||||
|
|
||||||
# Read pod data into array first to avoid subshell issues
|
|
||||||
mapfile -t POD_DATA < <(kubectl get pods -l app=nginx-nodeport -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.nodeName}{"\n"}{end}')
|
|
||||||
|
|
||||||
for line in "${POD_DATA[@]}"; do
|
|
||||||
IFS=$'\t' read -r pod_name node_name <<< "$line"
|
|
||||||
if [ ! -z "$node_name" ] && [ "${NODE_IPV6_MAP[$node_name]+isset}" = "" ]; then
|
|
||||||
echo "Pod $pod_name is on node $node_name"
|
|
||||||
# Get IPv6 address for this node
|
|
||||||
IPV6=$(kubectl get node "$node_name" -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)
|
|
||||||
if [ ! -z "$IPV6" ]; then
|
|
||||||
NODE_IPV6_MAP[$node_name]=$IPV6
|
|
||||||
NODES_WITH_PODS+=("$node_name")
|
|
||||||
IPV6_ADDRESSES+=("$IPV6")
|
|
||||||
echo " ✅ Node $node_name has IPv6: $IPV6"
|
|
||||||
else
|
|
||||||
echo " ❌ No IPv6 found for node $node_name"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Build the IPv6 addresses string
|
|
||||||
IPV6_LIST=""
|
|
||||||
FIRST=true
|
|
||||||
for ipv6 in "${IPV6_ADDRESSES[@]}"; do
|
|
||||||
if [ "$FIRST" = true ]; then
|
|
||||||
IPV6_LIST="$ipv6"
|
|
||||||
FIRST=false
|
|
||||||
else
|
|
||||||
IPV6_LIST="$IPV6_LIST $ipv6"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ ${#IPV6_ADDRESSES[@]} -eq 0 ]; then
|
|
||||||
echo "❌ No IPv6 addresses found for any pod nodes!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "✅ Found ${#IPV6_ADDRESSES[@]} accessible nodes with pods:"
|
|
||||||
for i in "${!NODES_WITH_PODS[@]}"; do
|
|
||||||
echo " ${NODES_WITH_PODS[$i]}: ${IPV6_ADDRESSES[$i]}"
|
|
||||||
done
|
|
||||||
|
|
||||||
# Generate HTML content with all accessible addresses
|
|
||||||
cat > /tmp/index.html << 'HTML_EOF'
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Mycelium Cloud - Nginx NodePort Website</title>
|
|
||||||
<meta http-equiv="refresh" content="30">
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
color: white;
|
|
||||||
min-height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.container {
|
|
||||||
text-align: center;
|
|
||||||
max-width: 900px;
|
|
||||||
padding: 2rem;
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
border-radius: 20px;
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
font-size: 3rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
|
|
||||||
}
|
|
||||||
.subtitle {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
opacity: 0.9;
|
|
||||||
}
|
|
||||||
.ipv6-info {
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 10px;
|
|
||||||
margin: 1rem 0;
|
|
||||||
font-family: 'Courier New', monospace;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
.status {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 0.5rem 1rem;
|
|
||||||
background: #4CAF50;
|
|
||||||
border-radius: 25px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0.5rem;
|
|
||||||
}
|
|
||||||
.status.nodeport {
|
|
||||||
background: #2196F3;
|
|
||||||
}
|
|
||||||
.timestamp {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
opacity: 0.7;
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
.features {
|
|
||||||
text-align: left;
|
|
||||||
margin: 2rem 0;
|
|
||||||
}
|
|
||||||
.feature {
|
|
||||||
margin: 0.5rem 0;
|
|
||||||
padding: 0.5rem;
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
.security-badge {
|
|
||||||
background: #FF9800;
|
|
||||||
color: white;
|
|
||||||
padding: 0.5rem 1rem;
|
|
||||||
border-radius: 15px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 1rem;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
.urls {
|
|
||||||
background: rgba(255, 255, 255, 0.15);
|
|
||||||
padding: 1.5rem;
|
|
||||||
border-radius: 10px;
|
|
||||||
margin: 1.5rem 0;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
.urls h3 {
|
|
||||||
margin-top: 0;
|
|
||||||
color: #FFD700;
|
|
||||||
}
|
|
||||||
.urls ul {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.urls li {
|
|
||||||
margin: 1rem 0;
|
|
||||||
font-family: 'Courier New', monospace;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
padding: 0.8rem;
|
|
||||||
border-radius: 6px;
|
|
||||||
}
|
|
||||||
.urls code {
|
|
||||||
background: rgba(0, 0, 0, 0.3);
|
|
||||||
padding: 0.3rem 0.6rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
.working {
|
|
||||||
color: #4CAF50;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.node-info {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
opacity: 0.8;
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script>
|
|
||||||
function updateTimestamp() {
|
|
||||||
const now = new Date();
|
|
||||||
document.getElementById('timestamp').textContent =
|
|
||||||
'Last updated: ' + now.toLocaleString();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getIPv6Address() {
|
|
||||||
// Extract IPv6 from the current connection
|
|
||||||
const ipv6Pattern = /\[([0-9a-f:]+)\]/;
|
|
||||||
const match = window.location.href.match(ipv6Pattern);
|
|
||||||
if (match) {
|
|
||||||
document.getElementById('current-ipv6').textContent = match[1];
|
|
||||||
} else {
|
|
||||||
document.getElementById('current-ipv6').textContent = 'Not accessed via IPv6';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onload = function() {
|
|
||||||
updateTimestamp();
|
|
||||||
getIPv6Address();
|
|
||||||
setInterval(updateTimestamp, 1000);
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<h1>🌐 Mycelium Cloud</h1>
|
|
||||||
<div class="subtitle">
|
|
||||||
Secure NodePort Website Hosting with IPv6!
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="status nodeport">
|
|
||||||
✅ NODEPORT SECURE
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="security-badge">
|
|
||||||
🔒 ENHANCED SECURITY
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="ipv6-info">
|
|
||||||
<strong>Connected via IPv6:</strong><br>
|
|
||||||
<span id="current-ipv6">Loading...</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="urls">
|
|
||||||
<h3>🌐 Access URLs (NodePort: 30091)</h3>
|
|
||||||
<p><strong>Your website is accessible via these Mycelium worker node IPv6 addresses:</strong></p>
|
|
||||||
<ul>
|
|
||||||
HTML_EOF
|
|
||||||
|
|
||||||
# Add all accessible IPv6 addresses to the HTML
|
|
||||||
for i in "${!IPV6_ADDRESSES[@]}"; do
|
|
||||||
ipv6="${IPV6_ADDRESSES[$i]}"
|
|
||||||
node="${NODES_WITH_PODS[$i]}"
|
|
||||||
echo " <li><code>http://[$ipv6]:30091</code> <span class=\"working\">✅ WORKING</span><div class=\"node-info\">Node: $node</div></li>" >> /tmp/index.html
|
|
||||||
done
|
|
||||||
|
|
||||||
cat >> /tmp/index.html << 'HTML_EOF'
|
|
||||||
</ul>
|
|
||||||
<div style="background: rgba(76, 175, 80, 0.2); padding: 1rem; border-radius: 8px; margin: 1rem 0; border-left: 4px solid #4CAF50;">
|
|
||||||
<strong>✅ Success:</strong> All <code>REPLICA_COUNT</code> replicas are accessible with <code>externalTrafficPolicy: Local</code><br>
|
|
||||||
Service is available on all <code>REPLICA_COUNT</code> nodes where pods are running.
|
|
||||||
</div>
|
|
||||||
<p><em>Anyone with Mycelium installed can access your website from any of these URLs from anywhere in the world!</em></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="features">
|
|
||||||
<h3>🚀 Key Features:</h3>
|
|
||||||
<div class="feature">🛡️ Enhanced security with network isolation</div>
|
|
||||||
<div class="feature">🌍 Peer-to-peer global access via NodePort</div>
|
|
||||||
<div class="feature">🔒 Standard Kubernetes service patterns</div>
|
|
||||||
<div class="feature">⚡ Clean pod networking without hostNetwork</div>
|
|
||||||
<div class="feature">🖥️ Multi-replica, multi-node Kubernetes cluster</div>
|
|
||||||
<div class="feature">🔄 Dynamic IPv6 discovery and routing</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="timestamp" id="timestamp">
|
|
||||||
Loading timestamp...
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="margin-top: 2rem; font-size: 0.8rem;">
|
|
||||||
Mycelium Cloud NodePort Demo<br>
|
|
||||||
Security-First IPv6 Website Hosting<br>
|
|
||||||
<strong>Auto-updated every 30 seconds</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
HTML_EOF
|
|
||||||
|
|
||||||
# Replace the replica count placeholder
|
|
||||||
sed -i "s/REPLICA_COUNT/${#IPV6_ADDRESSES[@]}/g" /tmp/index.html
|
|
||||||
|
|
||||||
echo "📝 Generated HTML content for ${#IPV6_ADDRESSES[@]} accessible nodes"
|
|
||||||
|
|
||||||
# Update the ConfigMap
|
|
||||||
echo "🔄 Updating ConfigMap..."
|
|
||||||
kubectl create configmap nginx-nodeport-content --from-file=index.html=/tmp/index.html --dry-run=client -o yaml | kubectl apply -f -
|
|
||||||
|
|
||||||
echo "✅ Successfully updated nginx-nodeport-content ConfigMap"
|
|
||||||
echo ""
|
|
||||||
echo "🔄 To apply changes to running pods, restart the deployment:"
|
|
||||||
echo " kubectl rollout restart deployment/nginx-nodeport"
|
|
||||||
echo ""
|
|
||||||
echo "🌐 Website will be accessible at ALL of these URLs:"
|
|
||||||
for i in "${!IPV6_ADDRESSES[@]}"; do
|
|
||||||
echo " http://[${IPV6_ADDRESSES[$i]}]:30091 (Node: ${NODES_WITH_PODS[$i]})"
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
echo "📊 Summary:"
|
|
||||||
echo " Total replicas: $POD_COUNT"
|
|
||||||
echo " Accessible nodes: ${#IPV6_ADDRESSES[@]}"
|
|
||||||
echo " All URLs working: ✅ YES"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Cleanup
|
|
||||||
rm -f /tmp/index.html
|
|
||||||
|
|
||||||
echo "✅ Multi-replica update complete!"
|
|
||||||
Reference in New Issue
Block a user