feat: Add complete Python Flask API example with deployment, service, and comprehensive documentation
This commit is contained in:
@@ -20,17 +20,24 @@ Comprehensive progression of Kubernetes examples designed to teach MyceliumCloud
|
|||||||
- **Template**: Same efficient pattern with `nginx-static.md` + `nginx-static-deployment.yaml` + `nginx-static-service.yaml` + `default-index.html`
|
- **Template**: Same efficient pattern with `nginx-static.md` + `nginx-static-deployment.yaml` + `nginx-static-service.yaml` + `default-index.html`
|
||||||
- **Key Concepts**: Static files, nginx deployment, custom configuration, ConfigMaps, HTML serving
|
- **Key Concepts**: Static files, nginx deployment, custom configuration, ConfigMaps, HTML serving
|
||||||
|
|
||||||
|
#### 3. Python Flask API ✅
|
||||||
|
- **Difficulty**: ⭐ Easy-Medium
|
||||||
|
- **Status**: ✅ **COMPLETED**
|
||||||
|
- **Learning Focus**: Application containerization, Python web services
|
||||||
|
- **Template**: Same efficient pattern with `python-flask.md` + `python-flask-deployment.yaml` + `python-flask-service.yaml` + `app.py`
|
||||||
|
- **Key Concepts**: Python containers, API development, HTTP services, JSON responses, RESTful design
|
||||||
|
|
||||||
### Planned Examples (In Progress)
|
### Planned Examples (In Progress)
|
||||||
|
|
||||||
### Planned Examples (Future)
|
### Planned Examples (Future)
|
||||||
|
|
||||||
#### 3. Python Flask API 🔄
|
#### 4. Redis Cache 🔄
|
||||||
- **Difficulty**: ⭐ Easy-Medium
|
- **Difficulty**: ⭐⭐ Medium
|
||||||
- **Status**: 🔄 **NEXT UP**
|
- **Status**: 🔄 **NEXT UP**
|
||||||
- **Learning Focus**: Application containerization, Python web services
|
- **Learning Focus**: Data storage, caching patterns, stateful services
|
||||||
- **Template**: Same efficient pattern
|
- **Template**: Same efficient pattern
|
||||||
- **Key Concepts**: Python containers, API development, HTTP services
|
- **Key Concepts**: Redis deployment, data persistence, cache strategies
|
||||||
- **Next Step**: Create python-flask directory using nginx-static template
|
- **Next Step**: Create redis-cache directory using python-flask template
|
||||||
|
|
||||||
#### 4. Redis Cache
|
#### 4. Redis Cache
|
||||||
- **Difficulty**: ⭐⭐ Medium
|
- **Difficulty**: ⭐⭐ Medium
|
||||||
|
|||||||
126
examples/python-flask/app.py
Normal file
126
examples/python-flask/app.py
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
from flask import Flask, jsonify, request
|
||||||
|
import random
|
||||||
|
import datetime
|
||||||
|
import platform
|
||||||
|
import os
|
||||||
|
import math
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def home():
|
||||||
|
return jsonify({
|
||||||
|
'api': 'Python Flask Tools API',
|
||||||
|
'version': '1.0.0',
|
||||||
|
'description': 'A practical API with useful endpoints for testing and development',
|
||||||
|
'endpoints': {
|
||||||
|
'/': 'API information',
|
||||||
|
'/time': 'Current timestamp',
|
||||||
|
'/random': 'Random data and quotes',
|
||||||
|
'/health': 'Health check',
|
||||||
|
'/calc': 'Mathematical calculations',
|
||||||
|
'/info': 'System information'
|
||||||
|
},
|
||||||
|
'examples': {
|
||||||
|
'time': '/time',
|
||||||
|
'random': '/random',
|
||||||
|
'calc': '/calc?operation=add&a=5&b=3',
|
||||||
|
'health': '/health'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
@app.route('/time')
|
||||||
|
def get_time():
|
||||||
|
return jsonify({
|
||||||
|
'current_time': datetime.datetime.now().isoformat(),
|
||||||
|
'timestamp': datetime.datetime.now().timestamp(),
|
||||||
|
'timezone': 'UTC',
|
||||||
|
'date': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
})
|
||||||
|
|
||||||
|
@app.route('/random')
|
||||||
|
def get_random():
|
||||||
|
quotes = [
|
||||||
|
'The only way to do great work is to love what you do. - Steve Jobs',
|
||||||
|
'Life is what happens to you while you are busy making other plans. - John Lennon',
|
||||||
|
'The future belongs to those who believe in the beauty of their dreams. - Eleanor Roosevelt',
|
||||||
|
'It is during our darkest moments that we must focus to see the light. - Aristotle',
|
||||||
|
'The only impossible journey is the one you never begin. - Tony Robbins',
|
||||||
|
'In the middle of difficulty lies opportunity. - Albert Einstein',
|
||||||
|
'Success is not final, failure is not fatal: it is the courage to continue that counts. - Winston Churchill',
|
||||||
|
'The way to get started is to quit talking and begin doing. - Walt Disney'
|
||||||
|
]
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'quote': random.choice(quotes),
|
||||||
|
'number': random.randint(1, 100),
|
||||||
|
'boolean': random.choice([True, False]),
|
||||||
|
'list_item': random.choice(['apple', 'banana', 'cherry', 'date', 'elderberry']),
|
||||||
|
'uuid': str(random.randint(1000, 9999)) + '-' + str(random.randint(100, 999)),
|
||||||
|
'color': random.choice(['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'])
|
||||||
|
})
|
||||||
|
|
||||||
|
@app.route('/health')
|
||||||
|
def health_check():
|
||||||
|
return jsonify({
|
||||||
|
'status': 'healthy',
|
||||||
|
'uptime': 'running',
|
||||||
|
'service': 'Python Flask Tools API',
|
||||||
|
'timestamp': datetime.datetime.now().isoformat()
|
||||||
|
}), 200
|
||||||
|
|
||||||
|
@app.route('/calc')
|
||||||
|
def calculate():
|
||||||
|
try:
|
||||||
|
operation = request.args.get('operation', 'add')
|
||||||
|
a = float(request.args.get('a', 0))
|
||||||
|
b = float(request.args.get('b', 0)) if request.args.get('b') is not None else None
|
||||||
|
|
||||||
|
operations = {
|
||||||
|
'add': lambda x, y: x + y,
|
||||||
|
'subtract': lambda x, y: x - y,
|
||||||
|
'multiply': lambda x, y: x * y,
|
||||||
|
'divide': lambda x, y: x / y if y != 0 else 'Cannot divide by zero',
|
||||||
|
'power': lambda x, y: x ** y,
|
||||||
|
'sqrt': lambda x, y: math.sqrt(x) if b is None else 'Only one parameter needed for sqrt',
|
||||||
|
'modulo': lambda x, y: x % y
|
||||||
|
}
|
||||||
|
|
||||||
|
if operation not in operations:
|
||||||
|
return jsonify({
|
||||||
|
'error': f'Operation {operation} not supported',
|
||||||
|
'available_operations': list(operations.keys())
|
||||||
|
}), 400
|
||||||
|
|
||||||
|
result = operations[operation](a, b)
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'operation': operation,
|
||||||
|
'a': a,
|
||||||
|
'b': b,
|
||||||
|
'result': result,
|
||||||
|
'calculation': f"{a} {operation} {b} = {result}"
|
||||||
|
})
|
||||||
|
|
||||||
|
except ValueError:
|
||||||
|
return jsonify({'error': 'Invalid numbers provided. Use /calc?operation=add&a=5&b=3'}), 400
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({'error': str(e)}), 500
|
||||||
|
|
||||||
|
@app.route('/info')
|
||||||
|
def system_info():
|
||||||
|
return jsonify({
|
||||||
|
'python_version': platform.python_version(),
|
||||||
|
'platform': platform.platform(),
|
||||||
|
'processor': platform.processor(),
|
||||||
|
'hostname': platform.node(),
|
||||||
|
'machine': platform.machine(),
|
||||||
|
'current_directory': os.getcwd(),
|
||||||
|
'environment': {
|
||||||
|
'HOSTNAME': os.getenv('HOSTNAME', 'N/A'),
|
||||||
|
'POD_NAME': os.getenv('POD_NAME', 'N/A')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host='0.0.0.0', port=5000, debug=False)
|
||||||
31
examples/python-flask/python-flask-deployment.yaml
Normal file
31
examples/python-flask/python-flask-deployment.yaml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: python-flask
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: python-flask
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: python-flask
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: python-flask
|
||||||
|
image: python:3.11-alpine
|
||||||
|
ports:
|
||||||
|
- containerPort: 5000
|
||||||
|
command: ["/bin/sh", "-c"]
|
||||||
|
args:
|
||||||
|
- |
|
||||||
|
pip install flask &&
|
||||||
|
python /app/app.py
|
||||||
|
volumeMounts:
|
||||||
|
- name: app-code
|
||||||
|
mountPath: /app
|
||||||
|
volumes:
|
||||||
|
- name: app-code
|
||||||
|
configMap:
|
||||||
|
name: python-flask-app
|
||||||
11
examples/python-flask/python-flask-service.yaml
Normal file
11
examples/python-flask/python-flask-service.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: python-flask-service
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: python-flask
|
||||||
|
ports:
|
||||||
|
- port: 5000
|
||||||
|
targetPort: 5000
|
||||||
|
type: LoadBalancer
|
||||||
533
examples/python-flask/python-flask.md
Normal file
533
examples/python-flask/python-flask.md
Normal file
@@ -0,0 +1,533 @@
|
|||||||
|
# Mycelium Cloud - Python Flask API Example
|
||||||
|
|
||||||
|
A complete, production-ready Python Flask API for deploying dynamic web services on Mycelium Cloud Kubernetes cluster.
|
||||||
|
|
||||||
|
## 📁 What This Contains
|
||||||
|
|
||||||
|
This directory contains everything you need to deploy a practical Flask API:
|
||||||
|
|
||||||
|
- **python-flask.md** - This comprehensive guide
|
||||||
|
- **python-flask-deployment.yaml** - Flask application deployment
|
||||||
|
- **python-flask-service.yaml** - Service configuration
|
||||||
|
- **app.py** - The Flask application source code
|
||||||
|
|
||||||
|
## 🚀 Quick Start (2 minutes)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Deploy the application
|
||||||
|
kubectl apply -f python-flask-deployment.yaml
|
||||||
|
|
||||||
|
# 2. Create ConfigMap with the Flask app
|
||||||
|
kubectl create configmap python-flask-app --from-file=app.py
|
||||||
|
|
||||||
|
# 3. Create the service
|
||||||
|
kubectl apply -f python-flask-service.yaml
|
||||||
|
|
||||||
|
# 4. Access your API via port-forward
|
||||||
|
|
||||||
|
**Option 1: Simple (Recommended)**
|
||||||
|
```bash
|
||||||
|
# Keep terminal open, see connection logs (Ctrl+C to stop)
|
||||||
|
kubectl port-forward service/python-flask-service 5000:5000
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option 2: Advanced (Background)**
|
||||||
|
```bash
|
||||||
|
# Start in background
|
||||||
|
nohup kubectl port-forward service/python-flask-service 5000:5000 > /dev/null 2>&1 &
|
||||||
|
|
||||||
|
# Kill when done
|
||||||
|
lsof -ti:5000 | xargs kill -9
|
||||||
|
```
|
||||||
|
|
||||||
|
# 5. Test the API
|
||||||
|
curl http://localhost:5000
|
||||||
|
curl http://localhost:5000/time
|
||||||
|
curl http://localhost:5000/health
|
||||||
|
curl http://localhost:5000/random
|
||||||
|
curl "http://localhost:5000/calc?operation=add&a=5&b=3"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected Result:** You'll see a complete API with multiple useful endpoints.
|
||||||
|
|
||||||
|
## 📋 What You'll Learn
|
||||||
|
|
||||||
|
- ✅ Flask web framework deployment
|
||||||
|
- ✅ Python application containerization
|
||||||
|
- ✅ API development and JSON responses
|
||||||
|
- ✅ RESTful endpoints with parameters
|
||||||
|
- ✅ Error handling and status codes
|
||||||
|
- ✅ Container management with ConfigMaps
|
||||||
|
- ✅ Service creation and networking
|
||||||
|
- ✅ Port-forwarding for external access (Mycelium Cloud method)
|
||||||
|
- ✅ Advanced Flask patterns and best practices
|
||||||
|
|
||||||
|
## 🏗️ Architecture
|
||||||
|
|
||||||
|
This example demonstrates:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||||
|
│ User │ │ Port-Forward │ │ Flask API │ │ Python │
|
||||||
|
│ (cURL/HTTP) │────│ localhost:5000 │────│ Service │────│ Container │
|
||||||
|
│ │ │ │ │ :5000 │ │ (Python 3.11) │
|
||||||
|
└─────────────────┘ └─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||||
|
│
|
||||||
|
┌───────────────┐
|
||||||
|
│ ConfigMap │
|
||||||
|
│ (app.py) │
|
||||||
|
└───────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Components:**
|
||||||
|
- **Flask Pod**: Python web application serving multiple endpoints
|
||||||
|
- **ConfigMap**: Stores the Flask application code (app.py)
|
||||||
|
- **Service**: LoadBalancer exposing the Flask API
|
||||||
|
- **Port-Forward**: Mycelium Cloud method for external access
|
||||||
|
- **Endpoints**: 6 useful API endpoints for testing and development
|
||||||
|
|
||||||
|
## 🔥 API Endpoints
|
||||||
|
|
||||||
|
### 1. Root Information
|
||||||
|
```bash
|
||||||
|
GET /
|
||||||
|
```
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"api": "Python Flask Tools API",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A practical API with useful endpoints for testing and development",
|
||||||
|
"endpoints": {
|
||||||
|
"/": "API information",
|
||||||
|
"/time": "Current timestamp",
|
||||||
|
"/random": "Random data and quotes",
|
||||||
|
"/health": "Health check",
|
||||||
|
"/calc": "Mathematical calculations",
|
||||||
|
"/info": "System information"
|
||||||
|
},
|
||||||
|
"examples": {
|
||||||
|
"time": "/time",
|
||||||
|
"random": "/random",
|
||||||
|
"calc": "/calc?operation=add&a=5&b=3",
|
||||||
|
"health": "/health"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Current Time
|
||||||
|
```bash
|
||||||
|
GET /time
|
||||||
|
```
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"current_time": "2025-11-04T17:31:40.387484",
|
||||||
|
"date": "2025-11-04 17:31:40",
|
||||||
|
"timestamp": 1762277500.387502,
|
||||||
|
"timezone": "UTC"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Random Data
|
||||||
|
```bash
|
||||||
|
GET /random
|
||||||
|
```
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"boolean": false,
|
||||||
|
"color": "#FF6B6B",
|
||||||
|
"list_item": "banana",
|
||||||
|
"number": 91,
|
||||||
|
"quote": "The way to get started is to quit talking and begin doing. - Walt Disney",
|
||||||
|
"uuid": "8351-328"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Health Check
|
||||||
|
```bash
|
||||||
|
GET /health
|
||||||
|
```
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"service": "Python Flask Tools API",
|
||||||
|
"status": "healthy",
|
||||||
|
"timestamp": "2025-11-04T17:31:48.464063",
|
||||||
|
"uptime": "running"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Mathematical Calculations
|
||||||
|
```bash
|
||||||
|
GET /calc?operation=add&a=5&b=3
|
||||||
|
```
|
||||||
|
**Operations supported:** `add`, `subtract`, `multiply`, `divide`, `power`, `sqrt`, `modulo`
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"operation": "add",
|
||||||
|
"a": 5,
|
||||||
|
"b": 3,
|
||||||
|
"result": 8,
|
||||||
|
"calculation": "5 add 3 = 8"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. System Information
|
||||||
|
```bash
|
||||||
|
GET /info
|
||||||
|
```
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"python_version": "3.11.14",
|
||||||
|
"platform": "Linux-6.1.21-x86_64-with-musl",
|
||||||
|
"processor": "",
|
||||||
|
"hostname": "python-flask-55fdbf5cb4-cnxrc",
|
||||||
|
"machine": "x86_64",
|
||||||
|
"current_directory": "/",
|
||||||
|
"environment": {
|
||||||
|
"HOSTNAME": "python-flask-55fdbf5cb4-cnxrc",
|
||||||
|
"POD_NAME": "N/A"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 Resource Details
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Expected output
|
||||||
|
kubectl get pods
|
||||||
|
NAME READY STATUS RESTARTS AGE
|
||||||
|
python-flask-xxxxxx-xxxxx 1/1 Running 0 2m
|
||||||
|
|
||||||
|
kubectl get svc
|
||||||
|
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
|
||||||
|
python-flask-service LoadBalancer 10.43.xx.x 10.20.x.x,10.20.x.x 5000:xxxxx/TCP
|
||||||
|
|
||||||
|
kubectl get configmap
|
||||||
|
NAME DATA AGE
|
||||||
|
python-flask-app 1 1m
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ API Testing Examples
|
||||||
|
|
||||||
|
### Test All Endpoints
|
||||||
|
```bash
|
||||||
|
# Test root endpoint
|
||||||
|
curl http://localhost:5000
|
||||||
|
|
||||||
|
# Test time endpoint
|
||||||
|
curl http://localhost:5000/time
|
||||||
|
|
||||||
|
# Test random data
|
||||||
|
curl http://localhost:5000/random
|
||||||
|
|
||||||
|
# Test health check
|
||||||
|
curl http://localhost:5000/health
|
||||||
|
|
||||||
|
# Test calculations
|
||||||
|
curl "http://localhost:5000/calc?operation=add&a=10&b=5"
|
||||||
|
curl "http://localhost:5000/calc?operation=multiply&a=7&b=8"
|
||||||
|
curl "http://localhost:5000/calc?operation=divide&a=20&b=4"
|
||||||
|
curl "http://localhost:5000/calc?operation=power&a=2&b=3"
|
||||||
|
|
||||||
|
# Test system info
|
||||||
|
curl http://localhost:5000/info
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advanced Testing
|
||||||
|
```bash
|
||||||
|
# Test with JSON response formatting
|
||||||
|
curl -s http://localhost:5000 | jq '.'
|
||||||
|
curl -s http://localhost:5000/time | jq '.current_time'
|
||||||
|
|
||||||
|
# Test error handling
|
||||||
|
curl "http://localhost:5000/calc?operation=unknown&a=5&b=3"
|
||||||
|
curl "http://localhost:5000/calc?operation=add&a=invalid&b=3"
|
||||||
|
|
||||||
|
# Test multiple random calls
|
||||||
|
for i in {1..5}; do
|
||||||
|
curl -s http://localhost:5000/random | jq -r '.quote'
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Customization Guide
|
||||||
|
|
||||||
|
### Add New Endpoints
|
||||||
|
|
||||||
|
Edit `app.py` to add custom endpoints:
|
||||||
|
|
||||||
|
```python
|
||||||
|
@app.route('/custom')
|
||||||
|
def custom_endpoint():
|
||||||
|
return jsonify({
|
||||||
|
'message': 'This is a custom endpoint',
|
||||||
|
'data': {'key': 'value'},
|
||||||
|
'timestamp': datetime.datetime.now().isoformat()
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Modify Existing Endpoints
|
||||||
|
|
||||||
|
```python
|
||||||
|
@app.route('/random')
|
||||||
|
def get_random():
|
||||||
|
# Add your own quotes or data
|
||||||
|
quotes = [
|
||||||
|
'Your custom quote here',
|
||||||
|
'Another custom quote'
|
||||||
|
]
|
||||||
|
# ... rest of the function
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update Container Image
|
||||||
|
|
||||||
|
To use a different Python version or add packages:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# In python-flask-deployment.yaml
|
||||||
|
- name: python-flask
|
||||||
|
image: python:3.12-alpine # Use different version
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# In python-flask-deployment.yaml
|
||||||
|
args:
|
||||||
|
- |
|
||||||
|
pip install flask requests && # Add more packages
|
||||||
|
python /app/app.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
Add environment-specific configuration:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# In python-flask-deployment.yaml
|
||||||
|
env:
|
||||||
|
- name: FLASK_ENV
|
||||||
|
value: "production"
|
||||||
|
- name: DEBUG
|
||||||
|
value: "False"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚪 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/python-flask-service 5000:5000
|
||||||
|
|
||||||
|
# Access via browser or curl
|
||||||
|
curl http://localhost:5000
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option 2: Advanced (Background)**
|
||||||
|
```bash
|
||||||
|
# Start in background
|
||||||
|
nohup kubectl port-forward service/python-flask-service 5000:5000 > /dev/null 2>&1 &
|
||||||
|
|
||||||
|
# Access via browser or curl
|
||||||
|
curl http://localhost:5000
|
||||||
|
```
|
||||||
|
|
||||||
|
**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.
|
||||||
|
|
||||||
|
### Method 3: Direct API Testing
|
||||||
|
|
||||||
|
Create a test script:
|
||||||
|
|
||||||
|
```python
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
# Test all endpoints
|
||||||
|
base_url = "http://localhost:5000"
|
||||||
|
|
||||||
|
endpoints = ['/', '/time', '/random', '/health', '/calc?operation=add&a=5&b=3', '/info']
|
||||||
|
|
||||||
|
for endpoint in endpoints:
|
||||||
|
response = requests.get(f"{base_url}{endpoint}")
|
||||||
|
print(f"GET {endpoint}")
|
||||||
|
print(json.dumps(response.json(), indent=2))
|
||||||
|
print("-" * 50)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🗑️ Resource Cleanup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Remove all resources
|
||||||
|
kubectl delete -f python-flask-deployment.yaml -f python-flask-service.yaml
|
||||||
|
|
||||||
|
# Remove the ConfigMap
|
||||||
|
kubectl delete configmap python-flask-app
|
||||||
|
|
||||||
|
# Verify cleanup
|
||||||
|
kubectl get all -l app=python-flask # Should return nothing
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 Troubleshooting
|
||||||
|
|
||||||
|
### Pod Won't Start
|
||||||
|
```bash
|
||||||
|
# Check pod status
|
||||||
|
kubectl get pods -l app=python-flask
|
||||||
|
|
||||||
|
# Check pod logs
|
||||||
|
kubectl logs deployment/python-flask
|
||||||
|
|
||||||
|
# Check pod events
|
||||||
|
kubectl describe pod -l app=python-flask
|
||||||
|
|
||||||
|
# Common issues:
|
||||||
|
# - ConfigMap not found
|
||||||
|
# - Python package installation failed
|
||||||
|
# - Port binding errors
|
||||||
|
```
|
||||||
|
|
||||||
|
### API Not Responding
|
||||||
|
```bash
|
||||||
|
# Check service endpoints
|
||||||
|
kubectl get endpoints python-flask-service
|
||||||
|
|
||||||
|
# Check if port-forward is working
|
||||||
|
kubectl port-forward service/python-flask-service 5001:5000 &
|
||||||
|
curl -v http://localhost:5001
|
||||||
|
|
||||||
|
# Test from within cluster
|
||||||
|
kubectl run test-flask --rm -it --image=curlimages/curl:8.7.1 -- \
|
||||||
|
sh -lc 'curl http://python-flask-service:5000'
|
||||||
|
```
|
||||||
|
|
||||||
|
### ConfigMap Issues
|
||||||
|
```bash
|
||||||
|
# Verify ConfigMap exists
|
||||||
|
kubectl get configmap python-flask-app
|
||||||
|
|
||||||
|
# Check ConfigMap content
|
||||||
|
kubectl get configmap python-flask-app -o yaml
|
||||||
|
|
||||||
|
# Recreate ConfigMap
|
||||||
|
kubectl delete configmap python-flask-app
|
||||||
|
kubectl create configmap python-flask-app --from-file=app.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Flask App Errors
|
||||||
|
```bash
|
||||||
|
# Check Flask app logs
|
||||||
|
kubectl logs deployment/python-flask
|
||||||
|
|
||||||
|
# Test Flask app locally
|
||||||
|
python app.py # Test locally first
|
||||||
|
|
||||||
|
# Check for syntax errors
|
||||||
|
python -m py_compile app.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Port Forward Fails
|
||||||
|
```bash
|
||||||
|
# Check if port is in use
|
||||||
|
lsof -i :5000
|
||||||
|
|
||||||
|
# Try different port
|
||||||
|
kubectl port-forward service/python-flask-service 5002:5000
|
||||||
|
curl http://localhost:5002
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📚 More Examples
|
||||||
|
|
||||||
|
This is currently one of the complete examples. Future examples will include:
|
||||||
|
- **python-flask/** - This example (COMPLETED)
|
||||||
|
- **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 access
|
||||||
|
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**: Use `curl` for all API testing
|
||||||
|
6. **Flask Logs**: `kubectl logs deployment/python-flask` for debugging
|
||||||
|
7. **Config Updates**: Update ConfigMap then restart deployment: `kubectl rollout restart deployment/python-flask`
|
||||||
|
8. **API Documentation**: The root endpoint (`/`) provides complete API documentation
|
||||||
|
9. **Error Handling**: Test error cases like invalid operations or missing parameters
|
||||||
|
10. **Environment Testing**: Test in both development and production modes
|
||||||
|
|
||||||
|
## 🎉 Success Indicators
|
||||||
|
|
||||||
|
You'll know everything is working when:
|
||||||
|
- ✅ `kubectl get pods` shows python-flask pod in "Running" status
|
||||||
|
- ✅ `kubectl get svc` shows python-flask-service created
|
||||||
|
- ✅ `curl http://localhost:5000` returns API information
|
||||||
|
- ✅ All endpoints (`/time`, `/random`, `/health`, `/calc`, `/info`) return proper JSON
|
||||||
|
- ✅ `kubectl logs deployment/python-flask` shows Flask starting without errors
|
||||||
|
- ✅ ConfigMap `python-flask-app` exists and contains app.py
|
||||||
|
|
||||||
|
## 🏆 Next Steps
|
||||||
|
|
||||||
|
After completing this example, you can:
|
||||||
|
1. **Customize Endpoints**: Add your own API endpoints
|
||||||
|
2. **Database Integration**: Connect to persistent databases
|
||||||
|
3. **Add More Examples**: Try the Redis cache example
|
||||||
|
4. **Scale Up**: Learn about load balancing with multiple replicas
|
||||||
|
5. **Advanced Patterns**: Learn about secrets, config maps, and persistent volumes
|
||||||
|
|
||||||
|
## 🚀 API Testing Tools
|
||||||
|
|
||||||
|
### Postman/Insomnia
|
||||||
|
Import the API into API testing tools:
|
||||||
|
```
|
||||||
|
http://localhost:5000/
|
||||||
|
http://localhost:5000/time
|
||||||
|
http://localhost:5000/random
|
||||||
|
http://localhost:5000/health
|
||||||
|
http://localhost:5000/calc?operation=add&a=5&b=3
|
||||||
|
http://localhost:5000/info
|
||||||
|
```
|
||||||
|
|
||||||
|
### Command Line Tools
|
||||||
|
```bash
|
||||||
|
# Install jq for JSON formatting
|
||||||
|
curl http://localhost:5000 | jq '.'
|
||||||
|
|
||||||
|
# Create an API test script
|
||||||
|
cat > test-api.sh << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
echo "Testing Python Flask API..."
|
||||||
|
curl -s http://localhost:5000 | jq '.api'
|
||||||
|
curl -s http://localhost:5000/time | jq '.current_time'
|
||||||
|
curl -s http://localhost:5000/random | jq '.quote'
|
||||||
|
echo "All tests completed!"
|
||||||
|
EOF
|
||||||
|
chmod +x test-api.sh
|
||||||
|
./test-api.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📞 Getting Help
|
||||||
|
|
||||||
|
- **Troubleshooting**: Check the troubleshooting section above
|
||||||
|
- **Mycelium Cloud Docs**: See main repository README
|
||||||
|
- **Flask Documentation**: https://flask.palletsprojects.com/
|
||||||
|
- **Kubectl Help**: `kubectl get pods --help` for command reference
|
||||||
|
- **API Testing**: Use Postman, Insomnia, or curl for testing
|
||||||
|
- **Support**: Contact Mycelium Cloud support team
|
||||||
|
|
||||||
|
For more help, visit our [documentation](../../README.md) or contact support.
|
||||||
Reference in New Issue
Block a user