chore: Remove outdated documentation files from completed nginx-nodeport example
This commit is contained in:
@@ -1,283 +0,0 @@
|
|||||||
# ✅ nginx-nodeport Implementation - 100% COMPLETE & WORKING
|
|
||||||
|
|
||||||
## 🎉 Success Confirmation
|
|
||||||
|
|
||||||
**The nginx-nodeport example is now FULLY FUNCTIONAL and accessible via Mycelium IPv6!**
|
|
||||||
|
|
||||||
### Test Results
|
|
||||||
```bash
|
|
||||||
$ ./test-nodeport-ipv6.sh
|
|
||||||
✅ External Mycelium IPv6 connectivity is working!
|
|
||||||
ℹ️ Your website is accessible at: http://[552:5984:2d97:72dc:ff0f:39ef:6ec:a48c]:30091/
|
|
||||||
```
|
|
||||||
|
|
||||||
### Actual Access Logs
|
|
||||||
```
|
|
||||||
5ff:5a5c:2db7:2ae5:d1a3:a3a8:83de:4c2 - - [07/Nov/2025:01:58:39 +0000] "GET / HTTP/1.1" 200 6354 "-" "Mozilla/5.0..."
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔑 Critical Fix Applied
|
|
||||||
|
|
||||||
### The Problem
|
|
||||||
- Service was configured for **IPv4 ONLY**
|
|
||||||
- Mycelium uses **IPv6 addresses**
|
|
||||||
- Result: Ping worked, HTTP failed
|
|
||||||
|
|
||||||
### The Solution
|
|
||||||
Updated `nginx-nodeport-service.yaml`:
|
|
||||||
```yaml
|
|
||||||
spec:
|
|
||||||
type: NodePort
|
|
||||||
externalTrafficPolicy: Local
|
|
||||||
ipFamilies: # ← ADDED
|
|
||||||
- IPv4
|
|
||||||
- IPv6
|
|
||||||
ipFamilyPolicy: RequireDualStack # ← ADDED
|
|
||||||
```
|
|
||||||
|
|
||||||
**This is THE critical configuration for Mycelium Cloud NodePort deployments!**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Complete Implementation Summary
|
|
||||||
|
|
||||||
### Files Created/Modified
|
|
||||||
|
|
||||||
| File | Status | Purpose |
|
|
||||||
|------|--------|---------|
|
|
||||||
| `nginx-nodeport-service.yaml` | ✅ Fixed | NodePort + Dual-stack IPv4/IPv6 |
|
|
||||||
| `nginx-nodeport-deployment.yaml` | ✅ Verified | Pod with isolated network |
|
|
||||||
| `nginx-nodeport-configmaps.yaml` | ✅ Verified | HTML content + nginx config |
|
|
||||||
| `test-nodeport-ipv6.sh` | ✅ Enhanced | Comprehensive testing |
|
|
||||||
| `update-content.sh` | ✅ Created | Dynamic content updates |
|
|
||||||
| `debug-nodeport.sh` | ✅ Created | Connectivity diagnostics |
|
|
||||||
| `nginx-nodeport.md` | ✅ Updated | Complete documentation |
|
|
||||||
| `IPV6_FIX.md` | ✅ Created | Critical IPv6 fix guide |
|
|
||||||
| `TROUBLESHOOTING.md` | ✅ Created | Common issues & solutions |
|
|
||||||
| `compare-approaches.md` | ✅ Existing | Security comparison |
|
|
||||||
| `../nginx-variants.md` | ✅ Created | All 4 nginx variants guide |
|
|
||||||
|
|
||||||
### Key Configuration
|
|
||||||
|
|
||||||
**Service:**
|
|
||||||
- Type: NodePort ✅
|
|
||||||
- NodePort: 30091 ✅
|
|
||||||
- externalTrafficPolicy: Local ✅
|
|
||||||
- **ipFamilies: [IPv4, IPv6]** ⭐ Critical
|
|
||||||
- **ipFamilyPolicy: RequireDualStack** ⭐ Critical
|
|
||||||
|
|
||||||
**Pod:**
|
|
||||||
- hostNetwork: false (isolated) ✅
|
|
||||||
- Resource limits configured ✅
|
|
||||||
- Health probes active ✅
|
|
||||||
- ConfigMaps mounted ✅
|
|
||||||
|
|
||||||
**Access Pattern:**
|
|
||||||
```
|
|
||||||
User (with Mycelium)
|
|
||||||
↓
|
|
||||||
http://[worker-node-mycelium-ipv6]:30091
|
|
||||||
↓
|
|
||||||
kube-proxy (dual-stack enabled)
|
|
||||||
↓
|
|
||||||
Kubernetes Service (IPv4 + IPv6)
|
|
||||||
↓
|
|
||||||
Pod (container port 8080)
|
|
||||||
↓
|
|
||||||
nginx → HTML
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 Quick Start (Working Example)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd myceliumcloud-examples/examples/nginx-nodeport
|
|
||||||
|
|
||||||
# Deploy everything
|
|
||||||
kubectl apply -f nginx-nodeport-configmaps.yaml
|
|
||||||
kubectl apply -f nginx-nodeport-deployment.yaml
|
|
||||||
kubectl apply -f nginx-nodeport-service.yaml
|
|
||||||
|
|
||||||
# Wait for ready
|
|
||||||
kubectl wait --for=condition=ready pod -l app=nginx-nodeport --timeout=60s
|
|
||||||
|
|
||||||
# Run comprehensive tests
|
|
||||||
./test-nodeport-ipv6.sh
|
|
||||||
|
|
||||||
# Get access URL
|
|
||||||
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 ':' | head -1)
|
|
||||||
echo "Access at: http://[$NODE_IPV6]:30091"
|
|
||||||
|
|
||||||
# Access website (requires Mycelium on your machine)
|
|
||||||
curl -6 "http://[$NODE_IPV6]:30091/"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ Verification Checklist
|
|
||||||
|
|
||||||
- [x] **Service Type:** NodePort (not LoadBalancer)
|
|
||||||
- [x] **NodePort:** 30091 (avoiding conflict with 30090)
|
|
||||||
- [x] **IP Families:** Dual-stack (IPv4 + IPv6)
|
|
||||||
- [x] **Pod Network:** Isolated (no hostNetwork)
|
|
||||||
- [x] **External Traffic Policy:** Local (preserves source IP)
|
|
||||||
- [x] **Resource Limits:** Configured
|
|
||||||
- [x] **Health Probes:** Active
|
|
||||||
- [x] **ConfigMaps:** Mounted correctly
|
|
||||||
- [x] **nginx:** Dual-stack listening
|
|
||||||
- [x] **Scripts:** Working (test, update, debug)
|
|
||||||
- [x] **Documentation:** Complete
|
|
||||||
- [x] **IPv6 Access:** ✅ WORKING
|
|
||||||
- [x] **Browser Access:** ✅ WORKING
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 Documentation Structure
|
|
||||||
|
|
||||||
### Primary Guides
|
|
||||||
1. **[nginx-nodeport.md](nginx-nodeport.md)** - Complete implementation guide
|
|
||||||
2. **[IPV6_FIX.md](IPV6_FIX.md)** - Critical IPv6 configuration fix
|
|
||||||
3. **[TROUBLESHOOTING.md](TROUBLESHOOTING.md)** - Common issues & solutions
|
|
||||||
|
|
||||||
### Supporting Files
|
|
||||||
4. **[compare-approaches.md](compare-approaches.md)** - Security comparison
|
|
||||||
5. **[debug-nodeport.sh](debug-nodeport.sh)** - Diagnostic script
|
|
||||||
6. **[../nginx-variants.md](../nginx-variants.md)** - All 4 nginx variants
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Key Learnings
|
|
||||||
|
|
||||||
### 1. IPv6 Dual-Stack is Critical
|
|
||||||
**For Mycelium Cloud, ALWAYS configure services with:**
|
|
||||||
```yaml
|
|
||||||
ipFamilies:
|
|
||||||
- IPv4
|
|
||||||
- IPv6
|
|
||||||
ipFamilyPolicy: RequireDualStack
|
|
||||||
```
|
|
||||||
|
|
||||||
Without this, services won't be accessible via Mycelium IPv6 addresses.
|
|
||||||
|
|
||||||
### 2. NodePort vs hostNetwork
|
|
||||||
- **hostNetwork:** Pod gets host's Mycelium IP directly
|
|
||||||
- **NodePort:** Pod isolated, access via node's Mycelium IP + port
|
|
||||||
|
|
||||||
### 3. externalTrafficPolicy: Local
|
|
||||||
- Preserves IPv6 source IP for logging
|
|
||||||
- Service only accessible on node where pod runs
|
|
||||||
- More secure but requires correct node IP
|
|
||||||
|
|
||||||
### 4. Port Allocation
|
|
||||||
- **30090:** nginx-mycelium (hostNetwork)
|
|
||||||
- **30091:** nginx-nodeport (NodePort)
|
|
||||||
- Avoids conflicts between variants
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 Comparison with Other Variants
|
|
||||||
|
|
||||||
| Feature | hostNetwork | NodePort | LoadBalancer | Ingress |
|
|
||||||
|---------|-------------|----------|--------------|---------|
|
|
||||||
| **Pod Network** | Host | Isolated | Isolated | Isolated |
|
|
||||||
| **Access** | `[pod-ip]:8080` | `[node-ip]:30091` | `[lb-ip]:80` | `domain.com` |
|
|
||||||
| **Security** | Low | High | High | Highest |
|
|
||||||
| **IPv6 Config** | N/A | **Dual-stack required** | **Dual-stack required** | **Dual-stack required** |
|
|
||||||
| **Production** | No | Yes | Yes | Yes |
|
|
||||||
| **Status** | ✅ Complete | ✅ **Complete** | 🚧 Planned | 🚧 Planned |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐛 Issues Resolved
|
|
||||||
|
|
||||||
### Issue 1: IPv4-Only Service
|
|
||||||
**Symptom:** Can ping IPv6 but can't access HTTP
|
|
||||||
**Root Cause:** Service configured for IPv4 only
|
|
||||||
**Fix:** Added dual-stack IP families
|
|
||||||
**Status:** ✅ Resolved
|
|
||||||
|
|
||||||
### Issue 2: LoadBalancer vs NodePort Confusion
|
|
||||||
**Symptom:** Service type was LoadBalancer
|
|
||||||
**Root Cause:** Initial configuration error
|
|
||||||
**Fix:** Changed to NodePort with explicit port
|
|
||||||
**Status:** ✅ Resolved
|
|
||||||
|
|
||||||
### Issue 3: IPv6 Address Filtering
|
|
||||||
**Symptom:** Scripts getting IPv4 + IPv6 on same line
|
|
||||||
**Root Cause:** Poor IPv6 filtering
|
|
||||||
**Fix:** Enhanced regex to filter IPv6 only
|
|
||||||
**Status:** ✅ Resolved
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎓 What This Example Teaches
|
|
||||||
|
|
||||||
1. **Kubernetes Service Networking** - NodePort configuration
|
|
||||||
2. **IPv6 on Kubernetes** - Dual-stack service configuration
|
|
||||||
3. **Mycelium Integration** - IPv6 address discovery and access
|
|
||||||
4. **Security Patterns** - Pod isolation vs hostNetwork
|
|
||||||
5. **Production Readiness** - Health checks, resource limits, monitoring
|
|
||||||
6. **Troubleshooting** - Debugging network connectivity issues
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 Next Steps
|
|
||||||
|
|
||||||
The nginx-nodeport example is **complete and production-ready**. Future enhancements:
|
|
||||||
|
|
||||||
1. **LoadBalancer Variant** - External IP with cloud LB
|
|
||||||
2. **Ingress Variant** - Domain names with SSL/TLS
|
|
||||||
3. **Multi-Replica** - Horizontal pod autoscaling
|
|
||||||
4. **Monitoring** - Prometheus/Grafana integration
|
|
||||||
5. **SSL/TLS** - Let's Encrypt certificates
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📞 Support
|
|
||||||
|
|
||||||
If you encounter issues:
|
|
||||||
|
|
||||||
1. **Check [TROUBLESHOOTING.md](TROUBLESHOOTING.md)** - Common issues
|
|
||||||
2. **Run [debug-nodeport.sh](debug-nodeport.sh)** - Automated diagnostics
|
|
||||||
3. **Verify dual-stack config** - `kubectl get svc -o jsonpath='{.spec.ipFamilies}'`
|
|
||||||
4. **Test internal access** - `kubectl exec pod -- curl localhost:8080`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🏆 Success Metrics
|
|
||||||
|
|
||||||
✅ **Deployment:** Pods running successfully
|
|
||||||
✅ **Service:** NodePort 30091 configured
|
|
||||||
✅ **IPv6:** Dual-stack enabled
|
|
||||||
✅ **Access:** Website accessible via Mycelium IPv6
|
|
||||||
✅ **Browser:** Real browser access confirmed
|
|
||||||
✅ **Logs:** nginx showing actual requests
|
|
||||||
✅ **Scripts:** All test scripts passing
|
|
||||||
✅ **Documentation:** Complete and comprehensive
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Implementation Date:** 2025-01-07
|
|
||||||
**Status:** ✅ **100% COMPLETE & WORKING**
|
|
||||||
**Tested:** ✅ Yes (real browser access confirmed)
|
|
||||||
**Production Ready:** ✅ Yes
|
|
||||||
**Next:** LoadBalancer and Ingress variants
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎉 Final Confirmation
|
|
||||||
|
|
||||||
**The nginx-nodeport example is now FULLY FUNCTIONAL and demonstrates:**
|
|
||||||
|
|
||||||
1. ✅ Secure NodePort deployment with pod isolation
|
|
||||||
2. ✅ Dual-stack IPv4/IPv6 service configuration
|
|
||||||
3. ✅ Mycelium IPv6 address discovery and access
|
|
||||||
4. ✅ Production-ready patterns (health checks, resource limits)
|
|
||||||
5. ✅ Comprehensive testing and troubleshooting tools
|
|
||||||
6. ✅ Complete documentation and guides
|
|
||||||
|
|
||||||
**Anyone can now deploy this and access their website via Mycelium IPv6!**
|
|
||||||
@@ -1,181 +0,0 @@
|
|||||||
# nginx-nodeport Implementation - COMPLETE ✅
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
The nginx-nodeport example has been successfully completed and is ready for production use. This implementation demonstrates **security-first IPv6 web hosting** using Kubernetes NodePort services on Mycelium Cloud.
|
|
||||||
|
|
||||||
## What Was Completed
|
|
||||||
|
|
||||||
### 1. Service Configuration ✅
|
|
||||||
**File:** `nginx-nodeport-service.yaml`
|
|
||||||
- Changed from `LoadBalancer` to `NodePort` type
|
|
||||||
- Explicitly set `nodePort: 30091` (avoiding conflict with nginx-mycelium's 30090)
|
|
||||||
- Maintained `externalTrafficPolicy: Local` for IPv6 source IP preservation
|
|
||||||
- **Access:** `http://[worker-node-mycelium-ipv6]:30091`
|
|
||||||
|
|
||||||
### 2. Content Update Script ✅
|
|
||||||
**File:** `update-content.sh`
|
|
||||||
- Created complete script for dynamic content updates
|
|
||||||
- Discovers worker node Mycelium IPv6 addresses automatically
|
|
||||||
- Generates HTML with all accessible URLs
|
|
||||||
- Updates ConfigMap and provides rollout instructions
|
|
||||||
- Made executable with proper permissions
|
|
||||||
|
|
||||||
### 3. Test Script Enhancement ✅
|
|
||||||
**File:** `test-nodeport-ipv6.sh`
|
|
||||||
- Enhanced validation to confirm NodePort type (not LoadBalancer)
|
|
||||||
- Validates explicit port 30091 configuration
|
|
||||||
- Comprehensive testing of all NodePort features
|
|
||||||
|
|
||||||
### 4. Documentation Updates ✅
|
|
||||||
**File:** `nginx-nodeport.md`
|
|
||||||
- Added clear explanation of NodePort vs hostNetwork differences
|
|
||||||
- Documented complete traffic flow: User → Node:30091 → Service:8080 → Pod:8080
|
|
||||||
- Added comprehensive flow diagrams
|
|
||||||
- Created comparison tables for all 4 nginx variants
|
|
||||||
- Clarified Mycelium access patterns
|
|
||||||
- Added security benefits and operational advantages
|
|
||||||
|
|
||||||
### 5. Comprehensive Nginx Variants Guide ✅
|
|
||||||
**File:** `../nginx-variants.md`
|
|
||||||
- Created complete comparison of all 4 nginx deployment methods
|
|
||||||
- Decision tree for choosing the right variant
|
|
||||||
- Migration paths between variants
|
|
||||||
- Detailed technical specifications
|
|
||||||
- Common operations and troubleshooting
|
|
||||||
|
|
||||||
## Key Architecture Points
|
|
||||||
|
|
||||||
### NodePort Access Pattern
|
|
||||||
```
|
|
||||||
User with Mycelium
|
|
||||||
↓
|
|
||||||
http://[worker-node-mycelium-ipv6]:30091
|
|
||||||
↓
|
|
||||||
Worker Node (kube-proxy)
|
|
||||||
↓
|
|
||||||
NodePort 30091 → Service port 8080
|
|
||||||
↓
|
|
||||||
Kubernetes Service (load balances)
|
|
||||||
↓
|
|
||||||
Pod container port 8080
|
|
||||||
↓
|
|
||||||
nginx → HTML Content
|
|
||||||
```
|
|
||||||
|
|
||||||
### Security Improvements Over hostNetwork
|
|
||||||
- ✅ Pod isolation (no hostNetwork)
|
|
||||||
- ✅ Network namespace isolation
|
|
||||||
- ✅ Resource limits enforced
|
|
||||||
- ✅ Health checks active
|
|
||||||
- ✅ Standard Kubernetes networking
|
|
||||||
- ✅ Network policies supported
|
|
||||||
|
|
||||||
### Port Allocation
|
|
||||||
- **External:** NodePort 30091 (on all worker nodes)
|
|
||||||
- **Service:** Port 8080 (ClusterIP)
|
|
||||||
- **Target:** Pod 8080 (nginx)
|
|
||||||
- **Rationale:** 30091 avoids conflict with nginx-mycelium's 30090
|
|
||||||
|
|
||||||
## Files Overview
|
|
||||||
|
|
||||||
| File | Purpose | Status |
|
|
||||||
|------|---------|--------|
|
|
||||||
| `nginx-nodeport-deployment.yaml` | Pod deployment config | ✅ Verified |
|
|
||||||
| `nginx-nodeport-service.yaml` | NodePort service | ✅ Fixed |
|
|
||||||
| `nginx-nodeport-configmaps.yaml` | HTML & nginx config | ✅ Verified |
|
|
||||||
| `test-nodeport-ipv6.sh` | Testing script | ✅ Enhanced |
|
|
||||||
| `update-content.sh` | Content updater | ✅ Created |
|
|
||||||
| `nginx-nodeport.md` | Complete documentation | ✅ Updated |
|
|
||||||
| `compare-approaches.md` | Security comparison | ✅ Existing |
|
|
||||||
| `../nginx-variants.md` | All variants guide | ✅ Created |
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Deploy ConfigMaps
|
|
||||||
kubectl apply -f nginx-nodeport-configmaps.yaml
|
|
||||||
|
|
||||||
# 2. Deploy application
|
|
||||||
kubectl apply -f nginx-nodeport-deployment.yaml
|
|
||||||
|
|
||||||
# 3. Create service
|
|
||||||
kubectl apply -f nginx-nodeport-service.yaml
|
|
||||||
|
|
||||||
# 4. Wait for ready
|
|
||||||
kubectl wait --for=condition=ready pod -l app=nginx-nodeport --timeout=60s
|
|
||||||
|
|
||||||
# 5. Get worker node IPv6
|
|
||||||
NODE_IPV6=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')
|
|
||||||
|
|
||||||
# 6. Access website
|
|
||||||
curl -6 "http://[$NODE_IPV6]:30091/"
|
|
||||||
|
|
||||||
# Or run comprehensive tests
|
|
||||||
./test-nodeport-ipv6.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## Testing Checklist
|
|
||||||
|
|
||||||
- [x] Service type is NodePort (not LoadBalancer)
|
|
||||||
- [x] NodePort is explicitly set to 30091
|
|
||||||
- [x] Pod uses hostNetwork: false (isolated)
|
|
||||||
- [x] Resource limits are configured
|
|
||||||
- [x] Health probes are active
|
|
||||||
- [x] ConfigMaps mount correctly
|
|
||||||
- [x] nginx listens on dual-stack (IPv4 + IPv6)
|
|
||||||
- [x] Service preserves source IP (externalTrafficPolicy: Local)
|
|
||||||
- [x] Test script validates all features
|
|
||||||
- [x] Update script creates dynamic content
|
|
||||||
- [x] Documentation is comprehensive
|
|
||||||
|
|
||||||
## Key Differences from hostNetwork
|
|
||||||
|
|
||||||
| Aspect | hostNetwork | NodePort |
|
|
||||||
|--------|-------------|----------|
|
|
||||||
| **Pod Network** | Host | Isolated |
|
|
||||||
| **Access** | `[pod-ip]:8080` | `[node-ip]:30091` |
|
|
||||||
| **Security** | Low | High |
|
|
||||||
| **Scaling** | Limited | Good |
|
|
||||||
| **Production** | No | Yes |
|
|
||||||
|
|
||||||
## What's Next
|
|
||||||
|
|
||||||
### Future nginx Variants
|
|
||||||
1. **LoadBalancer** - External IP with cloud LB
|
|
||||||
2. **Ingress** - Domain names with SSL/TLS
|
|
||||||
|
|
||||||
### Enhancements
|
|
||||||
1. Multi-replica deployment examples
|
|
||||||
2. Advanced monitoring with Prometheus
|
|
||||||
3. SSL/TLS certificate management
|
|
||||||
4. Custom domain integration
|
|
||||||
|
|
||||||
## Validation
|
|
||||||
|
|
||||||
All implementation goals have been achieved:
|
|
||||||
|
|
||||||
✅ Service correctly uses NodePort with explicit port 30091
|
|
||||||
✅ Documentation clearly explains NodePort vs hostNetwork
|
|
||||||
✅ Scripts work with correct ports and ConfigMaps
|
|
||||||
✅ Complete traffic flow is documented
|
|
||||||
✅ Comparison tables show all 4 variants
|
|
||||||
✅ Security improvements are documented
|
|
||||||
✅ Production-ready patterns implemented
|
|
||||||
✅ Comprehensive testing capabilities
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- **Port 30091** chosen to avoid conflict with nginx-mycelium (30090)
|
|
||||||
- **NodePort range** is 30000-32767 (Kubernetes standard)
|
|
||||||
- **externalTrafficPolicy: Local** preserves IPv6 source addresses for logging
|
|
||||||
- **hostNetwork: false** ensures pod isolation and security
|
|
||||||
- Works with **Mycelium IPv6 addresses** for global accessibility
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Implementation Date:** 2025-01-07
|
|
||||||
**Status:** ✅ COMPLETE AND PRODUCTION-READY
|
|
||||||
**Tested:** Yes
|
|
||||||
**Documentation:** Complete
|
|
||||||
**Next:** LoadBalancer and Ingress variants
|
|
||||||
@@ -1,242 +0,0 @@
|
|||||||
# 🚨 CRITICAL: IPv6 Configuration Fix Required
|
|
||||||
|
|
||||||
## The Problem
|
|
||||||
|
|
||||||
When initially deploying NodePort services on Mycelium Cloud, you may encounter a situation where:
|
|
||||||
- ✅ `ping -6` works (ICMP reaches the node)
|
|
||||||
- ❌ `curl -6 http://[ipv6]:30091/` fails (HTTP service unreachable)
|
|
||||||
|
|
||||||
## Root Cause
|
|
||||||
|
|
||||||
**IPv4-only service configuration!**
|
|
||||||
|
|
||||||
By default, Kubernetes services created without explicit IP family configuration are often IPv4-only, even when nodes have IPv6 addresses.
|
|
||||||
|
|
||||||
### Symptom
|
|
||||||
```bash
|
|
||||||
# Service shows IPv4-only
|
|
||||||
$ kubectl get svc nginx-nodeport-service -o json | grep ipFamily
|
|
||||||
"ipFamilyPolicy": "SingleStack",
|
|
||||||
"ipFamilies": ["IPv4"],
|
|
||||||
```
|
|
||||||
|
|
||||||
### Result
|
|
||||||
- Services only listen on IPv4 addresses
|
|
||||||
- IPv6 Mycelium addresses are "reachable" (ping works) but HTTP fails
|
|
||||||
- nginx itself is fine (listens on dual-stack)
|
|
||||||
- **kube-proxy won't forward IPv6 traffic to the service**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## The Fix ⭐
|
|
||||||
|
|
||||||
Update the Service YAML to explicitly support dual-stack:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: nginx-nodeport-service
|
|
||||||
spec:
|
|
||||||
type: NodePort
|
|
||||||
externalTrafficPolicy: Local
|
|
||||||
ipFamilies: # ← ADD THESE 3 LINES
|
|
||||||
- IPv4
|
|
||||||
- IPv6
|
|
||||||
ipFamilyPolicy: RequireDualStack # ← ADD THIS
|
|
||||||
selector:
|
|
||||||
app: nginx-nodeport
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
port: 8080
|
|
||||||
targetPort: 8080
|
|
||||||
nodePort: 30091
|
|
||||||
protocol: TCP
|
|
||||||
```
|
|
||||||
|
|
||||||
### Apply the fix:
|
|
||||||
```bash
|
|
||||||
kubectl apply -f nginx-nodeport-service.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
### Verify the fix:
|
|
||||||
```bash
|
|
||||||
# Should now show dual-stack
|
|
||||||
$ kubectl get svc nginx-nodeport-service -o jsonpath='{.spec.ipFamilies}'
|
|
||||||
["IPv4","IPv6"]
|
|
||||||
|
|
||||||
$ kubectl get svc nginx-nodeport-service -o jsonpath='{.spec.ipFamilyPolicy}'
|
|
||||||
RequireDualStack
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Why This Happens
|
|
||||||
|
|
||||||
1. **Legacy default**: Many Kubernetes setups default to IPv4-only
|
|
||||||
2. **Service doesn't inherit node IPs**: Service has its own ClusterIP
|
|
||||||
3. **kube-proxy needs explicit instruction**: Must know to create IPv6 rules
|
|
||||||
4. **IP family policy**: Controls whether service listens on IPv4, IPv6, or both
|
|
||||||
|
|
||||||
### Without dual-stack:
|
|
||||||
```
|
|
||||||
User → Mycelium IPv6 → Node port 30091
|
|
||||||
↓
|
|
||||||
kube-proxy
|
|
||||||
↓
|
|
||||||
IPv4 service ← BOTTLENECK
|
|
||||||
↓
|
|
||||||
Pod responds
|
|
||||||
```
|
|
||||||
|
|
||||||
### With dual-stack:
|
|
||||||
```
|
|
||||||
User → Mycelium IPv6 → Node port 30091
|
|
||||||
↓
|
|
||||||
kube-proxy
|
|
||||||
↓
|
|
||||||
IPv6 + IPv4 service ← WORKS!
|
|
||||||
↓
|
|
||||||
Pod responds
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Testing the Fix
|
|
||||||
|
|
||||||
### Before fix:
|
|
||||||
```bash
|
|
||||||
$ curl -6 "http://[552:5984:2d97:72dc:ff0f:39ef:6ec:a48c]:30091/"
|
|
||||||
curl: (7) Failed to connect to ... Connection refused
|
|
||||||
```
|
|
||||||
|
|
||||||
### After fix:
|
|
||||||
```bash
|
|
||||||
$ curl -6 "http://[552:5984:2d97:72dc:ff0f:39ef:6ec:a48c]:30091/"
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>Mycelium Cloud - Nginx NodePort Website</title>
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
### Automated test:
|
|
||||||
```bash
|
|
||||||
cd myceliumcloud-examples/examples/nginx-nodeport
|
|
||||||
./test-nodeport-ipv6.sh
|
|
||||||
|
|
||||||
# Should now show:
|
|
||||||
# ✅ External Mycelium IPv6 connectivity is working!
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Other Affected Variants
|
|
||||||
|
|
||||||
This IP family configuration is critical for:
|
|
||||||
|
|
||||||
- ✅ **NodePort** - This guide
|
|
||||||
- ✅ **LoadBalancer** - Will need same configuration (future example)
|
|
||||||
- ✅ **Ingress** - Will need same configuration (future example)
|
|
||||||
- ❌ **hostNetwork** - NOT affected (directly uses host network stack)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Kubernetes Version Compatibility
|
|
||||||
|
|
||||||
### Kubernetes 1.20+ (Recommended)
|
|
||||||
- Full dual-stack support
|
|
||||||
- `RequireDualStack` policy available
|
|
||||||
- Complete IPv4/IPv6 feature set
|
|
||||||
|
|
||||||
### Kubernetes 1.19 and earlier
|
|
||||||
- Limited dual-stack support
|
|
||||||
- May need `ipFamily: IPv6` instead of `RequireDualStack`
|
|
||||||
- Some features may not work
|
|
||||||
|
|
||||||
**Check your version:**
|
|
||||||
```bash
|
|
||||||
kubectl version --short
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Quick Reference
|
|
||||||
|
|
||||||
### Service configuration checklist:
|
|
||||||
- [ ] `type: NodePort` ✓
|
|
||||||
- [ ] `nodePort: 30091` ✓
|
|
||||||
- [ ] `externalTrafficPolicy: Local` ✓
|
|
||||||
- [ ] `ipFamilies: [IPv4, IPv6]` ⭐ Critical for Mycelium
|
|
||||||
- [ ] `ipFamilyPolicy: RequireDualStack` ⭐ Critical for Mycelium
|
|
||||||
|
|
||||||
### Test sequence:
|
|
||||||
```bash
|
|
||||||
# 1. Deploy
|
|
||||||
kubectl apply -f nginx-nodeport-configmaps.yaml
|
|
||||||
kubectl apply -f nginx-nodeport-deployment.yaml
|
|
||||||
kubectl apply -f nginx-nodeport-service.yaml
|
|
||||||
|
|
||||||
# 2. Wait
|
|
||||||
kubectl wait --for=condition=ready pod -l app=nginx-nodeport --timeout=60s
|
|
||||||
|
|
||||||
# 3. Check IP families
|
|
||||||
kubectl get svc nginx-nodeport-service -o jsonpath='{.spec.ipFamilies}'
|
|
||||||
|
|
||||||
# 4. Test
|
|
||||||
NODE_IPV6=$(kubectl get nodes -o jsonpath='{range .items[*]}{range .status.addresses[?(@.type=="InternalIP")]}{.address}{"\n"}{end}{end}' | grep ':' | head -1)
|
|
||||||
curl -6 "http://[$NODE_IPV6]:30091/"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Still not working after dual-stack config?
|
|
||||||
|
|
||||||
1. **Check kube-proxy logs:**
|
|
||||||
```bash
|
|
||||||
kubectl logs -n kube-system -l k8s-app=kube-proxy | grep -i error
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Verify nginx listens on IPv6:**
|
|
||||||
```bash
|
|
||||||
POD_NAME=$(kubectl get pods -l app=nginx-nodeport -o name | head -1)
|
|
||||||
kubectl exec $POD_NAME -- netstat -tuln | grep 8080
|
|
||||||
# Should show:
|
|
||||||
# tcp 0 0 0.0.0.0:8080 :::* LISTEN
|
|
||||||
# tcp 0 0 :::8080 :::* LISTEN ← IPv6
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Check service endpoints:**
|
|
||||||
```bash
|
|
||||||
kubectl get endpoints nginx-nodeport-service
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Test from within cluster:**
|
|
||||||
```bash
|
|
||||||
kubectl run test --rm -it --image=curlimages/curl -- sh -c "curl http://$SERVICE_IP:8080"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
**For Mycelium Cloud NodePort deployments, ALWAYS include:**
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
spec:
|
|
||||||
ipFamilies:
|
|
||||||
- IPv4
|
|
||||||
- IPv6
|
|
||||||
ipFamilyPolicy: RequireDualStack
|
|
||||||
```
|
|
||||||
|
|
||||||
Without this, services won't be accessible via Mycelium IPv6 addresses, even though the nodes are reachable via ping.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Impact:** This is a **deployment-blocking issue** for anyone trying to use NodePort with Mycelium IPv6.
|
|
||||||
|
|
||||||
**Status:** ✅ Fixed in updated `nginx-nodeport-service.yaml`
|
|
||||||
**Related:** [TROUBLESHOOTING.md](TROUBLESHOOTING.md)
|
|
||||||
@@ -48,16 +48,7 @@ Or open in browser:
|
|||||||
|
|
||||||
Does everything: deploy, test, configure, and show results.
|
Does everything: deploy, test, configure, and show results.
|
||||||
|
|
||||||
### 2. `test-nodeport-ipv6.sh` - Testing Only
|
### 2. `update-content.sh` - Content Update
|
||||||
**If you already have nginx-nodeport deployed and want to test it**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./test-nodeport-ipv6.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Runs comprehensive tests and shows access URLs.
|
|
||||||
|
|
||||||
### 3. `update-content.sh` - Content Update
|
|
||||||
**Updates website content with current cluster state**
|
**Updates website content with current cluster state**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -86,10 +77,6 @@ kubectl wait --for=condition=ready pod -l app=nginx-nodeport --timeout=60s
|
|||||||
./update-content.sh
|
./update-content.sh
|
||||||
kubectl rollout restart deployment/nginx-nodeport
|
kubectl rollout restart deployment/nginx-nodeport
|
||||||
|
|
||||||
# 4. Test
|
|
||||||
./test-nodeport-ipv6.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🎯 What This Example Teaches
|
## 🎯 What This Example Teaches
|
||||||
@@ -218,12 +205,6 @@ kubectl scale deployment nginx-nodeport --replicas=3
|
|||||||
- [`../nginx-static/`](../nginx-static/) - Simple static site
|
- [`../nginx-static/`](../nginx-static/) - Simple static site
|
||||||
- LoadBalancer and Ingress variants (coming soon)
|
- LoadBalancer and Ingress variants (coming soon)
|
||||||
|
|
||||||
3. **Learn more:**
|
|
||||||
- [Compare all variants](../nginx-variants.md)
|
|
||||||
- [Security comparison](compare-approaches.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎉 Success!
|
## 🎉 Success!
|
||||||
|
|
||||||
Once deployed and tested, you'll have a **fully functional website accessible via Mycelium IPv6** with:
|
Once deployed and tested, you'll have a **fully functional website accessible via Mycelium IPv6** with:
|
||||||
|
|||||||
@@ -1,347 +0,0 @@
|
|||||||
# nginx-nodeport Troubleshooting Guide
|
|
||||||
|
|
||||||
## Common Issues and Solutions
|
|
||||||
|
|
||||||
### Issue: External IPv6 Connectivity Test Failed
|
|
||||||
|
|
||||||
**Symptoms:**
|
|
||||||
```
|
|
||||||
⚠️ External Mycelium IPv6 connectivity test failed
|
|
||||||
ℹ️ This might be due to:
|
|
||||||
ℹ️ • Firewall or network policies blocking port 30091
|
|
||||||
ℹ️ • Pod not running on this specific node
|
|
||||||
ℹ️ • Mycelium network not properly configured
|
|
||||||
```
|
|
||||||
|
|
||||||
**Root Causes & Solutions:**
|
|
||||||
|
|
||||||
#### 1. Mycelium Not Running on Your Machine ⭐ Most Common
|
|
||||||
|
|
||||||
**Problem:** You're trying to access from a machine without Mycelium installed/running.
|
|
||||||
|
|
||||||
**Solution:** Install and start Mycelium on your local machine:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Download Mycelium
|
|
||||||
wget https://github.com/threefoldtech/mycelium/releases/latest/download/mycelium-private-x86_64-unknown-linux-musl.tar.gz
|
|
||||||
tar -xzf mycelium-private-x86_64-unknown-linux-musl.tar.gz
|
|
||||||
sudo chmod +x mycelium-private
|
|
||||||
sudo mv mycelium-private /usr/local/bin/mycelium
|
|
||||||
|
|
||||||
# Start Mycelium with peers
|
|
||||||
sudo mycelium --peers tcp://188.40.132.242:9651 tcp://136.243.47.186:9651 tcp://185.69.166.7:9651
|
|
||||||
```
|
|
||||||
|
|
||||||
**After starting Mycelium, test connectivity:**
|
|
||||||
```bash
|
|
||||||
# Your machine should now have a Mycelium IPv6 address
|
|
||||||
ip addr show | grep mycelium
|
|
||||||
|
|
||||||
# Test connection
|
|
||||||
NODE_IPV6="552:5984:2d97:72dc:ff0f:39ef:6ec:a48c" # Replace with your node's IP
|
|
||||||
curl -6 "http://[$NODE_IPV6]:30091/"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### 2. Testing from Wrong Location
|
|
||||||
|
|
||||||
**Problem:** Testing from within cluster or wrong network segment.
|
|
||||||
|
|
||||||
**Solution:** Test from a machine WITH Mycelium running:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# ✅ CORRECT: Test from machine with Mycelium
|
|
||||||
your-laptop$ curl -6 "http://[node-mycelium-ipv6]:30091/"
|
|
||||||
|
|
||||||
# ❌ WRONG: Test from within cluster (use localhost instead)
|
|
||||||
kubectl exec pod/nginx-nodeport-xxx -- curl localhost:8080
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### 3. Firewall Blocking NodePort
|
|
||||||
|
|
||||||
**Problem:** Firewall rules blocking port 30091.
|
|
||||||
|
|
||||||
**Check firewall:**
|
|
||||||
```bash
|
|
||||||
# On the worker node
|
|
||||||
sudo iptables -L -n | grep 30091
|
|
||||||
sudo firewall-cmd --list-ports # if using firewalld
|
|
||||||
```
|
|
||||||
|
|
||||||
**Solution:** Open port 30091 on worker nodes:
|
|
||||||
```bash
|
|
||||||
# Using iptables
|
|
||||||
sudo iptables -I INPUT -p tcp --dport 30091 -j ACCEPT
|
|
||||||
|
|
||||||
# Using firewalld
|
|
||||||
sudo firewall-cmd --permanent --add-port=30091/tcp
|
|
||||||
sudo firewall-cmd --reload
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### 4. externalTrafficPolicy: Local Issue
|
|
||||||
|
|
||||||
**Problem:** With `externalTrafficPolicy: Local`, service is only accessible on nodes where pods are running.
|
|
||||||
|
|
||||||
**Understanding:**
|
|
||||||
- ✅ Pod on node A → Access via node A's IP works
|
|
||||||
- ❌ Pod on node A → Access via node B's IP fails
|
|
||||||
|
|
||||||
**Solution:** Always use the IP of the node where your pod is running:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Find which node has your pod
|
|
||||||
POD_NODE=$(kubectl get pods -l app=nginx-nodeport -o jsonpath='{.items[0].spec.nodeName}')
|
|
||||||
echo "Pod is on: $POD_NODE"
|
|
||||||
|
|
||||||
# Get THAT node's Mycelium IPv6
|
|
||||||
NODE_IPV6=$(kubectl get node "$POD_NODE" -o jsonpath='{range .status.addresses[?(@.type=="InternalIP")]}{.address}{"\n"}{end}' | grep ':' | head -1)
|
|
||||||
echo "Use this IP: $NODE_IPV6"
|
|
||||||
|
|
||||||
# Test
|
|
||||||
curl -6 "http://[$NODE_IPV6]:30091/"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### 5. IPv6 vs IPv4 Confusion
|
|
||||||
|
|
||||||
**Problem:** Getting both IPv4 and IPv6 addresses, causing malformed URLs.
|
|
||||||
|
|
||||||
**Symptoms:**
|
|
||||||
```
|
|
||||||
curl: (3) bad range in URL position 9:
|
|
||||||
http://[10.20.2.2 51d:3596:6cc3:81e7:ff0f:d546:3737:4c8c]:30091/
|
|
||||||
```
|
|
||||||
|
|
||||||
**Solution:** Filter for IPv6 only:
|
|
||||||
```bash
|
|
||||||
# Correct way to get IPv6 only
|
|
||||||
kubectl get nodes -o jsonpath='{range .items[*]}{range .status.addresses[?(@.type=="InternalIP")]}{.address}{"\n"}{end}{end}' | grep -E '^[0-9a-f]+:[0-9a-f]+:'
|
|
||||||
|
|
||||||
# NOT this (gets both IPv4 and IPv6)
|
|
||||||
kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}'
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Issue: Pod Not Accessible
|
|
||||||
|
|
||||||
**Check pod status:**
|
|
||||||
```bash
|
|
||||||
kubectl get pods -l app=nginx-nodeport
|
|
||||||
kubectl describe pod -l app=nginx-nodeport
|
|
||||||
kubectl logs -l app=nginx-nodeport
|
|
||||||
```
|
|
||||||
|
|
||||||
**Test internal connectivity:**
|
|
||||||
```bash
|
|
||||||
POD_NAME=$(kubectl get pods -l app=nginx-nodeport -o name | head -1)
|
|
||||||
|
|
||||||
# Test from within pod
|
|
||||||
kubectl exec $POD_NAME -- curl -s http://localhost:8080/
|
|
||||||
|
|
||||||
# Test health endpoint
|
|
||||||
kubectl exec $POD_NAME -- curl -s http://localhost:8080/health
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Issue: Service Not Working
|
|
||||||
|
|
||||||
**Check service configuration:**
|
|
||||||
```bash
|
|
||||||
# Verify service type
|
|
||||||
kubectl get svc nginx-nodeport-service -o jsonpath='{.spec.type}'
|
|
||||||
# Should output: NodePort
|
|
||||||
|
|
||||||
# Check NodePort assignment
|
|
||||||
kubectl get svc nginx-nodeport-service -o jsonpath='{.spec.ports[0].nodePort}'
|
|
||||||
# Should output: 30091
|
|
||||||
|
|
||||||
# Check endpoints
|
|
||||||
kubectl get endpoints nginx-nodeport-service
|
|
||||||
# Should show pod IP and port
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Issue: Wrong Content Displayed
|
|
||||||
|
|
||||||
**Update ConfigMap:**
|
|
||||||
```bash
|
|
||||||
# Regenerate content with current IPs
|
|
||||||
./update-content.sh
|
|
||||||
|
|
||||||
# Restart deployment to pick up changes
|
|
||||||
kubectl rollout restart deployment/nginx-nodeport
|
|
||||||
|
|
||||||
# Wait for rollout
|
|
||||||
kubectl rollout status deployment/nginx-nodeport
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Testing Checklist
|
|
||||||
|
|
||||||
Run through this checklist to verify everything:
|
|
||||||
|
|
||||||
- [ ] **Mycelium Running:** `ip addr show | grep mycelium`
|
|
||||||
- [ ] **Pod Running:** `kubectl get pods -l app=nginx-nodeport`
|
|
||||||
- [ ] **Service Exists:** `kubectl get svc nginx-nodeport-service`
|
|
||||||
- [ ] **NodePort 30091:** `kubectl get svc nginx-nodeport-service -o jsonpath='{.spec.ports[0].nodePort}'`
|
|
||||||
- [ ] **Pod Node Located:** `kubectl get pods -l app=nginx-nodeport -o wide`
|
|
||||||
- [ ] **Node IPv6 Found:** `kubectl get node <node-name> -o jsonpath='{.status.addresses[?(@.type=="InternalIP")].address}' | grep ':'`
|
|
||||||
- [ ] **Internal Access:** `kubectl exec <pod> -- curl -s http://localhost:8080/`
|
|
||||||
- [ ] **External Access:** `curl -6 "http://[node-ipv6]:30091/"`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Quick Validation Commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Complete test sequence
|
|
||||||
cd myceliumcloud-examples/examples/nginx-nodeport
|
|
||||||
|
|
||||||
# 1. Run automated tests
|
|
||||||
./test-nodeport-ipv6.sh
|
|
||||||
|
|
||||||
# 2. Find your pod's node
|
|
||||||
POD_NODE=$(kubectl get pods -l app=nginx-nodeport -o jsonpath='{.items[0].spec.nodeName}')
|
|
||||||
echo "Pod is on node: $POD_NODE"
|
|
||||||
|
|
||||||
# 3. Get that node's Mycelium IPv6
|
|
||||||
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]+:' | head -1)
|
|
||||||
echo "Node Mycelium IPv6: $NODE_IPV6"
|
|
||||||
|
|
||||||
# 4. Test from machine with Mycelium
|
|
||||||
curl -6 "http://[$NODE_IPV6]:30091/"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Expected Behavior
|
|
||||||
|
|
||||||
### ✅ Working Correctly
|
|
||||||
|
|
||||||
When everything is working, you should see:
|
|
||||||
|
|
||||||
1. **Test Script Output:**
|
|
||||||
```
|
|
||||||
✅ nginx-nodeport pods are ready
|
|
||||||
✅ nginx configuration is valid
|
|
||||||
✅ Health endpoint is working
|
|
||||||
✅ NodePort service is configured correctly
|
|
||||||
✅ NodePort is correctly set to 30091
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **External Access:**
|
|
||||||
```bash
|
|
||||||
$ curl -6 "http://[552:5984:2d97:72dc:ff0f:39ef:6ec:a48c]:30091/"
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>Mycelium Cloud - Nginx NodePort Website</title>
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Browser Access:**
|
|
||||||
- Navigate to: `http://[node-mycelium-ipv6]:30091/`
|
|
||||||
- Should see: Styled website with "NODEPORT SECURE" badge
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Advanced Debugging
|
|
||||||
|
|
||||||
### Check kube-proxy
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# On worker node
|
|
||||||
sudo iptables-save | grep 30091
|
|
||||||
```
|
|
||||||
|
|
||||||
### View Service Routing
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check service details
|
|
||||||
kubectl describe svc nginx-nodeport-service
|
|
||||||
|
|
||||||
# Check endpoints
|
|
||||||
kubectl get endpoints nginx-nodeport-service -o yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test from Another Pod
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create test pod
|
|
||||||
kubectl run test-pod --image=nginx:alpine --rm -it -- sh
|
|
||||||
|
|
||||||
# From inside test pod
|
|
||||||
wget -O- http://nginx-nodeport-service:8080/
|
|
||||||
# Should work (internal cluster access)
|
|
||||||
|
|
||||||
# Try NodePort (won't work from inside cluster)
|
|
||||||
wget -O- http://[node-ip]:30091/
|
|
||||||
# May not work depending on network policies
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Still Having Issues?
|
|
||||||
|
|
||||||
If none of the above solutions work:
|
|
||||||
|
|
||||||
1. **Check Logs:**
|
|
||||||
```bash
|
|
||||||
kubectl logs -l app=nginx-nodeport --tail=50
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Describe Resources:**
|
|
||||||
```bash
|
|
||||||
kubectl describe deployment nginx-nodeport
|
|
||||||
kubectl describe service nginx-nodeport-service
|
|
||||||
kubectl describe pod -l app=nginx-nodeport
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Verify Network:**
|
|
||||||
```bash
|
|
||||||
# Check pod can reach internet
|
|
||||||
kubectl exec <pod> -- ping -c 3 8.8.8.8
|
|
||||||
|
|
||||||
# Check pod networking
|
|
||||||
kubectl exec <pod> -- ip addr
|
|
||||||
kubectl exec <pod> -- ip route
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Compare with hostNetwork:**
|
|
||||||
- The [`nginx-mycelium`](../nginx-mycelium/) example uses hostNetwork
|
|
||||||
- If that works but NodePort doesn't, it's likely a service/networking issue
|
|
||||||
- If neither works, check Mycelium connectivity
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Common Questions
|
|
||||||
|
|
||||||
**Q: Why can't I access from any node's IP?**
|
|
||||||
A: With `externalTrafficPolicy: Local`, you can only access via the node where the pod is running. This preserves source IP but limits accessibility.
|
|
||||||
|
|
||||||
**Q: Should I change to `externalTrafficPolicy: Cluster`?**
|
|
||||||
A: You can, but you'll lose source IP preservation. Decision depends on your logging/security needs.
|
|
||||||
|
|
||||||
**Q: How is this different from hostNetwork?**
|
|
||||||
A: NodePort provides network isolation and standard Kubernetes patterns. HostNetwork gives direct host access (less secure). See [compare-approaches.md](compare-approaches.md).
|
|
||||||
|
|
||||||
**Q: Why port 30091 and not 80?**
|
|
||||||
A: Kubernetes NodePorts use range 30000-32767. Port 80 requires LoadBalancer or Ingress type services.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Last Updated:** 2025-01-07
|
|
||||||
**Related Docs:**
|
|
||||||
- [nginx-nodeport.md](nginx-nodeport.md) - Complete guide
|
|
||||||
- [compare-approaches.md](compare-approaches.md) - Security comparison
|
|
||||||
- [../nginx-variants.md](../nginx-variants.md) - All nginx variants
|
|
||||||
@@ -1,378 +0,0 @@
|
|||||||
# Nginx Mycelium Approaches: Security and Architecture Comparison
|
|
||||||
|
|
||||||
A comprehensive comparison of **hostNetwork** vs **NodePort** approaches for IPv6 web hosting on Mycelium Cloud, helping you choose the right solution for your use case.
|
|
||||||
|
|
||||||
## 🔍 Quick Comparison Summary
|
|
||||||
|
|
||||||
| Aspect | hostNetwork (nginx-mycelium) | NodePort (nginx-nodeport) |
|
|
||||||
|--------|------------------------------|---------------------------|
|
|
||||||
| **Security Level** | ⚠️ Low | ✅ High |
|
|
||||||
| **Network Isolation** | ❌ None | ✅ Full |
|
|
||||||
| **Complexity** | ✅ Simple | ✅ Simple |
|
|
||||||
| **IPv6 Access** | ✅ Direct | ✅ Via Service |
|
|
||||||
| **Production Ready** | ⚠️ Demo/POC | ✅ Production |
|
|
||||||
| **Scalability** | ❌ Limited | ✅ Good |
|
|
||||||
| **Debugging** | 🔄 Hard | ✅ Standard K8s |
|
|
||||||
|
|
||||||
## 🏗️ Architecture Deep Dive
|
|
||||||
|
|
||||||
### hostNetwork Approach (nginx-mycelium)
|
|
||||||
|
|
||||||
**How it works:**
|
|
||||||
```
|
|
||||||
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
|
||||||
│ Mycelium │ │ NodePort │ │ Host Network │
|
|
||||||
│ IPv6 Network │───▶│ Service │───▶│ (Direct) │
|
|
||||||
│ :30090 │ │ :8080 │ │ :8080 │
|
|
||||||
└─────────────────┘ └──────────────────┘ └─────────────────┘
|
|
||||||
│ │
|
|
||||||
▼ ▼
|
|
||||||
┌──────────────────┐ ┌─────────────────┐
|
|
||||||
│ ConfigMaps │ │ Direct Host │
|
|
||||||
│ • HTML Content │ │ Interface │
|
|
||||||
│ • nginx Config │ │ Access │
|
|
||||||
└──────────────────┘ └─────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
**Key characteristics:**
|
|
||||||
- Pod shares host's network namespace
|
|
||||||
- Direct access to host's IPv6 interfaces
|
|
||||||
- nginx binds directly to host ports
|
|
||||||
- No network isolation between pod and host
|
|
||||||
- Simple networking, minimal overhead
|
|
||||||
|
|
||||||
**Configuration:**
|
|
||||||
```yaml
|
|
||||||
spec:
|
|
||||||
hostNetwork: true # Shares host network
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
ports:
|
|
||||||
- containerPort: 8080
|
|
||||||
hostPort: 8080 # Direct host port binding
|
|
||||||
```
|
|
||||||
|
|
||||||
### NodePort Approach (nginx-nodeport)
|
|
||||||
|
|
||||||
**How it works:**
|
|
||||||
```
|
|
||||||
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
|
||||||
│ Mycelium │ │ NodePort │ │ Pod Network │
|
|
||||||
│ IPv6 Network │───▶│ Service │───▶│ (Isolated) │
|
|
||||||
│ :30090 │ │ :8080 │ │ :8080 │
|
|
||||||
└─────────────────┘ └──────────────────┘ └─────────────────┘
|
|
||||||
│ │
|
|
||||||
▼ ▼
|
|
||||||
┌──────────────────┐ ┌─────────────────┐
|
|
||||||
│ K8s Service │ │ Pod Namespace │
|
|
||||||
│ Load Balancer │ │ Isolation │
|
|
||||||
└──────────────────┘ └─────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌──────────────────┐
|
|
||||||
│ ConfigMaps │
|
|
||||||
│ • HTML Content │
|
|
||||||
│ • nginx Config │
|
|
||||||
└──────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
**Key characteristics:**
|
|
||||||
- Pod runs in isolated network namespace
|
|
||||||
- Traffic flows through Kubernetes service
|
|
||||||
- Network policy enforcement possible
|
|
||||||
- Standard Kubernetes networking patterns
|
|
||||||
- Enhanced security through isolation
|
|
||||||
|
|
||||||
**Configuration:**
|
|
||||||
```yaml
|
|
||||||
spec:
|
|
||||||
hostNetwork: false # Isolated pod network
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
ports:
|
|
||||||
- containerPort: 8080 # No hostPort needed
|
|
||||||
---
|
|
||||||
spec:
|
|
||||||
type: NodePort
|
|
||||||
externalTrafficPolicy: Local # Preserves IPv6 source IP
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🛡️ Security Analysis
|
|
||||||
|
|
||||||
### Security Threats and Mitigations
|
|
||||||
|
|
||||||
| Threat | hostNetwork Risk | NodePort Mitigation |
|
|
||||||
|--------|------------------|-------------------|
|
|
||||||
| **Pod Escape** | ⚠️ High - Direct host access | ✅ Low - Isolated namespace |
|
|
||||||
| **Port Conflicts** | ⚠️ High - Limited available ports | ✅ Low - No host port binding |
|
|
||||||
| **Network Policy Bypass** | ⚠️ High - Direct host interface | ✅ Low - K8s network policies |
|
|
||||||
| **Resource Starvation** | ⚠️ High - Direct host resources | ✅ Low - Resource limits enforced |
|
|
||||||
| **Service Discovery Abuse** | ⚠️ Medium - Direct access | ✅ Low - Service mesh protection |
|
|
||||||
| **Traffic Interception** | ⚠️ High - Host-level access | ✅ Low - Encrypted service traffic |
|
|
||||||
|
|
||||||
### Network Isolation Comparison
|
|
||||||
|
|
||||||
**hostNetwork (nginx-mycelium):**
|
|
||||||
- **No isolation**: Pod shares host network stack
|
|
||||||
- **Direct access**: Can access all host network interfaces
|
|
||||||
- **No K8s networking**: Bypasses service mesh and policies
|
|
||||||
- **Host dependencies**: Subject to host network issues
|
|
||||||
|
|
||||||
**NodePort (nginx-nodeport):**
|
|
||||||
- **Full isolation**: Pod in separate network namespace
|
|
||||||
- **K8s networking**: Uses standard service discovery
|
|
||||||
- **Policy enforcement**: Network policies can control traffic
|
|
||||||
- **Resource isolation**: Separate network resources
|
|
||||||
|
|
||||||
## 📊 Performance Analysis
|
|
||||||
|
|
||||||
### Network Performance
|
|
||||||
|
|
||||||
| Metric | hostNetwork | NodePort | Winner |
|
|
||||||
|--------|-------------|----------|---------|
|
|
||||||
| **Latency** | ~1-2ms | ~2-3ms | hostNetwork (minimal) |
|
|
||||||
| **Throughput** | Native | Slight overhead | hostNetwork |
|
|
||||||
| **CPU Usage** | Lower | Slight overhead | hostNetwork |
|
|
||||||
| **Memory Usage** | Lower | Standard K8s overhead | hostNetwork |
|
|
||||||
| **Connection Overhead** | None | Service routing | hostNetwork |
|
|
||||||
|
|
||||||
### Resource Usage
|
|
||||||
|
|
||||||
**hostNetwork:**
|
|
||||||
```
|
|
||||||
Pod Resource Usage:
|
|
||||||
- CPU: ~10-15% for nginx
|
|
||||||
- Memory: ~30-50MB
|
|
||||||
- Network: Direct host interface
|
|
||||||
- Storage: ConfigMap mounting only
|
|
||||||
```
|
|
||||||
|
|
||||||
**NodePort:**
|
|
||||||
```
|
|
||||||
Pod Resource Usage:
|
|
||||||
- CPU: ~15-20% for nginx + K8s overhead
|
|
||||||
- Memory: ~50-80MB
|
|
||||||
- Network: K8s service networking
|
|
||||||
- Storage: ConfigMap mounting + K8s components
|
|
||||||
```
|
|
||||||
|
|
||||||
### Scalability Comparison
|
|
||||||
|
|
||||||
**hostNetwork Limitations:**
|
|
||||||
- Single instance per host (port conflicts)
|
|
||||||
- Manual load balancing required
|
|
||||||
- No automatic failover
|
|
||||||
- Limited to available host ports
|
|
||||||
- No service discovery
|
|
||||||
|
|
||||||
**NodePort Advantages:**
|
|
||||||
- Multiple replicas across cluster
|
|
||||||
- Automatic load balancing
|
|
||||||
- Built-in service discovery
|
|
||||||
- No port conflicts
|
|
||||||
- Standard K8s scaling patterns
|
|
||||||
|
|
||||||
## 🔧 Operational Complexity
|
|
||||||
|
|
||||||
### Deployment and Management
|
|
||||||
|
|
||||||
**hostNetwork (nginx-mycelium):**
|
|
||||||
- ✅ Simple deployment
|
|
||||||
- ✅ No service configuration needed
|
|
||||||
- ✅ Direct debugging on host
|
|
||||||
- ⚠️ Manual port management
|
|
||||||
- ⚠️ Host-level troubleshooting required
|
|
||||||
- ⚠️ No standard K8s tools
|
|
||||||
|
|
||||||
**NodePort (nginx-nodeport):**
|
|
||||||
- ✅ Standard K8s patterns
|
|
||||||
- ✅ Service-level load balancing
|
|
||||||
- ✅ Standard debugging tools
|
|
||||||
- ✅ Network policy support
|
|
||||||
- ✅ Horizontal pod autoscaling
|
|
||||||
- ✅ Ingress controller compatible
|
|
||||||
|
|
||||||
### Monitoring and Observability
|
|
||||||
|
|
||||||
**hostNetwork:**
|
|
||||||
- ⚠️ Host-level monitoring only
|
|
||||||
- ⚠️ No pod-level metrics
|
|
||||||
- ⚠️ Custom logging required
|
|
||||||
- ⚠️ Limited health check options
|
|
||||||
|
|
||||||
**NodePort:**
|
|
||||||
- ✅ Full K8s monitoring stack
|
|
||||||
- ✅ Pod-level metrics and logging
|
|
||||||
- ✅ Standard health probes
|
|
||||||
- ✅ Service mesh integration
|
|
||||||
|
|
||||||
## 🎯 Use Case Recommendations
|
|
||||||
|
|
||||||
### When to Use hostNetwork (nginx-mycelium)
|
|
||||||
|
|
||||||
**✅ Recommended for:**
|
|
||||||
- **Learning and experimentation** - Simple, direct networking
|
|
||||||
- **Maximum performance requirements** - Minimal overhead
|
|
||||||
- **Legacy applications** - Existing host-networked apps
|
|
||||||
- **Simple demos and POCs** - Quick deployment needs
|
|
||||||
- **Single-instance applications** - No scaling requirements
|
|
||||||
|
|
||||||
**❌ Not recommended for:**
|
|
||||||
- **Production environments** - Security concerns
|
|
||||||
- **Multi-tenant systems** - Isolation requirements
|
|
||||||
- **Compliance requirements** - Security auditing
|
|
||||||
- **Microservices architectures** - Service mesh integration
|
|
||||||
- **High-availability systems** - No built-in failover
|
|
||||||
|
|
||||||
### When to Use NodePort (nginx-nodeport)
|
|
||||||
|
|
||||||
**✅ Recommended for:**
|
|
||||||
- **Production deployments** - Enhanced security
|
|
||||||
- **Multi-replica applications** - Load balancing
|
|
||||||
- **Microservices** - Service discovery and policies
|
|
||||||
- **Compliance requirements** - Audit trails and isolation
|
|
||||||
- **Enterprise applications** - Standard K8s patterns
|
|
||||||
- **Development environments** - Standard debugging tools
|
|
||||||
|
|
||||||
**❌ Not recommended for:**
|
|
||||||
- **Extreme low-latency** - Additional network hop
|
|
||||||
- **Resource-constrained environments** - K8s overhead
|
|
||||||
- **Simple learning projects** - May be overkill
|
|
||||||
|
|
||||||
## 🚀 Migration Strategy
|
|
||||||
|
|
||||||
### From hostNetwork to NodePort
|
|
||||||
|
|
||||||
**Step 1: Security Assessment**
|
|
||||||
```bash
|
|
||||||
# Review current hostNetwork deployments
|
|
||||||
kubectl get pods -o yaml | grep -A 5 "hostNetwork"
|
|
||||||
|
|
||||||
# Identify security requirements
|
|
||||||
# Document current port usage
|
|
||||||
# Check for compliance requirements
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 2: Migration Planning**
|
|
||||||
```bash
|
|
||||||
# Plan service configuration
|
|
||||||
# Design load balancing strategy
|
|
||||||
# Update monitoring and alerting
|
|
||||||
# Test migration in staging environment
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 3: Incremental Migration**
|
|
||||||
```bash
|
|
||||||
# Deploy NodePort version alongside hostNetwork
|
|
||||||
# Update DNS/load balancer configuration
|
|
||||||
# Monitor performance and functionality
|
|
||||||
# Gradually shift traffic
|
|
||||||
# Remove hostNetwork deployment
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 4: Validation**
|
|
||||||
```bash
|
|
||||||
# Test all functionality
|
|
||||||
# Verify security improvements
|
|
||||||
# Update documentation and runbooks
|
|
||||||
# Train operations team
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📈 Performance Benchmarking
|
|
||||||
|
|
||||||
### Test Setup
|
|
||||||
- **Environment**: Mycelium Cloud 3-master, 3-worker cluster
|
|
||||||
- **Load**: 1000 requests/second for 5 minutes
|
|
||||||
- **Tools**: Apache Bench (ab) and wrk
|
|
||||||
- **Metrics**: Latency, throughput, error rate
|
|
||||||
|
|
||||||
### Expected Results
|
|
||||||
|
|
||||||
**hostNetwork Performance:**
|
|
||||||
```
|
|
||||||
Requests per second: 1200-1500
|
|
||||||
Mean latency: 1.2ms
|
|
||||||
95th percentile: 2.1ms
|
|
||||||
Error rate: 0.01%
|
|
||||||
CPU usage: 12%
|
|
||||||
Memory usage: 45MB
|
|
||||||
```
|
|
||||||
|
|
||||||
**NodePort Performance:**
|
|
||||||
```
|
|
||||||
Requests per second: 1100-1400
|
|
||||||
Mean latency: 1.8ms
|
|
||||||
95th percentile: 2.8ms
|
|
||||||
Error rate: 0.01%
|
|
||||||
CPU usage: 16%
|
|
||||||
Memory usage: 65MB
|
|
||||||
```
|
|
||||||
|
|
||||||
**Performance Trade-off:** ~10-15% overhead for significantly improved security and operational capabilities.
|
|
||||||
|
|
||||||
## 🔄 Best Practices Summary
|
|
||||||
|
|
||||||
### Security Best Practices
|
|
||||||
|
|
||||||
1. **Default to NodePort** - Use hostNetwork only when justified
|
|
||||||
2. **Regular security audits** - Review network access patterns
|
|
||||||
3. **Implement network policies** - Control east-west traffic
|
|
||||||
4. **Use RBAC** - Limit service account permissions
|
|
||||||
5. **Enable audit logging** - Track all network access
|
|
||||||
|
|
||||||
### Performance Best Practices
|
|
||||||
|
|
||||||
1. **Monitor resource usage** - Track CPU/memory metrics
|
|
||||||
2. **Implement health checks** - Use liveness and readiness probes
|
|
||||||
3. **Configure resource limits** - Prevent resource exhaustion
|
|
||||||
4. **Use connection pooling** - Optimize nginx configuration
|
|
||||||
5. **Implement caching** - Reduce backend load
|
|
||||||
|
|
||||||
### Operational Best Practices
|
|
||||||
|
|
||||||
1. **Use GitOps** - Manage configurations as code
|
|
||||||
2. **Implement monitoring** - Full observability stack
|
|
||||||
3. **Regular testing** - Automated testing and validation
|
|
||||||
4. **Documentation** - Keep runbooks updated
|
|
||||||
5. **Team training** - Ensure competency in chosen approach
|
|
||||||
|
|
||||||
## 🎯 Decision Matrix
|
|
||||||
|
|
||||||
### Score each criterion (1-5 scale) for your use case:
|
|
||||||
|
|
||||||
| Criterion | Weight | hostNetwork Score | NodePort Score | Weighted Score |
|
|
||||||
|-----------|--------|-------------------|----------------|----------------|
|
|
||||||
| **Security** | 5 | 2 | 5 | HN: 10, NP: 25 |
|
|
||||||
| **Performance** | 4 | 5 | 4 | HN: 20, NP: 16 |
|
|
||||||
| **Simplicity** | 3 | 5 | 4 | HN: 15, NP: 12 |
|
|
||||||
| **Scalability** | 4 | 2 | 5 | HN: 8, NP: 20 |
|
|
||||||
| **Production Readiness** | 5 | 2 | 5 | HN: 10, NP: 25 |
|
|
||||||
| **Compliance** | 4 | 1 | 5 | HN: 4, NP: 20 |
|
|
||||||
| **Team Expertise** | 3 | 3 | 5 | HN: 9, NP: 15 |
|
|
||||||
|
|
||||||
**Score Interpretation:**
|
|
||||||
- **Total > 100**: NodePort recommended
|
|
||||||
- **Total 70-100**: Consider NodePort with justification
|
|
||||||
- **Total < 70**: hostNetwork acceptable
|
|
||||||
|
|
||||||
## 📚 Additional Resources
|
|
||||||
|
|
||||||
### Documentation
|
|
||||||
- [Kubernetes Network Policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/)
|
|
||||||
- [Kubernetes Services](https://kubernetes.io/docs/concepts/services-networking/service/)
|
|
||||||
- [Mycelium Cloud Networking Guide](https://docs.mycelium.cloud/networking)
|
|
||||||
|
|
||||||
### Tools and Utilities
|
|
||||||
- **kubectl network policy generator**
|
|
||||||
- **Kubernetes service mesh (Istio/Linkerd)**
|
|
||||||
- **Network policy visualizer**
|
|
||||||
- **Performance monitoring (Prometheus/Grafana)**
|
|
||||||
|
|
||||||
### Community and Support
|
|
||||||
- **Mycelium Cloud Community**: [community.mycelium.cloud](https://community.mycelium.cloud)
|
|
||||||
- **Kubernetes Slack**: #kubernetes-newbies
|
|
||||||
- **GitHub Discussions**: [myceliumcloud-examples](https://github.com/myceliumcloud/examples)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Recommendation**: For production environments and most real-world use cases, the **NodePort approach** provides significantly better security, operational capabilities, and compliance posture with only minimal performance overhead. Reserve the **hostNetwork approach** for learning, development, and specific high-performance requirements where security is not a concern.
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# NodePort Connectivity Debug Script
|
|
||||||
# Diagnoses why NodePort 30091 is not accessible despite successful ping
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "🔍 NodePort Connectivity Diagnosis"
|
|
||||||
echo "===================================="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Colors
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
RED='\033[0;31m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# Get pod info
|
|
||||||
POD_NAME=$(kubectl get pods -l app=nginx-nodeport -o name | head -1)
|
|
||||||
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]+:' | head -1)
|
|
||||||
|
|
||||||
echo "📊 Pod Information:"
|
|
||||||
echo " Pod: $POD_NAME"
|
|
||||||
echo " Node: $POD_NODE"
|
|
||||||
echo " Node IPv6: $NODE_IPV6"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check service
|
|
||||||
echo "🔍 Service Configuration:"
|
|
||||||
kubectl get svc nginx-nodeport-service -o yaml | grep -E "type:|nodePort:|externalTrafficPolicy:|ipFamilies:" | sed 's/^/ /'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check endpoints
|
|
||||||
echo "🔍 Service Endpoints:"
|
|
||||||
kubectl get endpoints nginx-nodeport-service -o wide
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Test from within pod
|
|
||||||
echo "🧪 Test 1: Internal pod access (localhost)"
|
|
||||||
if kubectl exec $POD_NAME -- curl -s -m 5 http://localhost:8080/health > /dev/null 2>&1; then
|
|
||||||
echo -e " ${GREEN}✅ SUCCESS${NC} - nginx responding on localhost:8080"
|
|
||||||
else
|
|
||||||
echo -e " ${RED}❌ FAILED${NC} - nginx not responding internally"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Test service ClusterIP
|
|
||||||
echo "🧪 Test 2: Service ClusterIP access"
|
|
||||||
SERVICE_IP=$(kubectl get svc nginx-nodeport-service -o jsonpath='{.spec.clusterIP}')
|
|
||||||
echo " Service ClusterIP: $SERVICE_IP"
|
|
||||||
|
|
||||||
# Create a test pod to check from
|
|
||||||
echo " Creating test pod..."
|
|
||||||
kubectl run test-curl --image=curlimages/curl:latest --rm -i --restart=Never --command -- sh -c "curl -s -m 5 http://$SERVICE_IP:8080/health" > /tmp/test-result.txt 2>&1 || true
|
|
||||||
|
|
||||||
if grep -q "healthy" /tmp/test-result.txt 2>/dev/null; then
|
|
||||||
echo -e " ${GREEN}✅ SUCCESS${NC} - Service ClusterIP accessible"
|
|
||||||
else
|
|
||||||
echo -e " ${YELLOW}⚠️ FAILED${NC} - Service ClusterIP not accessible"
|
|
||||||
cat /tmp/test-result.txt 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
rm -f /tmp/test-result.txt
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if kube-proxy is running
|
|
||||||
echo "🔍 kube-proxy Status:"
|
|
||||||
KUBE_PROXY_PODS=$(kubectl get pods -n kube-system -l k8s-app=kube-proxy --no-headers 2>/dev/null | wc -l)
|
|
||||||
if [ "$KUBE_PROXY_PODS" -gt 0 ]; then
|
|
||||||
echo -e " ${GREEN}✅ kube-proxy running${NC} ($KUBE_PROXY_PODS pods)"
|
|
||||||
else
|
|
||||||
echo -e " ${RED}❌ kube-proxy NOT running${NC}"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check node ports
|
|
||||||
echo "🔍 NodePort Listener Check:"
|
|
||||||
echo " Checking if port 30091 is being listened on..."
|
|
||||||
echo ""
|
|
||||||
echo " Note: On the worker node ($POD_NODE), check with:"
|
|
||||||
echo " ssh root@$POD_NODE 'netstat -tuln | grep 30091'"
|
|
||||||
echo " ssh root@$POD_NODE 'ss -tuln | grep 30091'"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Try to access NodePort from inside cluster
|
|
||||||
echo "🧪 Test 3: NodePort access from test pod"
|
|
||||||
echo " Testing: http://[$NODE_IPV6]:30091/"
|
|
||||||
|
|
||||||
kubectl run test-nodeport --image=curlimages/curl:latest --rm -i --restart=Never --command -- sh -c "curl -6 -s -m 10 http://[$NODE_IPV6]:30091/health" > /tmp/nodeport-test.txt 2>&1 || true
|
|
||||||
|
|
||||||
if grep -q "healthy" /tmp/nodeport-test.txt 2>/dev/null; then
|
|
||||||
echo -e " ${GREEN}✅ SUCCESS${NC} - NodePort accessible from within cluster"
|
|
||||||
else
|
|
||||||
echo -e " ${RED}❌ FAILED${NC} - NodePort not accessible from within cluster"
|
|
||||||
echo " Output:"
|
|
||||||
cat /tmp/nodeport-test.txt 2>/dev/null | sed 's/^/ /' || true
|
|
||||||
fi
|
|
||||||
rm -f /tmp/nodeport-test.txt
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check iptables rules (if we can access the node)
|
|
||||||
echo "🔍 Potential Issues:"
|
|
||||||
echo ""
|
|
||||||
echo " 1. IPv6 Support in kube-proxy:"
|
|
||||||
echo " kube-proxy might not be configured for IPv6"
|
|
||||||
echo " Check with: kubectl logs -n kube-system -l k8s-app=kube-proxy | grep -i ipv6"
|
|
||||||
echo ""
|
|
||||||
echo " 2. Firewall on worker node:"
|
|
||||||
echo " Port 30091 might be blocked by firewall"
|
|
||||||
echo " On node: sudo iptables -L -n | grep 30091"
|
|
||||||
echo " On node: sudo ip6tables -L -n | grep 30091"
|
|
||||||
echo ""
|
|
||||||
echo " 3. externalTrafficPolicy: Local:"
|
|
||||||
echo " Service only accessible on the node where pod is running"
|
|
||||||
echo " Pod is on: $POD_NODE"
|
|
||||||
echo " You must use that node's IPv6: $NODE_IPV6"
|
|
||||||
echo ""
|
|
||||||
echo " 4. IPv6 iptables rules:"
|
|
||||||
echo " kube-proxy might not have created IPv6 rules"
|
|
||||||
echo " On node: sudo ip6tables -t nat -L -n | grep 30091"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Get all node IPs to show which one to use
|
|
||||||
echo "📋 Summary:"
|
|
||||||
echo ""
|
|
||||||
echo " Pod running on node: $POD_NODE"
|
|
||||||
echo " MUST use this IPv6: $NODE_IPV6"
|
|
||||||
echo ""
|
|
||||||
echo " Try accessing:"
|
|
||||||
echo " curl -6 \"http://[$NODE_IPV6]:30091/\""
|
|
||||||
echo ""
|
|
||||||
echo " All worker node IPs (for reference):"
|
|
||||||
kubectl get nodes -o jsonpath='{range .items[*]}{range .status.addresses[?(@.type=="InternalIP")]}{.address}{"\n"}{end}{end}' | grep -E '^[0-9a-f]+:[0-9a-f]+:' | nl -v 1 -w 5 -s '. ' | sed 's/^/ /'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Suggest checking k3s/k8s configuration
|
|
||||||
echo "🔧 Recommended Checks:"
|
|
||||||
echo ""
|
|
||||||
echo "1. Check if this is a K3s cluster:"
|
|
||||||
echo " kubectl version --short"
|
|
||||||
echo ""
|
|
||||||
echo "2. Check kube-proxy mode:"
|
|
||||||
echo " kubectl logs -n kube-system -l k8s-app=kube-proxy | grep -i mode"
|
|
||||||
echo ""
|
|
||||||
echo "3. Check if IPv6 is enabled in cluster:"
|
|
||||||
echo " kubectl get nodes -o jsonpath='{.items[0].status.addresses}' | grep ':'"
|
|
||||||
echo ""
|
|
||||||
echo "4. Check service IP families:"
|
|
||||||
echo " kubectl get svc nginx-nodeport-service -o jsonpath='{.spec.ipFamilies}'"
|
|
||||||
echo ""
|
|
||||||
echo "5. Try changing externalTrafficPolicy to Cluster:"
|
|
||||||
echo " kubectl patch svc nginx-nodeport-service -p '{\"spec\":{\"externalTrafficPolicy\":\"Cluster\"}}'"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "======================================"
|
|
||||||
echo "Diagnosis complete!"
|
|
||||||
@@ -1,355 +0,0 @@
|
|||||||
# Deployment Troubleshooting Guide for nginx-nodeport
|
|
||||||
|
|
||||||
This guide helps resolve common connectivity and deployment issues with the nginx-nodeport implementation.
|
|
||||||
|
|
||||||
## 🚨 Common Connection Issues
|
|
||||||
|
|
||||||
### Issue 1: API Server Timeout
|
|
||||||
**Error**: `dial tcp [IPv6]:6443: i/o timeout`
|
|
||||||
|
|
||||||
**Cause**: Kubernetes API server is slow to respond or network connectivity issues.
|
|
||||||
|
|
||||||
**Solutions**:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Option 1: Disable API validation (faster deployment)
|
|
||||||
kubectl apply -f nginx-nodeport-configmaps.yaml --validate=false
|
|
||||||
kubectl apply -f nginx-nodeport-deployment.yaml --validate=false
|
|
||||||
kubectl apply -f nginx-nodeport-service.yaml --validate=false
|
|
||||||
|
|
||||||
# Option 2: Use client-side dry-run to verify YAML syntax
|
|
||||||
kubectl apply -f nginx-nodeport-configmaps.yaml --dry-run=client
|
|
||||||
kubectl apply -f nginx-nodeport-deployment.yaml --dry-run=client
|
|
||||||
kubectl apply -f nginx-nodeport-service.yaml --dry-run=client
|
|
||||||
|
|
||||||
# Option 3: Increase timeout
|
|
||||||
kubectl apply -f nginx-nodeport-configmaps.yaml --timeout=5m
|
|
||||||
```
|
|
||||||
|
|
||||||
### Issue 2: Network Connectivity Problems
|
|
||||||
**Error**: `Unable to connect to the server`
|
|
||||||
|
|
||||||
**Diagnose and Fix**:
|
|
||||||
```bash
|
|
||||||
# Check cluster connectivity
|
|
||||||
kubectl cluster-info
|
|
||||||
|
|
||||||
# Check node status
|
|
||||||
kubectl get nodes
|
|
||||||
|
|
||||||
# Verify kubeconfig
|
|
||||||
kubectl config view
|
|
||||||
|
|
||||||
# Test basic connectivity
|
|
||||||
kubectl get pods --all-namespaces
|
|
||||||
```
|
|
||||||
|
|
||||||
### Issue 3: Slow API Responses
|
|
||||||
**Error**: Operations take very long or timeout
|
|
||||||
|
|
||||||
**Performance Optimizations**:
|
|
||||||
```bash
|
|
||||||
# Use smaller output formats
|
|
||||||
kubectl get pods -l app=nginx-nodeport -o wide
|
|
||||||
|
|
||||||
# Disable unnecessary features
|
|
||||||
kubectl apply -f nginx-nodeport-configmaps.yaml --v=1
|
|
||||||
|
|
||||||
# Use specific resource targeting
|
|
||||||
kubectl apply -f nginx-nodeport-configmaps.yaml --namespace=default
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔍 Pre-Deployment Validation
|
|
||||||
|
|
||||||
### YAML Syntax Validation (No Cluster Required)
|
|
||||||
```bash
|
|
||||||
# Validate all files without cluster connection
|
|
||||||
for file in *.yaml; do
|
|
||||||
echo "Validating $file..."
|
|
||||||
kubectl create -f "$file" --dry-run=client --validate=false
|
|
||||||
done
|
|
||||||
```
|
|
||||||
|
|
||||||
### File-by-File Validation
|
|
||||||
```bash
|
|
||||||
# Test each component individually
|
|
||||||
echo "=== Testing ConfigMaps ==="
|
|
||||||
kubectl apply -f nginx-nodeport-configmaps.yaml --dry-run=client
|
|
||||||
|
|
||||||
echo "=== Testing Deployment ==="
|
|
||||||
kubectl apply -f nginx-nodeport-deployment.yaml --dry-run=client
|
|
||||||
|
|
||||||
echo "=== Testing Service ==="
|
|
||||||
kubectl apply -f nginx-nodeport-service.yaml --dry-run=client
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🚀 Alternative Deployment Methods
|
|
||||||
|
|
||||||
### Method 1: Manual Resource Creation
|
|
||||||
If `kubectl apply` fails, create resources manually:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Create ConfigMaps
|
|
||||||
kubectl create configmap nginx-nodeport-content --from-literal=index.html="<h1>Hello NodePort</h1>"
|
|
||||||
kubectl create configmap nginx-nodeport-nginx-config --from-literal=default.conf="server { listen 8080; }"
|
|
||||||
|
|
||||||
# 2. Create Deployment
|
|
||||||
kubectl create deployment nginx-nodeport --image=nginx:alpine --replicas=1
|
|
||||||
|
|
||||||
# 3. Expose Service
|
|
||||||
kubectl expose deployment nginx-nodeport --type=NodePort --port=8080 --target-port=8080
|
|
||||||
```
|
|
||||||
|
|
||||||
### Method 2: Using Helm (Advanced)
|
|
||||||
Create a Helm chart for easier deployment:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install Helm if not present
|
|
||||||
# Then package and deploy
|
|
||||||
helm package .
|
|
||||||
helm install nginx-nodeport ./nginx-nodeport-0.1.0.tgz
|
|
||||||
```
|
|
||||||
|
|
||||||
### Method 3: Scripted Deployment
|
|
||||||
Use the provided deployment script:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Make script executable
|
|
||||||
chmod +x deploy-nginx-nodeport.sh
|
|
||||||
|
|
||||||
# Run automated deployment
|
|
||||||
./deploy-nginx-nodeport.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🛠️ Creating deployment-nginx-nodeport.sh
|
|
||||||
|
|
||||||
Let me create a robust deployment script that handles connectivity issues:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# nginx-nodeport Deployment Script
|
|
||||||
# Handles connectivity issues and provides fallback options
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "🚀 Deploying nginx-nodeport to Mycelium Cloud"
|
|
||||||
echo "=============================================="
|
|
||||||
|
|
||||||
# Colors
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
RED='\033[0;31m'
|
|
||||||
NC='\033[0m'
|
|
||||||
|
|
||||||
print_success() { echo -e "${GREEN}✅ $1${NC}"; }
|
|
||||||
print_warning() { echo -e "${YELLOW}⚠️ $1${NC}"; }
|
|
||||||
print_error() { echo -e "${RED}❌ $1${NC}"; }
|
|
||||||
|
|
||||||
# Function to deploy with fallback options
|
|
||||||
deploy_with_fallback() {
|
|
||||||
local file=$1
|
|
||||||
local name=$2
|
|
||||||
|
|
||||||
echo "📋 Deploying $name..."
|
|
||||||
|
|
||||||
# Try normal deployment
|
|
||||||
if kubectl apply -f "$file" --validate=false 2>/dev/null; then
|
|
||||||
print_success "$name deployed successfully"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Try with client validation only
|
|
||||||
print_warning "Normal deployment failed, trying client-side validation..."
|
|
||||||
if kubectl apply -f "$file" --dry-run=client --validate=false 2>/dev/null; then
|
|
||||||
print_warning "$name validated (client-side only) - cluster may be unavailable"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Try manual creation for specific resource types
|
|
||||||
print_error "$name deployment failed completely"
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check cluster connectivity
|
|
||||||
echo "🔍 Checking cluster connectivity..."
|
|
||||||
if kubectl cluster-info &>/dev/null; then
|
|
||||||
print_success "Cluster is accessible"
|
|
||||||
CLUSTER_AVAILABLE=true
|
|
||||||
else
|
|
||||||
print_warning "Cluster is not accessible - will use client-side validation only"
|
|
||||||
CLUSTER_AVAILABLE=false
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Deploy ConfigMaps
|
|
||||||
if [ "$CLUSTER_AVAILABLE" = true ]; then
|
|
||||||
deploy_with_fallback "nginx-nodeport-configmaps.yaml" "ConfigMaps"
|
|
||||||
else
|
|
||||||
echo "🔍 Validating ConfigMaps (client-side)..."
|
|
||||||
if kubectl create -f nginx-nodeport-configmaps.yaml --dry-run=client --validate=false &>/dev/null; then
|
|
||||||
print_success "ConfigMaps validated (client-side)"
|
|
||||||
else
|
|
||||||
print_error "ConfigMaps validation failed"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Deploy Deployment
|
|
||||||
if [ "$CLUSTER_AVAILABLE" = true ]; then
|
|
||||||
deploy_with_fallback "nginx-nodeport-deployment.yaml" "Deployment"
|
|
||||||
else
|
|
||||||
echo "🔍 Validating Deployment (client-side)..."
|
|
||||||
if kubectl create -f nginx-nodeport-deployment.yaml --dry-run=client --validate=false &>/dev/null; then
|
|
||||||
print_success "Deployment validated (client-side)"
|
|
||||||
else
|
|
||||||
print_error "Deployment validation failed"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Deploy Service
|
|
||||||
if [ "$CLUSTER_AVAILABLE" = true ]; then
|
|
||||||
deploy_with_fallback "nginx-nodeport-service.yaml" "Service"
|
|
||||||
else
|
|
||||||
echo "🔍 Validating Service (client-side)..."
|
|
||||||
if kubectl create -f nginx-nodeport-service.yaml --dry-run=client --validate=false &>/dev/null; then
|
|
||||||
print_success "Service validated (client-side)"
|
|
||||||
else
|
|
||||||
print_error "Service validation failed"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Final status
|
|
||||||
if [ "$CLUSTER_AVAILABLE" = true ]; then
|
|
||||||
echo ""
|
|
||||||
echo "🎉 Deployment Complete!"
|
|
||||||
echo "======================"
|
|
||||||
echo "📊 Checking deployment status..."
|
|
||||||
kubectl get all -l app=nginx-nodeport
|
|
||||||
|
|
||||||
# Get access information
|
|
||||||
NODE_IPV6=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}' 2>/dev/null || echo "YOUR-NODE-IPV6")
|
|
||||||
echo ""
|
|
||||||
echo "🌐 Access your website at: http://[$NODE_IPV6]:30090"
|
|
||||||
echo "🧪 Run health check: curl -6 http://[$NODE_IPV6]:30090/health"
|
|
||||||
echo "📋 Test script: ./test-nodeport-ipv6.sh"
|
|
||||||
else
|
|
||||||
echo ""
|
|
||||||
print_warning "Deployment files are valid but cluster is not accessible"
|
|
||||||
echo "📝 When cluster becomes available, run:"
|
|
||||||
echo " kubectl apply -f nginx-nodeport-configmaps.yaml --validate=false"
|
|
||||||
echo " kubectl apply -f nginx-nodeport-deployment.yaml --validate=false"
|
|
||||||
echo " kubectl apply -f nginx-nodeport-service.yaml --validate=false"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📚 Next Steps:"
|
|
||||||
echo " • Check documentation: nginx-nodeport.md"
|
|
||||||
echo " • Compare approaches: compare-approaches.md"
|
|
||||||
echo " • Run validation: deployment-validation.md"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🧪 Testing Without Cluster
|
|
||||||
|
|
||||||
### Syntax Validation
|
|
||||||
```bash
|
|
||||||
# Test all YAML files for syntax errors
|
|
||||||
for file in *.yaml; do
|
|
||||||
echo "Testing $file syntax..."
|
|
||||||
python3 -c "
|
|
||||||
import yaml
|
|
||||||
import sys
|
|
||||||
try:
|
|
||||||
with open('$file') as f:
|
|
||||||
yaml.safe_load_all(f)
|
|
||||||
print('✅ $file: Valid YAML')
|
|
||||||
except Exception as e:
|
|
||||||
print('❌ $file: Invalid -', str(e))
|
|
||||||
sys.exit(1)
|
|
||||||
"
|
|
||||||
done
|
|
||||||
```
|
|
||||||
|
|
||||||
### Lint Kubernetes YAML
|
|
||||||
```bash
|
|
||||||
# Install kube-linter if not present
|
|
||||||
# wget https://github.com/stackrox/kube-linter/releases/download/v0.6.0/kube-linter_Linux_x86_64.tar.gz
|
|
||||||
# tar xzf kube-linter_Linux_x86_64.tar.gz
|
|
||||||
# sudo mv kube-linter /usr/local/bin/
|
|
||||||
|
|
||||||
# Lint all files
|
|
||||||
kube-linter lint *.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔧 Cluster-Specific Issues
|
|
||||||
|
|
||||||
### Mycelium Cloud Specific
|
|
||||||
```bash
|
|
||||||
# Check Mycelium-specific connectivity
|
|
||||||
kubectl get nodes -o wide
|
|
||||||
kubectl describe node | grep -A 5 -B 5 "Addresses"
|
|
||||||
|
|
||||||
# Test IPv6 connectivity
|
|
||||||
ping6 -c 3 $(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')
|
|
||||||
|
|
||||||
# Check Mycelium network plugin
|
|
||||||
kubectl get pods -n kube-system | grep mycelium
|
|
||||||
```
|
|
||||||
|
|
||||||
### Local Development Clusters
|
|
||||||
```bash
|
|
||||||
# For minikube
|
|
||||||
minikube status
|
|
||||||
minikube start --driver=docker
|
|
||||||
|
|
||||||
# For kind
|
|
||||||
kind get clusters
|
|
||||||
kind create cluster --name mycelium-test
|
|
||||||
|
|
||||||
# For k3s
|
|
||||||
sudo systemctl status k3s
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📊 Performance Optimization
|
|
||||||
|
|
||||||
### Faster Operations
|
|
||||||
```bash
|
|
||||||
# Use shorter timeouts for faster failure
|
|
||||||
kubectl get pods --timeout=30s
|
|
||||||
|
|
||||||
# Reduce verbosity
|
|
||||||
kubectl get pods -l app=nginx-nodeport -o json
|
|
||||||
|
|
||||||
# Use specific namespaces
|
|
||||||
kubectl config set-context --current --namespace=default
|
|
||||||
```
|
|
||||||
|
|
||||||
### Resource-Afficient Queries
|
|
||||||
```bash
|
|
||||||
# Lightweight status checks
|
|
||||||
kubectl get pods -l app=nginx-nodeport --no-headers
|
|
||||||
|
|
||||||
# Minimal output
|
|
||||||
kubectl get svc nginx-nodeport-service -o name
|
|
||||||
|
|
||||||
# Batch operations
|
|
||||||
kubectl get deployment,svc,configmap -l app=nginx-nodeport
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🆘 Emergency Deployment
|
|
||||||
|
|
||||||
If all else fails, here's a minimal emergency deployment:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Emergency nginx deployment
|
|
||||||
kubectl create deployment emergency-nginx --image=nginx:alpine
|
|
||||||
kubectl expose deployment emergency-nginx --type=NodePort --port=80
|
|
||||||
kubectl patch service emergency-nginx -p '{"spec":{"ports":[{"port":80,"targetPort":80,"nodePort":30090}]}}'
|
|
||||||
|
|
||||||
# Get access
|
|
||||||
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')
|
|
||||||
echo "Emergency site: http://$NODE_IP:30090"
|
|
||||||
```
|
|
||||||
|
|
||||||
This comprehensive troubleshooting guide should help resolve most deployment issues and provide multiple fallback options for different scenarios.
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
# Nginx-NodePort Deployment Validation Guide
|
|
||||||
|
|
||||||
This document provides step-by-step deployment and validation procedures for the nginx-nodeport implementation.
|
|
||||||
|
|
||||||
## 🚀 Deployment Instructions
|
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
- Kubernetes cluster access (kubectl configured)
|
|
||||||
- Mycelium Cloud environment with IPv6 support
|
|
||||||
- bash shell for running test scripts
|
|
||||||
|
|
||||||
### Step-by-Step Deployment
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Navigate to the nginx-nodeport directory
|
|
||||||
cd myceliumcloud-examples/examples/nginx-nodeport
|
|
||||||
|
|
||||||
# 2. Deploy the ConfigMaps (content and nginx configuration)
|
|
||||||
kubectl apply -f nginx-nodeport-configmaps.yaml
|
|
||||||
|
|
||||||
# 3. Deploy the nginx application (secure pod deployment)
|
|
||||||
kubectl apply -f nginx-nodeport-deployment.yaml
|
|
||||||
|
|
||||||
# 4. Create the NodePort service
|
|
||||||
kubectl apply -f nginx-nodeport-service.yaml
|
|
||||||
|
|
||||||
# 5. Wait for deployment to be ready
|
|
||||||
kubectl wait --for=condition=ready pod -l app=nginx-nodeport --timeout=60s
|
|
||||||
|
|
||||||
# 6. Verify deployment
|
|
||||||
kubectl get all -l app=nginx-nodeport
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔍 Validation Procedures
|
|
||||||
|
|
||||||
### 1. Basic Functionality Tests
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Test pod health
|
|
||||||
kubectl get pods -l app=nginx-nodeport
|
|
||||||
kubectl describe pod -l app=nginx-nodeport
|
|
||||||
|
|
||||||
# Test nginx configuration
|
|
||||||
POD_NAME=$(kubectl get pods -l app=nginx-nodeport -o name | head -1)
|
|
||||||
kubectl exec $POD_NAME -- nginx -t
|
|
||||||
|
|
||||||
# Test health endpoint
|
|
||||||
kubectl exec $POD_NAME -- curl -s http://localhost:8080/health
|
|
||||||
# Expected: "healthy"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. IPv6 Accessibility Tests
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Get node IPv6 address (IPv4 + IPv6 extraction issue fix)
|
|
||||||
NODE_IPV6=$(kubectl get nodes -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)
|
|
||||||
|
|
||||||
# Test external IPv6 connectivity
|
|
||||||
curl -6 "http://[$NODE_IPV6]:30091/"
|
|
||||||
curl -6 "http://[$NODE_IPV6]:30091/health"
|
|
||||||
|
|
||||||
# Verify website displays correctly
|
|
||||||
curl -6 "http://[$NODE_IPV6]:30091/" | grep -i "nodeport secure"
|
|
||||||
# Expected: Should find "NODEPORT SECURE" text
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Automated Testing
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Run the comprehensive test script
|
|
||||||
./test-nodeport-ipv6.sh
|
|
||||||
|
|
||||||
# Expected output:
|
|
||||||
# ✅ Connected to Kubernetes cluster
|
|
||||||
# ✅ nginx-nodeport deployment found
|
|
||||||
# ✅ nginx-nodeport pods are ready
|
|
||||||
# ✅ nginx configuration is valid
|
|
||||||
# ✅ Health endpoint is working
|
|
||||||
# ✅ NodePort service is configured
|
|
||||||
# ✅ NodePort: 30091
|
|
||||||
# ✅ Node IPv6 address: [YOUR_IPV6]
|
|
||||||
# ✅ External IPv6 connectivity is working!
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🎯 Success Criteria
|
|
||||||
|
|
||||||
### Primary Success Indicators
|
|
||||||
|
|
||||||
- [ ] **Pod Status**: kubectl get pods shows nginx-nodeport pod in "Running" status
|
|
||||||
- [ ] **Service Status**: kubectl get svc shows nginx-nodeport-service with NodePort 30091
|
|
||||||
- [ ] **Health Endpoint**: curl -6 "http://[$NODE_IPV6]:30091/health" returns "healthy"
|
|
||||||
- [ ] **Website Access**: curl -6 "http://[$NODE_IPV6]:30091" returns HTML with "NODEPORT SECURE"
|
|
||||||
- [ ] **IPv6 Connectivity**: External IPv6 access works from outside the cluster
|
|
||||||
- [ ] **nginx Logs**: kubectl logs deployment/nginx-nodeport shows access logs
|
|
||||||
|
|
||||||
**Your website will be accessible at**: http://[YOUR-NODE-IPV6]:30091
|
|
||||||
|
|
||||||
**Success indicator**: Website displays "NODEPORT SECURE" and "ENHANCED SECURITY" badges with professional styling and IPv6 address detection.
|
|
||||||
@@ -1,242 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Nginx NodePort IPv6 Testing Script
|
|
||||||
# Tests and validates IPv6 accessibility for nginx-nodeport deployment
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "🌐 Mycelium Cloud - Nginx NodePort IPv6 Testing"
|
|
||||||
echo "=================================================="
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# Function to print colored output
|
|
||||||
print_status() {
|
|
||||||
echo -e "${GREEN}✅ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_warning() {
|
|
||||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_error() {
|
|
||||||
echo -e "${RED}❌ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_info() {
|
|
||||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check if kubectl is available
|
|
||||||
if ! command -v kubectl &> /dev/null; then
|
|
||||||
print_error "kubectl is not installed or not in PATH"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if we can connect to the cluster
|
|
||||||
if ! kubectl cluster-info &> /dev/null; then
|
|
||||||
print_error "Cannot connect to Kubernetes cluster"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
print_status "Connected to Kubernetes cluster"
|
|
||||||
|
|
||||||
# Check if nginx-nodeport deployment exists
|
|
||||||
if ! kubectl get deployment nginx-nodeport &> /dev/null; then
|
|
||||||
print_error "nginx-nodeport deployment not found. Please deploy first:"
|
|
||||||
echo " kubectl apply -f nginx-nodeport-configmaps.yaml"
|
|
||||||
echo " kubectl apply -f nginx-nodeport-deployment.yaml"
|
|
||||||
echo " kubectl apply -f nginx-nodeport-service.yaml"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
print_status "nginx-nodeport deployment found"
|
|
||||||
|
|
||||||
# Wait for pods to be ready
|
|
||||||
print_info "Waiting for nginx-nodeport pods to be ready..."
|
|
||||||
if kubectl wait --for=condition=ready pod -l app=nginx-nodeport --timeout=60s; then
|
|
||||||
print_status "nginx-nodeport pods are ready"
|
|
||||||
else
|
|
||||||
print_error "nginx-nodeport pods failed to become ready"
|
|
||||||
kubectl get pods -l app=nginx-nodeport
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get pod information and node it's running on
|
|
||||||
POD_NAME=$(kubectl get pods -l app=nginx-nodeport -o name | head -1)
|
|
||||||
POD_NODE=$(kubectl get pods -l app=nginx-nodeport -o jsonpath='{.items[0].spec.nodeName}')
|
|
||||||
print_info "Testing pod: $POD_NAME"
|
|
||||||
print_info "Pod is running on node: $POD_NODE"
|
|
||||||
|
|
||||||
# Test nginx configuration
|
|
||||||
print_info "Testing nginx configuration..."
|
|
||||||
if kubectl exec $POD_NAME -- nginx -t &> /dev/null; then
|
|
||||||
print_status "nginx configuration is valid"
|
|
||||||
else
|
|
||||||
print_error "nginx configuration is invalid"
|
|
||||||
kubectl exec $POD_NAME -- nginx -t
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test health endpoint
|
|
||||||
print_info "Testing health endpoint..."
|
|
||||||
if kubectl exec $POD_NAME -- curl -s http://localhost:8080/health | grep -q "healthy"; then
|
|
||||||
print_status "Health endpoint is working"
|
|
||||||
else
|
|
||||||
print_error "Health endpoint failed"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test IPv6 listening
|
|
||||||
print_info "Checking IPv6 support in nginx..."
|
|
||||||
if kubectl exec $POD_NAME -- netstat -tuln | grep -q ":8080"; then
|
|
||||||
print_status "nginx is listening on port 8080"
|
|
||||||
else
|
|
||||||
print_error "nginx is not listening on port 8080"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get service information
|
|
||||||
print_info "Checking NodePort service..."
|
|
||||||
SERVICE_TYPE=$(kubectl get svc nginx-nodeport-service -o jsonpath='{.spec.type}')
|
|
||||||
if [ "$SERVICE_TYPE" = "NodePort" ]; then
|
|
||||||
print_status "NodePort service is configured correctly"
|
|
||||||
else
|
|
||||||
print_error "Service type is '$SERVICE_TYPE', expected 'NodePort'"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Extract NodePort
|
|
||||||
NODEPORT=$(kubectl get svc nginx-nodeport-service -o jsonpath='{.spec.ports[0].nodePort}')
|
|
||||||
if [ "$NODEPORT" = "30091" ]; then
|
|
||||||
print_status "NodePort is correctly set to 30091"
|
|
||||||
else
|
|
||||||
print_warning "NodePort is $NODEPORT (expected 30091)"
|
|
||||||
fi
|
|
||||||
print_info "NodePort: $NODEPORT"
|
|
||||||
|
|
||||||
# Get the Mycelium IPv6 address of the SPECIFIC node where the pod is running
|
|
||||||
# This is critical with externalTrafficPolicy: Local
|
|
||||||
print_info "Getting Mycelium IPv6 address of node where pod is running..."
|
|
||||||
|
|
||||||
# Get Mycelium IPv6 of the specific node where our pod is running
|
|
||||||
NODE_IPV6=$(kubectl get node "$POD_NODE" -o jsonpath='{range .status.addresses[?(@.type=="InternalIP")]}{.address}{"\n"}{end}' 2>/dev/null | 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 "$NODE_IPV6" ]; then
|
|
||||||
print_warning "Could not get Mycelium IPv6 address for node $POD_NODE"
|
|
||||||
print_info "Please manually find your node IPv6 address with:"
|
|
||||||
echo " kubectl get node $POD_NODE -o jsonpath='{range .status.addresses[?(@.type==\"InternalIP\")]}{.address}{\"\n\"}{end}' | grep ':'"
|
|
||||||
else
|
|
||||||
print_status "Pod's node ($POD_NODE) Mycelium IPv6: $NODE_IPV6"
|
|
||||||
print_info "⚠️ NOTE: With externalTrafficPolicy: Local, service is only accessible on THIS node's IP"
|
|
||||||
|
|
||||||
# Test external connectivity
|
|
||||||
print_info "Testing external Mycelium IPv6 connectivity..."
|
|
||||||
|
|
||||||
# Test with IPv6
|
|
||||||
if command -v curl &> /dev/null; then
|
|
||||||
print_info "Testing: curl -6 \"http://[$NODE_IPV6]:$NODEPORT/\""
|
|
||||||
if curl -6 -s -m 10 "http://[$NODE_IPV6]:$NODEPORT/" > /tmp/nodeport_test.html 2>/dev/null; then
|
|
||||||
if [ -s /tmp/nodeport_test.html ]; then
|
|
||||||
print_status "External Mycelium IPv6 connectivity is working!"
|
|
||||||
print_info "Your website is accessible at: http://[$NODE_IPV6]:$NODEPORT/"
|
|
||||||
print_info "Content preview:"
|
|
||||||
head -3 /tmp/nodeport_test.html | sed 's/^/ /'
|
|
||||||
rm -f /tmp/nodeport_test.html
|
|
||||||
else
|
|
||||||
print_warning "Connected but received no content"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
print_warning "External Mycelium IPv6 connectivity test failed"
|
|
||||||
print_info "This might be due to:"
|
|
||||||
print_info " • Firewall or network policies blocking port $NODEPORT"
|
|
||||||
print_info " • Pod not running on this specific node"
|
|
||||||
print_info " • Mycelium network not properly configured"
|
|
||||||
print_info ""
|
|
||||||
print_info "Try testing from within the cluster:"
|
|
||||||
echo " kubectl exec $POD_NAME -- curl -s http://localhost:8080/"
|
|
||||||
fi
|
|
||||||
rm -f /tmp/nodeport_test.html
|
|
||||||
else
|
|
||||||
print_info "curl not available, skipping external connectivity test"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test ConfigMaps
|
|
||||||
print_info "Checking ConfigMaps..."
|
|
||||||
if kubectl get configmap nginx-nodeport-content &> /dev/null; then
|
|
||||||
print_status "nginx-nodeport-content ConfigMap exists"
|
|
||||||
else
|
|
||||||
print_error "nginx-nodeport-content ConfigMap not found"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if kubectl get configmap nginx-nodeport-nginx-config &> /dev/null; then
|
|
||||||
print_status "nginx-nodeport-nginx-config ConfigMap exists"
|
|
||||||
else
|
|
||||||
print_error "nginx-nodeport-nginx-config ConfigMap not found"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test content mounting
|
|
||||||
print_info "Testing content mounting..."
|
|
||||||
if kubectl exec $POD_NAME -- ls -la /usr/share/nginx/html/index.html &> /dev/null; then
|
|
||||||
print_status "Website content is properly mounted"
|
|
||||||
else
|
|
||||||
print_error "Website content mounting failed"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test nginx config mounting
|
|
||||||
print_info "Testing nginx config mounting..."
|
|
||||||
if kubectl exec $POD_NAME -- ls -la /etc/nginx/conf.d/default.conf &> /dev/null; then
|
|
||||||
print_status "nginx configuration is properly mounted"
|
|
||||||
else
|
|
||||||
print_error "nginx configuration mounting failed"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Display access information
|
|
||||||
echo ""
|
|
||||||
echo "🎉 Nginx NodePort IPv6 Testing Complete!"
|
|
||||||
echo "========================================="
|
|
||||||
echo ""
|
|
||||||
echo "📊 Summary:"
|
|
||||||
echo " • nginx-nodeport deployment: Running"
|
|
||||||
echo " • NodePort service: Configured (Port $NODEPORT)"
|
|
||||||
echo " • Health endpoint: Working"
|
|
||||||
echo " • Content mounting: OK"
|
|
||||||
echo " • nginx configuration: Valid"
|
|
||||||
echo ""
|
|
||||||
echo "🌐 Access Information:"
|
|
||||||
if [ ! -z "$NODE_IPV6" ]; then
|
|
||||||
echo " • External URL: http://[$NODE_IPV6]:$NODEPORT/"
|
|
||||||
echo " • Health check: http://[$NODE_IPV6]:$NODEPORT/health"
|
|
||||||
echo " • Internal test: kubectl exec $POD_NAME -- curl -s http://localhost:8080/"
|
|
||||||
echo ""
|
|
||||||
echo " 💡 All worker node Mycelium IPv6 addresses:"
|
|
||||||
kubectl get nodes -o jsonpath='{range .items[*]}{range .status.addresses[?(@.type=="InternalIP")]}{.address}{"\n"}{end}{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]+$' | nl -v 1 -w 5 -s '. ' | sed 's/^/ /'
|
|
||||||
else
|
|
||||||
echo " • Get your node Mycelium IPv6 addresses:"
|
|
||||||
echo " kubectl get nodes -o jsonpath='{range .items[*]}{range .status.addresses[?(@.type==\"InternalIP\")]}{.address}{\"\n\"}{end}{end}' | grep ':'"
|
|
||||||
echo " • Access URL: http://[YOUR-NODE-IPV6]:$NODEPORT/"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
echo "📋 Next Steps:"
|
|
||||||
echo " • Open the external URL in a browser to see your secure website"
|
|
||||||
echo " • Check the compare-approaches.md for security comparison"
|
|
||||||
echo " • Test scaling: kubectl scale deployment nginx-nodeport --replicas=3"
|
|
||||||
echo " • Monitor logs: kubectl logs -f deployment/nginx-nodeport"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Show recent logs
|
|
||||||
print_info "Recent nginx access logs:"
|
|
||||||
kubectl logs --tail=5 deployment/nginx-nodeport
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
print_status "All tests passed! Your nginx-nodeport deployment is working correctly."
|
|
||||||
Reference in New Issue
Block a user