diff --git a/docs/roadmap.md b/docs/roadmap.md index 8728b8c..741c1d2 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -15,13 +15,14 @@ Comprehensive progression of Kubernetes examples designed to teach MyceliumCloud ### Planned Examples (In Progress) -#### 2. Nginx Static Site 🔄 -- **Difficulty**: ⭐ Easy -- **Status**: 🔄 **NEXT UP** +#### 2. Nginx Static Site ✅ +- **Difficulty**: ⭐ Easy +- **Status**: ✅ **COMPLETED** - **Learning Focus**: Static content serving, custom HTML, nginx configuration - **Template**: Same efficient pattern as hello-world -- **Key Concepts**: Static files, nginx deployment, custom configuration -- **Next Step**: Copy hello-world template, adapt for nginx +- **Key Concepts**: Static files, nginx deployment, custom configuration, ConfigMaps +- **Result**: Tested and working on MyceliumCloud cluster +- **Next Step**: Move to Python Flask API example ### Planned Examples (Future) diff --git a/examples/nginx-static/default-index.html b/examples/nginx-static/default-index.html new file mode 100644 index 0000000..6d426b4 --- /dev/null +++ b/examples/nginx-static/default-index.html @@ -0,0 +1,48 @@ + + + + Nginx Static Site + + + +
+ +

Nginx Static Site

+

Welcome to your custom static website on Mycelium Cloud!

+

This site is served by Nginx in a Kubernetes pod.

+

Deployment: nginx-static

+

Time:

+

+ Deploying static sites on Mycelium Cloud is easy! +

+
+ + + \ No newline at end of file diff --git a/examples/nginx-static/nginx-static-deployment.yaml b/examples/nginx-static/nginx-static-deployment.yaml new file mode 100644 index 0000000..fcb6af4 --- /dev/null +++ b/examples/nginx-static/nginx-static-deployment.yaml @@ -0,0 +1,26 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-static +spec: + replicas: 1 + selector: + matchLabels: + app: nginx-static + template: + metadata: + labels: + app: nginx-static + spec: + containers: + - name: nginx-static + image: nginx:alpine + ports: + - containerPort: 80 + volumeMounts: + - name: nginx-content + mountPath: /usr/share/nginx/html + volumes: + - name: nginx-content + configMap: + name: nginx-static-content \ No newline at end of file diff --git a/examples/nginx-static/nginx-static-service.yaml b/examples/nginx-static/nginx-static-service.yaml new file mode 100644 index 0000000..1a41cfe --- /dev/null +++ b/examples/nginx-static/nginx-static-service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: nginx-static-service +spec: + selector: + app: nginx-static + ports: + - port: 80 + targetPort: 80 + type: LoadBalancer \ No newline at end of file diff --git a/examples/nginx-static/nginx-static.md b/examples/nginx-static/nginx-static.md new file mode 100644 index 0000000..f92ad14 --- /dev/null +++ b/examples/nginx-static/nginx-static.md @@ -0,0 +1,288 @@ +# Mycelium Cloud - Nginx Static Site Example + +A complete, standalone example for deploying a static website using Nginx on Mycelium Cloud Kubernetes cluster. + +## 📁 What This Contains + +This directory contains everything you need to deploy a static website: + +- **nginx-static.md** - This guide +- **nginx-static-deployment.yaml** - Nginx deployment with custom content +- **nginx-static-service.yaml** - Service configuration +- **default-index.html** - Default website content (used to create ConfigMap) + +## 🚀 Quick Start (2 minutes) + +```bash +# 1. Deploy the application +kubectl apply -f nginx-static-deployment.yaml + +# 2. Create ConfigMap with default content +kubectl create configmap nginx-static-content --from-file=index.html=default-index.html + +# 3. Create the service +kubectl apply -f nginx-static-service.yaml + +# 3. Access your static site via port-forward + +**Option 1: Simple (Recommended)** +```bash +# Keep terminal open, see connection logs (Ctrl+C to stop) +kubectl port-forward service/nginx-static-service 8080:80 +``` + +**Option 2: Advanced (Background)** +```bash +# Start in background +nohup kubectl port-forward service/nginx-static-service 8080:80 > /dev/null 2>&1 & + +# Kill when done +lsof -ti:8080 | xargs kill -9 +``` + +# 4. Visit http://localhost:8080 +curl http://localhost:8080 +``` + +**Expected Result:** You'll see a custom static website served by Nginx. + +## 📋 What You'll Learn + +- ✅ Nginx container deployment +- ✅ Static content serving +- ✅ ConfigMap usage for custom HTML +- ✅ Service creation and networking +- ✅ Port-forwarding for external access (Mycelium Cloud method) +- ✅ Basic nginx configuration patterns + +## 🏗️ Architecture + +This example demonstrates: + +``` +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ User │ │ Port-Forward │ │ Nginx │ +│ (Browser) │────│ localhost:8080 │────│ Pod │ +│ │ │ │ │ :80 │ +└─────────────────┘ └─────────────────┘ └─────────────────┘ + │ + ┌───────────────┐ + │ ConfigMap │ + │ (HTML/CSS) │ + └───────────────┘ +``` + +**Components:** +- **Nginx Pod**: Serves static content from /usr/share/nginx/html +- **ConfigMap**: Stores custom HTML, CSS, and other static files +- **Service**: LoadBalancer exposing the nginx pod +- **Port-Forward**: Mycelium Cloud method for external access + +## 📊 Resource Details + +```bash +# Expected output +kubectl get pods +NAME READY STATUS RESTARTS AGE +nginx-static-xxxxxx-xxxxx 1/1 Running 0 2m + +kubectl get svc +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) +nginx-static-service LoadBalancer 10.43.xx.x 10.20.x.x,10.20.x.x 80:xxxxx/TCP +``` + +## 🔧 Customization Guide + +### Change the Content + +Create a custom ConfigMap with your content: + +```bash +# Create your custom HTML file +cat << EOF > custom-index.html + + + + My Custom Site + + + +
+

Welcome to My Static Site

+

This site is running on Mycelium Cloud!

+

Current time: $(date)

+
+ + +EOF + +# Create ConfigMap with custom content +kubectl create configmap nginx-static-content \ + --from-file=index.html=custom-index.html + +# Update deployment to use the new ConfigMap +kubectl apply -f nginx-static-deployment.yaml +``` + +### Add More Static Files + +Create additional ConfigMaps for CSS, JavaScript, or images: + +```bash +# Add a stylesheet +cat << EOF > custom.css +body { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; +} +h1 { text-align: center; margin-top: 100px; } +``` + +```bash +# Create ConfigMap with multiple files +kubectl create configmap nginx-static-content \ + --from-file=index.html=custom-index.html \ + --from-file=styles.css=custom.css +``` + +## 🚪 Access Methods + +### Method 1: Port-Forward (Recommended for Mycelium Cloud) + +**Option 1: Simple (Recommended)** +```bash +# Keep terminal open, see connection logs (Ctrl+C to stop) +kubectl port-forward service/nginx-static-service 8080:80 + +# Access via browser or curl +curl http://localhost:8080 +``` + +**Option 2: Advanced (Background)** +```bash +# Start in background +nohup kubectl port-forward service/nginx-static-service 8080:80 > /dev/null 2>&1 & + +# Access via browser or curl +curl http://localhost:8080 +``` + +**Why this works in Mycelium Cloud:** +- LoadBalancer external IPs are internal cluster addresses +- Port-forward creates local tunnel to cluster service +- Reliable and consistent access method + +### Method 2: LoadBalancer (For Reference) + +Note: In Mycelium Cloud, LoadBalancer external IPs (like 10.20.x.x) are internal cluster IPs and not externally accessible. Use port-forward for external access. + +## 🗑️ Resource Cleanup + +```bash +# Remove all resources +kubectl delete -f nginx-static-deployment.yaml -f nginx-static-service.yaml + +# Remove the ConfigMap +kubectl delete configmap nginx-static-content + +# Verify cleanup +kubectl get all -l app=nginx-static # Should return nothing +``` + +## 🔍 Troubleshooting + +### Pod Won't Start +```bash +# Check pod status +kubectl get pods -l app=nginx-static + +# Check pod logs +kubectl logs deployment/nginx-static + +# Check pod events +kubectl describe pod -l app=nginx-static +``` + +### Site Not Loading +```bash +# Check service endpoints +kubectl get endpoints nginx-static-service + +# Check if port-forward is working +kubectl port-forward service/nginx-static-service 8081:80 & +curl -v http://localhost:8081 +``` + +### Custom Content Not Showing +```bash +# Verify ConfigMap content +kubectl get configmap nginx-static-content -o yaml + +# Check if files are mounted correctly +kubectl exec -it deployment/nginx-static -- ls -la /usr/share/nginx/html/ + +# Reload nginx to pick up changes +kubectl exec -it deployment/nginx-static -- nginx -s reload +``` + +### Port Forward Fails +```bash +# Check if port is in use +lsof -i :8080 + +# Try different port +kubectl port-forward service/nginx-static-service 8082:80 +curl http://localhost:8082 +``` + +## 📚 More Examples + +This is currently one of the complete examples. Future examples will include: +- **python-flask/** - Python web applications +- **redis-cache/** - In-memory data caching +- **postgresql/** - Persistent database services +- **wordpress/** - Multi-container CMS deployment +- **nodejs-api/** - Modern JavaScript applications +- **jenkins-cicd/** - Infrastructure automation +- **nextcloud/** - Enterprise file sharing + +## 💡 Pro Tips + +1. **Start Simple**: Begin with foreground port-forward (`kubectl port-forward`) +2. **Background Optional**: Use `nohup` only when you need persistent port-forwards +3. **Port Management**: Use `lsof -ti:PORT` to find and kill processes +4. **Resource Monitoring**: `kubectl get pods -o wide` shows pod distribution +5. **Quick Testing**: `curl -s http://localhost:8080` to verify nginx is working +6. **Nginx Logs**: `kubectl logs deployment/nginx-static` for debugging +7. **Config Updates**: Update ConfigMap then reload nginx: `kubectl exec deployment/nginx-static -- nginx -s reload` + +## 🎉 Success Indicators + +You'll know everything is working when: +- ✅ `kubectl get pods` shows nginx-static pod in "Running" status +- ✅ `kubectl get svc` shows nginx-static-service created +- ✅ `curl http://localhost:8080` returns your custom HTML content +- ✅ `kubectl logs deployment/nginx-static` shows nginx access logs + +## 🏆 Next Steps + +After completing this example, you can: +1. **Customize Content**: Replace with your own static site +2. **Add More Examples**: Try the Python Flask API example +3. **Scale Up**: Learn about load balancing with multiple replicas +4. **Add Persistence**: Learn about persistent volumes for file storage + +--- + +## 📞 Getting Help + +- **Troubleshooting**: Check the troubleshooting section above +- **Mycelium Cloud Docs**: See main repository README +- **Kubectl Help**: `kubectl get pods --help` for command reference +- **Support**: Contact Mycelium Cloud support team + +For more help, visit our [documentation](../../README.md) or contact support. \ No newline at end of file