first commit
This commit is contained in:
76
.gitea/workflows/build.yml
Normal file
76
.gitea/workflows/build.yml
Normal file
@@ -0,0 +1,76 @@
|
||||
name: Build and Push Docker Images
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-web:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Gitea Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: git.commandware.com
|
||||
username: ${{ gitea.actor }}
|
||||
password: ${{ secrets.GITEA_TOKEN }}
|
||||
|
||||
- name: Extract metadata for web image
|
||||
id: meta-web
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: git.commandware.com/demos/api7-demo/web
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
|
||||
- name: Build and push web image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./web
|
||||
file: ./web/Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta-web.outputs.tags }}
|
||||
labels: ${{ steps.meta-web.outputs.labels }}
|
||||
cache-from: type=registry,ref=git.commandware.com/demos/api7-demo/web:buildcache
|
||||
cache-to: type=registry,ref=git.commandware.com/demos/api7-demo/web:buildcache,mode=max
|
||||
|
||||
build-api:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Gitea Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: git.commandware.com
|
||||
username: ${{ gitea.actor }}
|
||||
password: ${{ secrets.GITEA_TOKEN }}
|
||||
|
||||
- name: Extract metadata for api image
|
||||
id: meta-api
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: git.commandware.com/demos/api7-demo/api
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
|
||||
- name: Build and push api image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./api
|
||||
file: ./api/Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta-api.outputs.tags }}
|
||||
labels: ${{ steps.meta-api.outputs.labels }}
|
||||
cache-from: type=registry,ref=git.commandware.com/demos/api7-demo/api:buildcache
|
||||
cache-to: type=registry,ref=git.commandware.com/demos/api7-demo/api:buildcache,mode=max
|
||||
492
README.md
Normal file
492
README.md
Normal file
@@ -0,0 +1,492 @@
|
||||
# API7 Demo - FastAPI Applications
|
||||
|
||||
Demo project showcasing two FastAPI applications deployed on Kubernetes through API7 Enterprise Gateway with automated CI/CD using Gitea.
|
||||
|
||||
## 📁 Project Structure
|
||||
|
||||
```
|
||||
api7-demo/
|
||||
├── web/ # Web application
|
||||
│ ├── main.py # FastAPI web app with HTML UI
|
||||
│ ├── Dockerfile # Container image
|
||||
│ └── requirements.txt # Python dependencies
|
||||
├── api/ # API application
|
||||
│ ├── main.py # FastAPI REST API with Swagger
|
||||
│ ├── Dockerfile # Container image
|
||||
│ └── requirements.txt # Python dependencies
|
||||
├── .gitea/
|
||||
│ └── workflows/
|
||||
│ └── build.yml # CI/CD pipeline
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## 🌐 Applications
|
||||
|
||||
### Web Application (`web/`)
|
||||
|
||||
Modern web interface with:
|
||||
- Responsive HTML dashboard
|
||||
- System information display
|
||||
- Health check endpoints
|
||||
|
||||
**Endpoints:**
|
||||
- `GET /` - Main webpage
|
||||
- `GET /health` - Health check
|
||||
|
||||
**Port:** 8000
|
||||
|
||||
### API Application (`api/`)
|
||||
|
||||
REST API with full documentation:
|
||||
- CRUD operations for Items and Users
|
||||
- Automatic Swagger/OpenAPI docs
|
||||
- Data validation with Pydantic
|
||||
|
||||
**Key Endpoints:**
|
||||
- `GET /docs` - Swagger UI
|
||||
- `GET /items` - List items
|
||||
- `POST /items` - Create item
|
||||
- `GET /users` - List users
|
||||
- `GET /health` - Health check
|
||||
|
||||
**Port:** 8001 (internally 8000)
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Local Development
|
||||
|
||||
**Web Application:**
|
||||
```bash
|
||||
cd web
|
||||
pip install -r requirements.txt
|
||||
python main.py
|
||||
# Access at http://localhost:8000
|
||||
```
|
||||
|
||||
**API Application:**
|
||||
```bash
|
||||
cd api
|
||||
pip install -r requirements.txt
|
||||
python main.py
|
||||
# Swagger at http://localhost:8000/docs
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
**Build and run Web:**
|
||||
```bash
|
||||
docker build -t web-app ./web
|
||||
docker run -p 8000:8000 web-app
|
||||
```
|
||||
|
||||
**Build and run API:**
|
||||
```bash
|
||||
docker build -t api-app ./api
|
||||
docker run -p 8001:8000 api-app
|
||||
```
|
||||
|
||||
## 🐳 CI/CD with Gitea
|
||||
|
||||
### Automated Pipeline
|
||||
|
||||
The `.gitea/workflows/build.yml` pipeline automatically:
|
||||
1. Builds Docker images for both applications
|
||||
2. Pushes to Gitea container registry
|
||||
3. Tags images with branch name
|
||||
4. Implements layer caching for faster builds
|
||||
|
||||
**Triggers:**
|
||||
- Any branch push
|
||||
- Manual dispatch
|
||||
|
||||
**Registry:** `git.commandware.com/demos/api7-demo`
|
||||
|
||||
**Images:**
|
||||
- `git.commandware.com/demos/api7-demo/web:<branch-name>`
|
||||
- `git.commandware.com/demos/api7-demo/api:<branch-name>`
|
||||
|
||||
### Setup
|
||||
|
||||
1. **Create `GITEA_TOKEN` secret:**
|
||||
- Repository Settings → Secrets → Add Secret
|
||||
- Name: `GITEA_TOKEN`
|
||||
- Generate token at: User Settings → Applications → Generate Token
|
||||
- Required scope: `write:package`
|
||||
|
||||
2. **Push to trigger build:**
|
||||
```bash
|
||||
git push origin main
|
||||
```
|
||||
|
||||
## ☸️ Kubernetes Deployment
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Kubernetes cluster (v1.19+)
|
||||
- API7 Enterprise Gateway installed
|
||||
- Namespace: `api7ee`
|
||||
|
||||
### Deployment Manifest
|
||||
|
||||
**k8s-deployments.yaml:**
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: web
|
||||
namespace: api7ee
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: web
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: web
|
||||
spec:
|
||||
containers:
|
||||
- name: web
|
||||
image: git.commandware.com/demos/api7-demo/web:main
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
name: http
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8000
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: web-service
|
||||
namespace: api7ee
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8000
|
||||
name: http
|
||||
selector:
|
||||
app: web
|
||||
---
|
||||
# Similar configuration for api deployment
|
||||
```
|
||||
|
||||
### Deploy
|
||||
|
||||
```bash
|
||||
kubectl apply -f k8s-deployments.yaml
|
||||
kubectl rollout status deployment/web -n api7ee
|
||||
kubectl rollout status deployment/api -n api7ee
|
||||
```
|
||||
|
||||
## 🔌 API7 Gateway Configuration
|
||||
|
||||
### Route Configuration (ADC)
|
||||
|
||||
**api7-routes.yaml:**
|
||||
```yaml
|
||||
services:
|
||||
- name: web-service
|
||||
upstream:
|
||||
name: web-upstream
|
||||
scheme: http
|
||||
type: roundrobin
|
||||
discovery_type: kubernetes
|
||||
service_name: api7ee/web-service:http
|
||||
routes:
|
||||
- name: web-route
|
||||
uris:
|
||||
- /*
|
||||
hosts:
|
||||
- demo.yourdomain.com
|
||||
plugins:
|
||||
redirect:
|
||||
http_to_https: true
|
||||
|
||||
- name: api-service
|
||||
upstream:
|
||||
name: api-upstream
|
||||
scheme: http
|
||||
type: roundrobin
|
||||
discovery_type: kubernetes
|
||||
service_name: api7ee/api-service:http
|
||||
routes:
|
||||
- name: api-route
|
||||
priority: 10
|
||||
uris:
|
||||
- /api
|
||||
- /api/*
|
||||
hosts:
|
||||
- demo.yourdomain.com
|
||||
plugins:
|
||||
redirect:
|
||||
http_to_https: true
|
||||
proxy-rewrite:
|
||||
regex_uri:
|
||||
- ^/api/(.*)
|
||||
- /$1
|
||||
|
||||
ssls:
|
||||
- snis:
|
||||
- "*.yourdomain.com"
|
||||
certificates:
|
||||
- certificate: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
<YOUR_CERTIFICATE>
|
||||
-----END CERTIFICATE-----
|
||||
key: |
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
<YOUR_KEY>
|
||||
-----END PRIVATE KEY-----
|
||||
```
|
||||
|
||||
### Sync Configuration
|
||||
|
||||
```bash
|
||||
adc sync -f api7-routes.yaml \
|
||||
--backend api7ee \
|
||||
--server https://api7-dashboard.yourdomain.com \
|
||||
--token <YOUR_API7_TOKEN> \
|
||||
--gateway-group default \
|
||||
--tls-skip-verify
|
||||
```
|
||||
|
||||
### Publish Routes
|
||||
|
||||
Routes must be published via API7 Dashboard to become active:
|
||||
|
||||
1. Navigate to **Services** → Select service
|
||||
2. Go to **Routes** tab
|
||||
3. Click **"Publish"** for each route
|
||||
4. Select gateway group: **"default"**
|
||||
5. Confirm
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
### Test Endpoints
|
||||
|
||||
```bash
|
||||
# Web application
|
||||
curl https://demo.yourdomain.com
|
||||
|
||||
# API health check
|
||||
curl https://demo.yourdomain.com/api/health
|
||||
|
||||
# API Swagger (if exposed)
|
||||
curl https://demo.yourdomain.com/api/docs
|
||||
|
||||
# Verify HTTP → HTTPS redirect
|
||||
curl -I http://demo.yourdomain.com
|
||||
```
|
||||
|
||||
### Verify Service Discovery
|
||||
|
||||
```bash
|
||||
# Scale deployment
|
||||
kubectl scale deployment web -n api7ee --replicas=5
|
||||
|
||||
# API7 automatically discovers new endpoints
|
||||
kubectl get endpoints -n api7ee web-service
|
||||
|
||||
# Scale back
|
||||
kubectl scale deployment web -n api7ee --replicas=2
|
||||
```
|
||||
|
||||
## 📊 Architecture
|
||||
|
||||
```
|
||||
Internet
|
||||
↓
|
||||
LoadBalancer (External IP)
|
||||
↓
|
||||
NGINX Ingress Controller
|
||||
↓
|
||||
TLS Termination (Let's Encrypt)
|
||||
↓
|
||||
API7 Gateway (ClusterIP)
|
||||
↓
|
||||
[Kubernetes Service Discovery]
|
||||
↓
|
||||
┌──────────────┬──────────────┐
|
||||
│ Web Service │ API Service │
|
||||
└──────────────┴──────────────┘
|
||||
```
|
||||
|
||||
### Traffic Routing
|
||||
|
||||
- `demo.yourdomain.com/api/*` → API Service (priority 10, strips `/api` prefix)
|
||||
- `demo.yourdomain.com/*` → Web Service (default priority)
|
||||
|
||||
## 🔧 API7 Enterprise Setup Guide
|
||||
|
||||
### Certificate Management
|
||||
|
||||
**Using cert-manager with Cloudflare:**
|
||||
|
||||
```yaml
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: cloudflare-acme-prod
|
||||
spec:
|
||||
acme:
|
||||
email: your-email@example.com
|
||||
server: https://acme-v02.api.letsencrypt.org/directory
|
||||
privateKeySecretRef:
|
||||
name: letsencrypt-prod-key
|
||||
solvers:
|
||||
- dns01:
|
||||
cloudflare:
|
||||
apiTokenSecretRef:
|
||||
name: cloudflare-api-token-secret
|
||||
key: api-token
|
||||
```
|
||||
|
||||
**Create Cloudflare secret:**
|
||||
```bash
|
||||
kubectl create secret generic cloudflare-api-token-secret \
|
||||
-n cert-manager \
|
||||
--from-literal=api-token=YOUR_TOKEN
|
||||
```
|
||||
|
||||
### Kubernetes Service Discovery
|
||||
|
||||
**Configure in API7 Dashboard:**
|
||||
|
||||
1. **Settings → Service Registry → Add Service Registry**
|
||||
2. **Select:** Kubernetes
|
||||
3. **Configure:**
|
||||
```
|
||||
Name: kubernetes-cluster
|
||||
API Server: https://kubernetes.default.svc.cluster.local:443
|
||||
Token Path: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||
Namespace Filter: api7ee (optional)
|
||||
```
|
||||
|
||||
**Verify RBAC permissions:**
|
||||
```bash
|
||||
kubectl create clusterrolebinding api7-gateway-discovery \
|
||||
--clusterrole=view \
|
||||
--serviceaccount=<API7_NAMESPACE>:default
|
||||
```
|
||||
|
||||
### Ingress Configuration
|
||||
|
||||
**Example ingress for API7 Gateway:**
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: api7-gateway-ingress
|
||||
namespace: api7ee
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
tls:
|
||||
- hosts:
|
||||
- demo.yourdomain.com
|
||||
secretName: demo-tls
|
||||
rules:
|
||||
- host: demo.yourdomain.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: api7-gateway-service
|
||||
port:
|
||||
number: 80
|
||||
```
|
||||
|
||||
**Note:** Ingress backend points to API7 Gateway service, not application services.
|
||||
|
||||
## 🛠️ Troubleshooting
|
||||
|
||||
### Routes Return 404
|
||||
|
||||
**Problem:** Routes synced but returning 404
|
||||
|
||||
**Solution:** Routes not published. Publish via API7 Dashboard.
|
||||
|
||||
### Service Discovery Not Working
|
||||
|
||||
**Problem:** `service registry not found` error
|
||||
|
||||
**Checklist:**
|
||||
- ✅ Service registry configured in dashboard
|
||||
- ✅ Registry status shows "Connected"
|
||||
- ✅ RBAC permissions granted
|
||||
- ✅ Service ports have `name` field
|
||||
|
||||
### Certificate Issues
|
||||
|
||||
**Problem:** Certificate not trusted
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Check certificate status
|
||||
kubectl get certificate -n api7ee
|
||||
kubectl describe certificate -n api7ee <cert-name>
|
||||
|
||||
# Check cert-manager logs
|
||||
kubectl logs -n cert-manager -l app.kubernetes.io/name=cert-manager --tail=50
|
||||
```
|
||||
|
||||
### Container Images Not Found
|
||||
|
||||
**Problem:** ImagePullBackOff in Kubernetes
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Create registry secret
|
||||
kubectl create secret docker-registry gitea-registry \
|
||||
--docker-server=git.commandware.com \
|
||||
--docker-username=<USERNAME> \
|
||||
--docker-password=<TOKEN> \
|
||||
-n api7ee
|
||||
|
||||
# Add to deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: gitea-registry
|
||||
```
|
||||
|
||||
## 📚 Resources
|
||||
|
||||
- **API7 Documentation:** https://docs.api7.ai/
|
||||
- **APISIX Documentation:** https://apisix.apache.org/docs/
|
||||
- **FastAPI Documentation:** https://fastapi.tiangolo.com/
|
||||
- **Gitea Actions:** https://docs.gitea.com/usage/actions/overview
|
||||
|
||||
## 🔐 Best Practices
|
||||
|
||||
### Security
|
||||
- ✅ Use TLS for all external traffic
|
||||
- ✅ Implement rate limiting on public endpoints
|
||||
- ✅ Store secrets in Kubernetes Secrets or external vault
|
||||
- ✅ Use least-privilege RBAC permissions
|
||||
|
||||
### Performance
|
||||
- ✅ Enable service discovery for automatic scaling
|
||||
- ✅ Configure appropriate resource limits
|
||||
- ✅ Use Docker layer caching in CI/CD
|
||||
- ✅ Implement health checks and readiness probes
|
||||
|
||||
### Monitoring
|
||||
- ✅ Monitor gateway metrics in API7 Dashboard
|
||||
- ✅ Track API usage and performance
|
||||
- ✅ Set up alerts for certificate expiration
|
||||
- ✅ Review application logs regularly
|
||||
|
||||
## 📝 License
|
||||
|
||||
Demo project for API7 Enterprise Gateway evaluation.
|
||||
|
||||
---
|
||||
|
||||
**Repository:** https://git.commandware.com/demos/api7-demo.git
|
||||
16
api/.dockerignore
Normal file
16
api/.dockerignore
Normal file
@@ -0,0 +1,16 @@
|
||||
__pycache__
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
.Python
|
||||
env/
|
||||
venv/
|
||||
.venv/
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
.pytest_cache/
|
||||
.coverage
|
||||
htmlcov/
|
||||
*.log
|
||||
.DS_Store
|
||||
.env
|
||||
15
api/Dockerfile
Normal file
15
api/Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies
|
||||
RUN pip install --no-cache-dir fastapi uvicorn[standard] pydantic
|
||||
|
||||
# Copy application
|
||||
COPY main.py .
|
||||
|
||||
# Expose port
|
||||
EXPOSE 8001
|
||||
|
||||
# Run the application
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8001"]
|
||||
87
api/README.md
Normal file
87
api/README.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# API Service - FastAPI
|
||||
|
||||
A RESTful API service built with FastAPI featuring Swagger documentation.
|
||||
|
||||
## Features
|
||||
|
||||
- 📚 Automatic Swagger/OpenAPI documentation
|
||||
- 🔄 RESTful API endpoints
|
||||
- ✅ Data validation with Pydantic
|
||||
- 📊 Statistics and monitoring endpoints
|
||||
- ❤️ Health check endpoints
|
||||
|
||||
## Local Development
|
||||
|
||||
### Run with Python
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Run the application
|
||||
python main.py
|
||||
|
||||
# Or use uvicorn directly
|
||||
uvicorn main:app --reload --host 0.0.0.0 --port 8000
|
||||
```
|
||||
|
||||
### Run with Docker
|
||||
|
||||
```bash
|
||||
# Build image
|
||||
docker build -t fastapi-api .
|
||||
|
||||
# Run container
|
||||
docker run -p 8000:8000 fastapi-api
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Items
|
||||
- `GET /items` - List all items (with pagination)
|
||||
- `GET /items/{item_id}` - Get specific item
|
||||
- `POST /items` - Create new item
|
||||
- `PUT /items/{item_id}` - Update item
|
||||
- `DELETE /items/{item_id}` - Delete item
|
||||
|
||||
### Users
|
||||
- `GET /users` - List all users
|
||||
- `GET /users/{user_id}` - Get specific user
|
||||
- `POST /users` - Create new user
|
||||
|
||||
### Other
|
||||
- `GET /` - API information
|
||||
- `GET /health` - Health check
|
||||
- `GET /info` - Service information
|
||||
- `GET /stats` - API statistics
|
||||
|
||||
## Documentation
|
||||
|
||||
- Swagger UI: http://localhost:8000/docs
|
||||
- ReDoc: http://localhost:8000/redoc
|
||||
- OpenAPI JSON: http://localhost:8000/openapi.json
|
||||
|
||||
## Example Requests
|
||||
|
||||
### Create Item
|
||||
```bash
|
||||
curl -X POST "http://localhost:8000/items" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"id": 4,
|
||||
"name": "Monitor",
|
||||
"description": "4K Display",
|
||||
"price": 299.99,
|
||||
"in_stock": true
|
||||
}'
|
||||
```
|
||||
|
||||
### Get Items
|
||||
```bash
|
||||
curl "http://localhost:8000/items?skip=0&limit=10&in_stock=true"
|
||||
```
|
||||
|
||||
### Get Statistics
|
||||
```bash
|
||||
curl "http://localhost:8000/stats"
|
||||
```
|
||||
123
api/main.py
Normal file
123
api/main.py
Normal file
@@ -0,0 +1,123 @@
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from pydantic import BaseModel
|
||||
from typing import List, Optional
|
||||
import uvicorn
|
||||
from datetime import datetime
|
||||
|
||||
app = FastAPI(
|
||||
title="API Demo Application",
|
||||
description="Demo API with Swagger documentation",
|
||||
version="1.0.0"
|
||||
)
|
||||
|
||||
# Models
|
||||
class Item(BaseModel):
|
||||
id: Optional[int] = None
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
price: float
|
||||
in_stock: bool = True
|
||||
|
||||
class User(BaseModel):
|
||||
id: Optional[int] = None
|
||||
username: str
|
||||
email: str
|
||||
active: bool = True
|
||||
|
||||
# In-memory storage
|
||||
items_db = [
|
||||
{"id": 1, "name": "Laptop", "description": "High-performance laptop", "price": 999.99, "in_stock": True},
|
||||
{"id": 2, "name": "Mouse", "description": "Wireless mouse", "price": 29.99, "in_stock": True},
|
||||
{"id": 3, "name": "Keyboard", "description": "Mechanical keyboard", "price": 79.99, "in_stock": False},
|
||||
]
|
||||
|
||||
users_db = [
|
||||
{"id": 1, "username": "john_doe", "email": "john@example.com", "active": True},
|
||||
{"id": 2, "username": "jane_smith", "email": "jane@example.com", "active": True},
|
||||
]
|
||||
|
||||
# Root endpoint
|
||||
@app.get("/")
|
||||
async def root():
|
||||
"""Root endpoint with API information"""
|
||||
return {
|
||||
"message": "Welcome to API Demo",
|
||||
"version": "1.0.0",
|
||||
"docs": "/docs",
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
# Health check
|
||||
@app.get("/health")
|
||||
async def health():
|
||||
"""Health check endpoint"""
|
||||
return {"status": "healthy", "service": "api", "timestamp": datetime.now().isoformat()}
|
||||
|
||||
# Items endpoints
|
||||
@app.get("/items", response_model=List[Item], tags=["Items"])
|
||||
async def get_items():
|
||||
"""Get all items"""
|
||||
return items_db
|
||||
|
||||
@app.get("/items/{item_id}", response_model=Item, tags=["Items"])
|
||||
async def get_item(item_id: int):
|
||||
"""Get a specific item by ID"""
|
||||
item = next((item for item in items_db if item["id"] == item_id), None)
|
||||
if item is None:
|
||||
raise HTTPException(status_code=404, detail="Item not found")
|
||||
return item
|
||||
|
||||
@app.post("/items", response_model=Item, tags=["Items"])
|
||||
async def create_item(item: Item):
|
||||
"""Create a new item"""
|
||||
new_id = max([i["id"] for i in items_db]) + 1 if items_db else 1
|
||||
item_dict = item.dict()
|
||||
item_dict["id"] = new_id
|
||||
items_db.append(item_dict)
|
||||
return item_dict
|
||||
|
||||
@app.put("/items/{item_id}", response_model=Item, tags=["Items"])
|
||||
async def update_item(item_id: int, item: Item):
|
||||
"""Update an existing item"""
|
||||
for idx, existing_item in enumerate(items_db):
|
||||
if existing_item["id"] == item_id:
|
||||
item_dict = item.dict()
|
||||
item_dict["id"] = item_id
|
||||
items_db[idx] = item_dict
|
||||
return item_dict
|
||||
raise HTTPException(status_code=404, detail="Item not found")
|
||||
|
||||
@app.delete("/items/{item_id}", tags=["Items"])
|
||||
async def delete_item(item_id: int):
|
||||
"""Delete an item"""
|
||||
for idx, item in enumerate(items_db):
|
||||
if item["id"] == item_id:
|
||||
items_db.pop(idx)
|
||||
return {"message": "Item deleted successfully"}
|
||||
raise HTTPException(status_code=404, detail="Item not found")
|
||||
|
||||
# Users endpoints
|
||||
@app.get("/users", response_model=List[User], tags=["Users"])
|
||||
async def get_users():
|
||||
"""Get all users"""
|
||||
return users_db
|
||||
|
||||
@app.get("/users/{user_id}", response_model=User, tags=["Users"])
|
||||
async def get_user(user_id: int):
|
||||
"""Get a specific user by ID"""
|
||||
user = next((user for user in users_db if user["id"] == user_id), None)
|
||||
if user is None:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
return user
|
||||
|
||||
@app.post("/users", response_model=User, tags=["Users"])
|
||||
async def create_user(user: User):
|
||||
"""Create a new user"""
|
||||
new_id = max([u["id"] for u in users_db]) + 1 if users_db else 1
|
||||
user_dict = user.dict()
|
||||
user_dict["id"] = new_id
|
||||
users_db.append(user_dict)
|
||||
return user_dict
|
||||
|
||||
if __name__ == "__main__":
|
||||
uvicorn.run(app, host="0.0.0.0", port=8001)
|
||||
3
api/requirements.txt
Normal file
3
api/requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
fastapi==0.104.1
|
||||
uvicorn[standard]==0.24.0
|
||||
pydantic==2.5.0
|
||||
20
web/.dockerignore
Normal file
20
web/.dockerignore
Normal file
@@ -0,0 +1,20 @@
|
||||
__pycache__
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
.Python
|
||||
*.so
|
||||
*.egg
|
||||
*.egg-info
|
||||
dist
|
||||
build
|
||||
.git
|
||||
.gitignore
|
||||
README.md
|
||||
site/
|
||||
.pytest_cache
|
||||
.coverage
|
||||
htmlcov
|
||||
.env
|
||||
.venv
|
||||
venv/
|
||||
22
web/Dockerfile
Normal file
22
web/Dockerfile
Normal file
@@ -0,0 +1,22 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy requirements first for better caching
|
||||
COPY requirements.txt .
|
||||
|
||||
# Install dependencies
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Copy application and documentation
|
||||
COPY main.py .
|
||||
COPY docs/ ./docs/
|
||||
|
||||
# Build documentation during image build
|
||||
RUN mkdocs build -f docs/mkdocs.yml -d site
|
||||
|
||||
# Expose port
|
||||
EXPOSE 8000
|
||||
|
||||
# Run the application
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||
168
web/README.md
Normal file
168
web/README.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# Web Application with Documentation
|
||||
|
||||
FastAPI web application serving a demo dashboard and comprehensive MkDocs documentation.
|
||||
|
||||
## Features
|
||||
|
||||
- **Web Dashboard**: Simple HTML interface with metrics display
|
||||
- **Documentation Site**: Complete API7 Enterprise setup guide at `/docs`
|
||||
- **Health Checks**: Monitoring endpoint at `/health`
|
||||
|
||||
## Documentation
|
||||
|
||||
The application includes comprehensive documentation built with MkDocs Material theme, covering:
|
||||
|
||||
- **Architecture Overview**: Complete infrastructure and component details
|
||||
- **Getting Started**: Quick setup and deployment guide
|
||||
- **API7 Configuration**: Route and service configuration with examples
|
||||
- **Kubernetes Resources**: Complete resource reference
|
||||
- **CI/CD Pipeline**: Gitea Actions workflow documentation
|
||||
- **Troubleshooting**: Common issues and solutions
|
||||
|
||||
## Running Locally
|
||||
|
||||
### Prerequisites
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Start Application
|
||||
|
||||
```bash
|
||||
python main.py
|
||||
```
|
||||
|
||||
**Access**:
|
||||
|
||||
- Main Page: http://localhost:8000
|
||||
- Documentation: http://localhost:8000/docs/
|
||||
- Health Check: http://localhost:8000/health
|
||||
|
||||
### Build Documentation Manually
|
||||
|
||||
```bash
|
||||
mkdocs build -f docs/mkdocs.yml -d site
|
||||
```
|
||||
|
||||
## Docker
|
||||
|
||||
### Build Image
|
||||
|
||||
```bash
|
||||
docker build -t web-app .
|
||||
```
|
||||
|
||||
The Dockerfile:
|
||||
|
||||
1. Installs Python dependencies
|
||||
2. Copies application and documentation source
|
||||
3. Builds static documentation site with MkDocs
|
||||
4. Serves both the app and docs
|
||||
|
||||
### Run Container
|
||||
|
||||
```bash
|
||||
docker run -p 8000:8000 web-app
|
||||
```
|
||||
|
||||
## Kubernetes Deployment
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: web
|
||||
namespace: api7ee
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: web
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: web
|
||||
spec:
|
||||
containers:
|
||||
- name: web
|
||||
image: git.commandware.com/demos/api7-demo/web:main
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
name: http
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8000
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8000
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: web-service
|
||||
namespace: api7ee
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8000
|
||||
name: http
|
||||
selector:
|
||||
app: web
|
||||
```
|
||||
|
||||
## Documentation Structure
|
||||
|
||||
```
|
||||
docs/
|
||||
├── mkdocs.yml # MkDocs configuration
|
||||
├── index.md # Documentation home
|
||||
├── getting-started.md # Quick start guide
|
||||
├── architecture.md # Infrastructure architecture
|
||||
├── kubernetes-resources.md # K8s resources reference
|
||||
├── api7-configuration.md # API7 Gateway config guide
|
||||
├── cicd-pipeline.md # CI/CD documentation
|
||||
└── troubleshooting.md # Troubleshooting guide
|
||||
```
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Endpoint | Description |
|
||||
| --------- | --------------------------- |
|
||||
| `/` | Main web dashboard |
|
||||
| `/docs/` | Documentation site (MkDocs) |
|
||||
| `/health` | Health check endpoint |
|
||||
|
||||
## CI/CD
|
||||
|
||||
Images are automatically built and pushed to Gitea registry on every push:
|
||||
|
||||
**Registry**: `git.commandware.com/demos/api7-demo/web:<branch>`
|
||||
|
||||
See [CI/CD Pipeline documentation](docs/cicd-pipeline.md) for details.
|
||||
|
||||
## Development
|
||||
|
||||
### Update Documentation
|
||||
|
||||
1. Edit markdown files in `docs/` directory
|
||||
2. Test locally:
|
||||
```bash
|
||||
mkdocs serve -f docs/mkdocs.yml
|
||||
```
|
||||
3. View at http://localhost:8001
|
||||
4. Rebuild with `mkdocs build` or rebuild Docker image
|
||||
|
||||
### Dependencies
|
||||
|
||||
- **fastapi**: Web framework
|
||||
- **uvicorn**: ASGI server
|
||||
- **mkdocs**: Documentation site generator
|
||||
- **mkdocs-material**: Material theme for MkDocs
|
||||
|
||||
---
|
||||
|
||||
_FastAPI web application with integrated MkDocs documentation for API7 Enterprise demo._
|
||||
615
web/docs/api7-configuration.md
Normal file
615
web/docs/api7-configuration.md
Normal file
@@ -0,0 +1,615 @@
|
||||
# Gateway Configuration
|
||||
|
||||
Complete guide for configuring routes, services, and policies in the API Gateway.
|
||||
|
||||
## Declarative Configuration Management
|
||||
|
||||
The gateway supports declarative configuration management using YAML files through CLI tools.
|
||||
|
||||
### CLI Tool Installation
|
||||
|
||||
```bash
|
||||
# Install the gateway CLI tool
|
||||
# Installation method varies by gateway solution
|
||||
|
||||
# Verify installation
|
||||
<cli-tool> version
|
||||
```
|
||||
|
||||
### Configuration Structure
|
||||
|
||||
```yaml
|
||||
services:
|
||||
- name: <service-name>
|
||||
upstream:
|
||||
name: <upstream-name>
|
||||
scheme: http|https
|
||||
type: roundrobin|chash|least_conn|ewma
|
||||
# Option 1: Static nodes
|
||||
nodes:
|
||||
- host: <hostname>
|
||||
port: <port>
|
||||
weight: <1-100>
|
||||
# Option 2: Service discovery
|
||||
discovery_type: kubernetes
|
||||
service_name: <namespace>/<service-name>:<port-name>
|
||||
routes:
|
||||
- name: <route-name>
|
||||
priority: <number>
|
||||
uris:
|
||||
- <path-pattern>
|
||||
hosts:
|
||||
- <hostname>
|
||||
methods:
|
||||
- GET|POST|PUT|DELETE|...
|
||||
plugins:
|
||||
<plugin-name>:
|
||||
<plugin-config>
|
||||
|
||||
ssls:
|
||||
- snis:
|
||||
- <domain>
|
||||
certificates:
|
||||
- certificate: |
|
||||
<pem-certificate>
|
||||
key: |
|
||||
<pem-key>
|
||||
```
|
||||
|
||||
## Service Discovery
|
||||
|
||||
### Kubernetes Service Discovery
|
||||
|
||||
**Prerequisites**:
|
||||
1. Service registry configured in Dashboard
|
||||
2. RBAC permissions for gateway service account
|
||||
3. Service ports must have `name` field
|
||||
|
||||
**Configuration**:
|
||||
|
||||
**Via Dashboard**:
|
||||
1. **Settings → Service Registry → Add Service Registry**
|
||||
2. Select: **Kubernetes**
|
||||
3. Configure:
|
||||
```
|
||||
Name: kubernetes-cluster
|
||||
API Server: https://kubernetes.default.svc.cluster.local:443
|
||||
Token Path: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||
Namespace Filter: <namespace>
|
||||
```
|
||||
|
||||
**RBAC Setup**:
|
||||
```bash
|
||||
kubectl create clusterrolebinding gateway-discovery \
|
||||
--clusterrole=view \
|
||||
--serviceaccount=<namespace>:default
|
||||
```
|
||||
|
||||
**Service Configuration**:
|
||||
```yaml
|
||||
upstream:
|
||||
discovery_type: kubernetes
|
||||
service_name: <namespace>/<service-name>:<port-name>
|
||||
# Format: <namespace>/<service-name>:<port-name>
|
||||
```
|
||||
|
||||
### Static Nodes (No Service Discovery)
|
||||
|
||||
```yaml
|
||||
upstream:
|
||||
nodes:
|
||||
- host: web-service.<namespace>.svc.cluster.local
|
||||
port: 80
|
||||
weight: 100
|
||||
- host: <cluster-ip>
|
||||
port: 80
|
||||
weight: 100
|
||||
```
|
||||
|
||||
## Route Configuration
|
||||
|
||||
### Basic Route
|
||||
|
||||
```yaml
|
||||
routes:
|
||||
- name: web-route
|
||||
uris:
|
||||
- /*
|
||||
hosts:
|
||||
- app.domain.com
|
||||
methods:
|
||||
- GET
|
||||
- POST
|
||||
plugins:
|
||||
redirect:
|
||||
http_to_https: true
|
||||
```
|
||||
|
||||
### Path-Based Routing with Priorities
|
||||
|
||||
```yaml
|
||||
services:
|
||||
- name: api-service
|
||||
upstream:
|
||||
discovery_type: kubernetes
|
||||
service_name: <namespace>/api-service:http
|
||||
routes:
|
||||
- name: api-route
|
||||
priority: 10 # Higher priority = evaluated first
|
||||
uris:
|
||||
- /api
|
||||
- /api/*
|
||||
hosts:
|
||||
- app.domain.com
|
||||
plugins:
|
||||
redirect:
|
||||
http_to_https: true
|
||||
proxy-rewrite:
|
||||
regex_uri:
|
||||
- ^/api/(.*)
|
||||
- /$1 # Strip /api prefix
|
||||
|
||||
- name: web-service
|
||||
upstream:
|
||||
discovery_type: kubernetes
|
||||
service_name: <namespace>/web-service:http
|
||||
routes:
|
||||
- name: web-route
|
||||
priority: 1 # Lower priority = fallback
|
||||
uris:
|
||||
- /*
|
||||
hosts:
|
||||
- app.domain.com
|
||||
```
|
||||
|
||||
**Traffic Flow**:
|
||||
- `app.domain.com/api/users` → api-service (receives `/users`)
|
||||
- `app.domain.com/anything-else` → web-service
|
||||
|
||||
### Wildcard Host Matching
|
||||
|
||||
```yaml
|
||||
routes:
|
||||
- name: wildcard-route
|
||||
uris:
|
||||
- /*
|
||||
hosts:
|
||||
- "*.domain.com"
|
||||
- domain.com
|
||||
```
|
||||
|
||||
### Multiple Hosts
|
||||
|
||||
```yaml
|
||||
routes:
|
||||
- name: multi-host-route
|
||||
uris:
|
||||
- /*
|
||||
hosts:
|
||||
- api.domain.com
|
||||
- api.domain.org
|
||||
- api.example.com
|
||||
```
|
||||
|
||||
## Plugins
|
||||
|
||||
### HTTP to HTTPS Redirect
|
||||
|
||||
```yaml
|
||||
plugins:
|
||||
redirect:
|
||||
http_to_https: true
|
||||
```
|
||||
|
||||
### Proxy Rewrite (Path Manipulation)
|
||||
|
||||
**Strip prefix**:
|
||||
```yaml
|
||||
plugins:
|
||||
proxy-rewrite:
|
||||
regex_uri:
|
||||
- ^/api/(.*)
|
||||
- /$1
|
||||
```
|
||||
|
||||
**Add prefix**:
|
||||
```yaml
|
||||
plugins:
|
||||
proxy-rewrite:
|
||||
uri: /backend$uri
|
||||
```
|
||||
|
||||
**Rewrite host**:
|
||||
```yaml
|
||||
plugins:
|
||||
proxy-rewrite:
|
||||
host: backend-service.<namespace>.svc.cluster.local
|
||||
```
|
||||
|
||||
### CORS Configuration
|
||||
|
||||
```yaml
|
||||
plugins:
|
||||
cors:
|
||||
allow_origins: "*"
|
||||
allow_methods: "GET,POST,PUT,DELETE,OPTIONS"
|
||||
allow_headers: "Content-Type,Authorization"
|
||||
allow_credential: true
|
||||
max_age: 3600
|
||||
```
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
**Per IP**:
|
||||
```yaml
|
||||
plugins:
|
||||
limit-req:
|
||||
rate: 100
|
||||
burst: 200
|
||||
key: remote_addr
|
||||
rejected_code: 429
|
||||
```
|
||||
|
||||
**Per Consumer**:
|
||||
```yaml
|
||||
plugins:
|
||||
limit-req:
|
||||
rate: 1000
|
||||
burst: 2000
|
||||
key: consumer_name
|
||||
```
|
||||
|
||||
### Authentication
|
||||
|
||||
**API Key**:
|
||||
```yaml
|
||||
plugins:
|
||||
key-auth:
|
||||
header: X-API-Key
|
||||
```
|
||||
|
||||
**JWT**:
|
||||
```yaml
|
||||
plugins:
|
||||
jwt-auth:
|
||||
key: my-secret-key
|
||||
algorithm: HS256
|
||||
```
|
||||
|
||||
**Basic Auth**:
|
||||
```yaml
|
||||
plugins:
|
||||
basic-auth: {}
|
||||
```
|
||||
|
||||
### Request/Response Transformation
|
||||
|
||||
**Add headers**:
|
||||
```yaml
|
||||
plugins:
|
||||
proxy-rewrite:
|
||||
headers:
|
||||
X-Forwarded-By: "API-Gateway"
|
||||
X-Custom-Header: "value"
|
||||
```
|
||||
|
||||
**Remove headers**:
|
||||
```yaml
|
||||
plugins:
|
||||
response-rewrite:
|
||||
headers:
|
||||
remove:
|
||||
- X-Internal-Header
|
||||
```
|
||||
|
||||
### Caching
|
||||
|
||||
```yaml
|
||||
plugins:
|
||||
proxy-cache:
|
||||
cache_method:
|
||||
- GET
|
||||
- HEAD
|
||||
cache_http_status:
|
||||
- 200
|
||||
- 301
|
||||
- 302
|
||||
cache_ttl: 3600
|
||||
```
|
||||
|
||||
### IP Restriction
|
||||
|
||||
**Whitelist**:
|
||||
```yaml
|
||||
plugins:
|
||||
ip-restriction:
|
||||
whitelist:
|
||||
- 192.168.1.0/24
|
||||
- 10.0.0.0/8
|
||||
```
|
||||
|
||||
**Blacklist**:
|
||||
```yaml
|
||||
plugins:
|
||||
ip-restriction:
|
||||
blacklist:
|
||||
- 203.0.113.0/24
|
||||
```
|
||||
|
||||
## SSL/TLS Configuration
|
||||
|
||||
### Using Existing Kubernetes Secret
|
||||
|
||||
```yaml
|
||||
ssls:
|
||||
- snis:
|
||||
- "*.domain.com"
|
||||
- domain.com
|
||||
certificates:
|
||||
- certificate: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
<CERTIFICATE_CONTENT>
|
||||
-----END CERTIFICATE-----
|
||||
key: |
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
<KEY_CONTENT>
|
||||
-----END PRIVATE KEY-----
|
||||
```
|
||||
|
||||
### Extract from Kubernetes Secret
|
||||
|
||||
```bash
|
||||
# Extract certificate
|
||||
kubectl get secret tls-secret -n <namespace> -o jsonpath='{.data.tls\.crt}' | base64 -d
|
||||
|
||||
# Extract key
|
||||
kubectl get secret tls-secret -n <namespace> -o jsonpath='{.data.tls\.key}' | base64 -d
|
||||
```
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
### Multiple Service Routes
|
||||
|
||||
**Configuration**:
|
||||
```yaml
|
||||
services:
|
||||
- name: frontend-service
|
||||
upstream:
|
||||
name: frontend-upstream
|
||||
scheme: http
|
||||
type: roundrobin
|
||||
nodes:
|
||||
- host: frontend-service.<namespace>.svc.cluster.local
|
||||
port: 80
|
||||
weight: 100
|
||||
routes:
|
||||
- name: frontend-route
|
||||
uris:
|
||||
- /*
|
||||
hosts:
|
||||
- app.domain.com
|
||||
plugins:
|
||||
redirect:
|
||||
http_to_https: true
|
||||
|
||||
- name: root-route
|
||||
priority: 1
|
||||
uris:
|
||||
- /
|
||||
- /~*
|
||||
hosts:
|
||||
- domain.com
|
||||
plugins:
|
||||
redirect:
|
||||
http_to_https: true
|
||||
|
||||
- name: api-service
|
||||
upstream:
|
||||
name: api-upstream
|
||||
scheme: http
|
||||
type: roundrobin
|
||||
nodes:
|
||||
- host: api-service.<namespace>.svc.cluster.local
|
||||
port: 80
|
||||
weight: 100
|
||||
routes:
|
||||
- name: api-route
|
||||
priority: 10
|
||||
uris:
|
||||
- /api
|
||||
- /api/*
|
||||
hosts:
|
||||
- domain.com
|
||||
plugins:
|
||||
redirect:
|
||||
http_to_https: true
|
||||
proxy-rewrite:
|
||||
regex_uri:
|
||||
- ^/api/(.*)
|
||||
- /$1
|
||||
```
|
||||
|
||||
**Traffic Flow**:
|
||||
- `app.domain.com/*` → Frontend Service
|
||||
- `domain.com/api/*` → API Service (with `/api` prefix stripped)
|
||||
- `domain.com/*` → Frontend Service
|
||||
|
||||
## Syncing Configuration
|
||||
|
||||
### Via CLI Tools
|
||||
|
||||
**Sync configuration**:
|
||||
```bash
|
||||
<cli-tool> sync -f config.yaml \
|
||||
--server <dashboard-url> \
|
||||
--token <api-token> \
|
||||
--gateway-group default
|
||||
```
|
||||
|
||||
**Dump current configuration**:
|
||||
```bash
|
||||
<cli-tool> dump \
|
||||
--server <dashboard-url> \
|
||||
--token <api-token> > current-config.yaml
|
||||
```
|
||||
|
||||
**Validate configuration**:
|
||||
```bash
|
||||
<cli-tool> validate -f config.yaml
|
||||
```
|
||||
|
||||
### Publishing Routes
|
||||
|
||||
**⚠️ Important**: Routes synced via CLI may need to be published via Dashboard.
|
||||
|
||||
**Steps**:
|
||||
1. Access Dashboard
|
||||
2. Navigate: **Services** → Select service
|
||||
3. Go to: **Routes** tab
|
||||
4. For each route:
|
||||
- Click: **Publish**
|
||||
- Select: Gateway group
|
||||
- Confirm
|
||||
|
||||
**Route Status**:
|
||||
- **Unpublished**: Synced but not active
|
||||
- **Published**: Active on gateway
|
||||
|
||||
## Advanced Configurations
|
||||
|
||||
### Multi-Environment Setup
|
||||
|
||||
**Development Gateway Group**:
|
||||
```bash
|
||||
# Sync to dev gateway group
|
||||
<cli-tool> sync -f config.yaml \
|
||||
--gateway-group dev \
|
||||
--server <dashboard-url> \
|
||||
--token <token>
|
||||
```
|
||||
|
||||
**Production Gateway Group**:
|
||||
```bash
|
||||
# Sync to prod gateway group
|
||||
<cli-tool> sync -f config.yaml \
|
||||
--gateway-group prod \
|
||||
--server <dashboard-url> \
|
||||
--token <token>
|
||||
```
|
||||
|
||||
### Health Checks
|
||||
|
||||
```yaml
|
||||
upstream:
|
||||
checks:
|
||||
active:
|
||||
http_path: /health
|
||||
healthy:
|
||||
interval: 5
|
||||
successes: 2
|
||||
unhealthy:
|
||||
interval: 5
|
||||
http_failures: 3
|
||||
```
|
||||
|
||||
### Retry Policy
|
||||
|
||||
```yaml
|
||||
upstream:
|
||||
retries: 3
|
||||
retry_timeout: 10
|
||||
pass_host: pass # or rewrite, node
|
||||
```
|
||||
|
||||
### Circuit Breaker
|
||||
|
||||
```yaml
|
||||
plugins:
|
||||
api-breaker:
|
||||
break_response_code: 503
|
||||
max_breaker_sec: 300
|
||||
unhealthy:
|
||||
http_statuses: [500, 503]
|
||||
failures: 3
|
||||
healthy:
|
||||
http_statuses: [200]
|
||||
successes: 3
|
||||
```
|
||||
|
||||
## Monitoring Route Performance
|
||||
|
||||
### View Metrics in Dashboard
|
||||
|
||||
1. Navigate: **Monitoring** → **Routes**
|
||||
2. Select route to view:
|
||||
- Request rate (req/s)
|
||||
- Latency percentiles (P50, P95, P99)
|
||||
- Error rate
|
||||
- Status code distribution
|
||||
|
||||
### Prometheus Metrics
|
||||
|
||||
Access Prometheus:
|
||||
```bash
|
||||
kubectl port-forward -n <namespace> svc/prometheus-server 9090:9090
|
||||
```
|
||||
|
||||
**Useful Queries**:
|
||||
```promql
|
||||
# Request rate by route
|
||||
sum(rate(http_requests_total[5m])) by (route)
|
||||
|
||||
# Latency P95
|
||||
histogram_quantile(0.95, sum(rate(http_latency_bucket[5m])) by (le, route))
|
||||
|
||||
# Error rate
|
||||
sum(rate(http_requests_total{code=~"5.."}[5m])) by (route)
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Route Returns 404
|
||||
|
||||
**Check**:
|
||||
1. ✅ Route is published in Dashboard
|
||||
2. ✅ Host header matches route configuration exactly
|
||||
3. ✅ Path matches URI pattern
|
||||
4. ✅ Gateway pods are healthy
|
||||
|
||||
```bash
|
||||
# Check gateway logs
|
||||
kubectl logs -n <namespace> -l app.kubernetes.io/name=gateway --tail=100
|
||||
```
|
||||
|
||||
### Service Discovery Not Working
|
||||
|
||||
**Check**:
|
||||
1. ✅ Service registry configured in Dashboard
|
||||
2. ✅ Service registry status is "Connected"
|
||||
3. ✅ RBAC permissions granted
|
||||
4. ✅ Service has named ports
|
||||
|
||||
```bash
|
||||
# Verify service
|
||||
kubectl get svc -n <namespace> <service-name>
|
||||
|
||||
# Check endpoints
|
||||
kubectl get endpoints -n <namespace> <service-name>
|
||||
```
|
||||
|
||||
### Configuration Not Applied
|
||||
|
||||
**Check**:
|
||||
1. ✅ CLI sync succeeded
|
||||
2. ✅ Routes are published
|
||||
3. ✅ Gateway group matches
|
||||
|
||||
```bash
|
||||
# Dump and compare
|
||||
<cli-tool> dump --server <URL> --token <TOKEN> > current.yaml
|
||||
diff config.yaml current.yaml
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Complete configuration reference for API Gateway infrastructure.*
|
||||
283
web/docs/architecture.md
Normal file
283
web/docs/architecture.md
Normal file
@@ -0,0 +1,283 @@
|
||||
# Architecture Overview
|
||||
|
||||
## Infrastructure Architecture
|
||||
|
||||
```
|
||||
Internet
|
||||
↓
|
||||
Load Balancer (External IP)
|
||||
↓
|
||||
Ingress Controller
|
||||
↓
|
||||
TLS Termination (Wildcard Certificate)
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ Gateway Ingress │
|
||||
│ (*.domain.com / domain.com) │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ Gateway Service (ClusterIP) │
|
||||
│ gateway-service (Internal IP) │
|
||||
│ Ports: 80 (→9080), 443 (→9443) │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ Gateway Pods (Multiple Replicas) │
|
||||
│ - gateway-pod-1 │
|
||||
│ - gateway-pod-2 │
|
||||
│ - gateway-pod-3 │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
↓
|
||||
[Route Matching & Service Discovery]
|
||||
↓
|
||||
┌──────────────────┬──────────────────┐
|
||||
│ Backend │ Backend │
|
||||
│ Services │ Services │
|
||||
│ (ClusterIP) │ (ClusterIP) │
|
||||
└──────────────────┴──────────────────┘
|
||||
↓
|
||||
Application Pods
|
||||
```
|
||||
|
||||
## Component Details
|
||||
|
||||
### 1. External Access Layer
|
||||
|
||||
**Load Balancer**
|
||||
- Provides external IP address
|
||||
- Supports LoadBalancer service type
|
||||
- Exposes Ingress Controller to the internet
|
||||
|
||||
**Ingress Controller**
|
||||
- Handles HTTP/HTTPS traffic
|
||||
- TLS termination point
|
||||
- Routes to appropriate backend services
|
||||
|
||||
### 2. Control Plane
|
||||
|
||||
**Deployment Method**: Helm Chart
|
||||
**Namespace**: Dedicated namespace for gateway components
|
||||
|
||||
#### Components
|
||||
|
||||
**Dashboard**
|
||||
- **Function**: Web UI for gateway management
|
||||
- **Service Type**: ClusterIP
|
||||
- **Ports**: Management ports (HTTP/HTTPS)
|
||||
- **Replicas**: Configurable
|
||||
|
||||
**Developer Portal**
|
||||
- **Function**: API documentation and developer access
|
||||
- **Service Type**: ClusterIP
|
||||
- **Ports**: Web service port
|
||||
- **Replicas**: Configurable
|
||||
|
||||
**Data Plane Manager**
|
||||
- **Function**: Data Plane management and configuration distribution
|
||||
- **Service Type**: ClusterIP
|
||||
- **Ports**: Management and proxy ports
|
||||
- **Replicas**: Configurable
|
||||
|
||||
**PostgreSQL Database**
|
||||
- **Function**: Configuration and metadata storage
|
||||
- **Service Type**: ClusterIP
|
||||
- **Port**: 5432/TCP
|
||||
- **Storage**: Persistent volume with configurable size
|
||||
- **Deployment**: StatefulSet for data persistence
|
||||
|
||||
**Prometheus Server**
|
||||
- **Function**: Metrics collection and monitoring
|
||||
- **Service Type**: ClusterIP
|
||||
- **Port**: 9090/TCP
|
||||
- **Storage**: Persistent volume for metrics retention
|
||||
|
||||
### 3. Gateway Data Plane
|
||||
|
||||
**Deployment Method**: Helm Chart
|
||||
**High Availability**: Multiple replicas for fault tolerance
|
||||
|
||||
#### Gateway Deployment
|
||||
|
||||
- **Replicas**: Configurable (recommended: 3+)
|
||||
- **Strategy**: RollingUpdate for zero-downtime deployments
|
||||
- **Max Unavailable**: 25% during updates
|
||||
|
||||
**Gateway Groups**:
|
||||
- Logical grouping of gateway instances
|
||||
- Environment-based separation (dev/staging/prod)
|
||||
- Independent configuration per group
|
||||
|
||||
#### Gateway Service
|
||||
|
||||
- **Type**: ClusterIP for internal routing
|
||||
- **Ports**:
|
||||
- HTTP: 80/TCP → 9080/TCP
|
||||
- HTTPS: 443/TCP → 9443/TCP
|
||||
|
||||
#### Gateway Configuration
|
||||
|
||||
**Configuration Store**:
|
||||
- **Connection**: Secure connection to control plane
|
||||
- **TLS**: Mutual authentication enabled
|
||||
- **Certificates**: Managed via Kubernetes secrets
|
||||
|
||||
**Configuration Volumes**:
|
||||
- Gateway configuration via ConfigMap
|
||||
- TLS certificates for secure communication
|
||||
- Service discovery configuration
|
||||
|
||||
### 4. Ingress Configuration
|
||||
|
||||
**Gateway Ingress Resource**
|
||||
|
||||
```yaml
|
||||
Hosts:
|
||||
- *.domain.com
|
||||
- domain.com
|
||||
|
||||
Backend:
|
||||
Service: gateway-service
|
||||
Port: 80
|
||||
|
||||
TLS:
|
||||
- hosts:
|
||||
- *.domain.com
|
||||
- domain.com
|
||||
secretName: wildcard-tls-secret
|
||||
```
|
||||
|
||||
**Access Points**:
|
||||
- External IP: Provided by Load Balancer
|
||||
- Protocols: HTTP (80), HTTPS (443)
|
||||
- Ingress Class: Configurable
|
||||
|
||||
### 5. Storage Architecture
|
||||
|
||||
**Persistent Volumes**:
|
||||
|
||||
| Component | Recommended Size | Usage |
|
||||
|-----------|-----------------|-------|
|
||||
| PostgreSQL Database | 10Gi+ | Configuration and metadata storage |
|
||||
| Prometheus Metrics | 100Gi+ | Time-series metrics retention |
|
||||
| Configuration Store | 8Gi per node | Distributed configuration (if using etcd) |
|
||||
|
||||
**Storage Classes**:
|
||||
- Distributed storage for database persistence
|
||||
- Local or network storage for metrics
|
||||
- High-performance storage for configuration
|
||||
|
||||
## Network Flow
|
||||
|
||||
### External Request Flow
|
||||
|
||||
1. **Client Request** → Domain URL (HTTP/HTTPS)
|
||||
2. **DNS Resolution** → External Load Balancer IP
|
||||
3. **Ingress Controller** → TLS termination with wildcard certificate
|
||||
4. **Ingress Routing** → Gateway service endpoint
|
||||
5. **Gateway Service** → Load balances across gateway pod replicas
|
||||
6. **Route Matching** → Gateway evaluates routes based on host/path/priority
|
||||
7. **Service Discovery** → Gateway fetches backend endpoints from Kubernetes
|
||||
8. **Backend Request** → Proxies to backend service pods
|
||||
9. **Response** → Returns through the chain to client
|
||||
|
||||
### Control Plane Communication
|
||||
|
||||
1. **Dashboard** → Database (configuration storage)
|
||||
2. **Dashboard** → Data Plane Manager (gateway group management)
|
||||
3. **Data Plane Manager** → Configuration store (configuration distribution)
|
||||
4. **Gateway Pods** → Control plane endpoint (fetch routes/services)
|
||||
5. **Prometheus** → Gateway Pods (scrape metrics)
|
||||
|
||||
## Security Architecture
|
||||
|
||||
### TLS/SSL Configuration
|
||||
|
||||
**External TLS** (Ingress Layer):
|
||||
- **Certificate**: Wildcard certificate (Let's Encrypt or commercial)
|
||||
- **Secret**: Kubernetes TLS secret
|
||||
- **Domains**: Wildcard and root domain support
|
||||
|
||||
**Internal TLS** (Control Plane):
|
||||
- **Dashboard**: Secure HTTPS access
|
||||
- **Developer Portal**: Encrypted portal access
|
||||
- **Data Plane Manager**: Secure management interface
|
||||
|
||||
**Gateway Communication TLS**:
|
||||
- **Mutual TLS**: Enabled for secure communication
|
||||
- **CA Certificate**: Certificate authority validation
|
||||
- **Client Certificates**: Individual component authentication
|
||||
|
||||
### Service Accounts & RBAC
|
||||
|
||||
**Gateway Service Account**: Dedicated service account per namespace
|
||||
|
||||
**Required Permissions**:
|
||||
- `list/watch` endpoints (for service discovery)
|
||||
- Read access to services and pods
|
||||
- Typically bound to appropriate ClusterRole
|
||||
|
||||
## High Availability
|
||||
|
||||
### Gateway Layer
|
||||
- **Multiple replicas** for fault tolerance (3+ recommended)
|
||||
- **RollingUpdate** strategy for zero-downtime deployments
|
||||
- **Load balancing** across all healthy instances
|
||||
|
||||
### Control Plane
|
||||
- **Database**: StatefulSet with persistent storage
|
||||
- **Monitoring**: Persistent metrics storage
|
||||
- **Management Components**: Stateless, scalable replicas
|
||||
|
||||
### Storage
|
||||
- **Database**: Distributed or replicated storage
|
||||
- **Metrics**: Persistent volume with retention policy
|
||||
- **Configuration**: Highly available storage backend
|
||||
|
||||
## Monitoring & Observability
|
||||
|
||||
**Metrics Collection**:
|
||||
- Time-series metrics from all gateway pods
|
||||
- Persistent storage for historical data
|
||||
- Query interface for metrics analysis
|
||||
|
||||
**Gateway Metrics**:
|
||||
- HTTP request rates and throughput
|
||||
- Latency percentiles (p50, p95, p99)
|
||||
- Error rates and status codes
|
||||
- Active connections and concurrency
|
||||
- Upstream service health status
|
||||
|
||||
**Health Checks**:
|
||||
- Gateway readiness and liveness probes
|
||||
- Service health endpoints
|
||||
- Automated recovery mechanisms
|
||||
|
||||
## Scalability Considerations
|
||||
|
||||
**Horizontal Scaling**:
|
||||
- Gateway pods: Scale based on traffic patterns
|
||||
- Backend services: Auto-scaling based on metrics
|
||||
- Control plane: Scale management components as needed
|
||||
|
||||
**Vertical Scaling**:
|
||||
- Database: Expand storage as data grows
|
||||
- Metrics storage: Adjust retention and volume size
|
||||
- Gateway resources: Tune CPU/memory for performance
|
||||
|
||||
## Configuration Management
|
||||
|
||||
**Gateway Configuration**:
|
||||
- **Source**: Dashboard UI or CLI tools
|
||||
- **Storage**: Centralized database
|
||||
- **Distribution**: Control plane to data plane synchronization
|
||||
- **Format**: YAML configuration or Web-based management
|
||||
|
||||
**Kubernetes Resources**:
|
||||
- **Deployment**: Helm charts for standardized installation
|
||||
- **Management**: Kubernetes-native resource management
|
||||
- **Namespaces**: Logical separation of environments
|
||||
|
||||
---
|
||||
|
||||
*This architecture provides enterprise-grade API Gateway capabilities with high availability, scalability, and comprehensive monitoring.*
|
||||
477
web/docs/cicd-pipeline.md
Normal file
477
web/docs/cicd-pipeline.md
Normal file
@@ -0,0 +1,477 @@
|
||||
# CI/CD Pipeline
|
||||
|
||||
Automated build and deployment pipeline using Git-based CI/CD systems.
|
||||
|
||||
## Overview
|
||||
|
||||
The CI/CD pipeline automatically builds Docker images and pushes them to the container registry whenever code is pushed to any branch.
|
||||
|
||||
**Repository**: Git repository with application code
|
||||
|
||||
**Registry**: Container registry for Docker images
|
||||
|
||||
## Pipeline Architecture
|
||||
|
||||
```
|
||||
Git Push (any branch)
|
||||
↓
|
||||
CI/CD System Trigger
|
||||
↓
|
||||
┌─────────────────────────────────────┐
|
||||
│ Job: build-web (parallel) │
|
||||
│ Job: build-api (parallel) │
|
||||
└─────────────────────────────────────┘
|
||||
↓ ↓
|
||||
Build Web Image Build API Image
|
||||
↓ ↓
|
||||
Tag with branch Tag with branch
|
||||
↓ ↓
|
||||
Push to Registry Push to Registry
|
||||
↓ ↓
|
||||
<registry>/web:<branch>
|
||||
<registry>/api:<branch>
|
||||
```
|
||||
|
||||
## Workflow Configuration
|
||||
|
||||
**Location**: CI/CD workflow files (`.github/workflows/`, `.gitlab-ci.yml`, etc.)
|
||||
|
||||
```yaml
|
||||
name: Build and Push Docker Images
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-web:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: <registry-url>
|
||||
username: ${{ secrets.REGISTRY_USER }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Extract metadata for web image
|
||||
id: meta-web
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: <registry>/web
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
|
||||
- name: Build and push web image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./web
|
||||
file: ./web/Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta-web.outputs.tags }}
|
||||
labels: ${{ steps.meta-web.outputs.labels }}
|
||||
cache-from: type=registry,ref=<registry>/web:buildcache
|
||||
cache-to: type=registry,ref=<registry>/web:buildcache,mode=max
|
||||
|
||||
build-api:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Similar steps for API application
|
||||
...
|
||||
```
|
||||
|
||||
## Trigger Events
|
||||
|
||||
### Automatic Triggers
|
||||
|
||||
**Push to any branch**:
|
||||
```bash
|
||||
git push origin <branch-name>
|
||||
```
|
||||
|
||||
Images tagged with branch name:
|
||||
- `<registry>/web:<branch-name>`
|
||||
- `<registry>/api:<branch-name>`
|
||||
|
||||
### Manual Trigger
|
||||
|
||||
**Via CI/CD Interface**:
|
||||
1. Go to repository → **CI/CD** or **Actions**
|
||||
2. Select workflow: **Build and Push Docker Images**
|
||||
3. Click: **Run workflow**
|
||||
4. Select branch
|
||||
5. Click: **Run**
|
||||
|
||||
**Via Git**:
|
||||
```bash
|
||||
# Trigger workflow with empty commit
|
||||
git commit --allow-empty -m "Trigger CI/CD pipeline"
|
||||
git push
|
||||
```
|
||||
|
||||
## Setup Instructions
|
||||
|
||||
### 1. Create Registry Token
|
||||
|
||||
**Generate Token**:
|
||||
1. Go to: **User Settings** or **Access Tokens**
|
||||
2. Click: **Generate New Token**
|
||||
3. Name: `container-registry`
|
||||
4. Select appropriate permissions:
|
||||
- ✅ Write/push access (required)
|
||||
- ✅ Read/pull access (required)
|
||||
5. Click: **Generate Token**
|
||||
6. **Copy token** (shown once only)
|
||||
|
||||
### 2. Add Repository Secret
|
||||
|
||||
**In Repository Settings**:
|
||||
1. Go to: **Repository → Settings → Secrets/Variables**
|
||||
2. Click: **Add Secret**
|
||||
3. Add required secrets:
|
||||
- `REGISTRY_TOKEN`: Token from step 1
|
||||
- `REGISTRY_USER`: Username
|
||||
4. Click: **Save**
|
||||
|
||||
### 3. Verify Workflow
|
||||
|
||||
**Check workflow file exists**:
|
||||
```bash
|
||||
ls -la .github/workflows/ # or appropriate CI/CD directory
|
||||
```
|
||||
|
||||
**Push to trigger**:
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Test CI/CD pipeline"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
**Monitor execution**:
|
||||
1. Go to repository → **CI/CD** or **Actions**
|
||||
2. Click on the running workflow
|
||||
3. View logs for each job
|
||||
|
||||
## Image Naming Convention
|
||||
|
||||
**Format**: `<registry>/<namespace>/<app>:<tag>`
|
||||
|
||||
**Examples**:
|
||||
- `<registry>/web:main`
|
||||
- `<registry>/web:develop`
|
||||
- `<registry>/web:feature-xyz`
|
||||
- `<registry>/api:main`
|
||||
|
||||
## Using Built Images in Kubernetes
|
||||
|
||||
### 1. Pull Images from Container Registry
|
||||
|
||||
**Create registry secret**:
|
||||
```bash
|
||||
kubectl create secret docker-registry registry-secret \
|
||||
--docker-server=<registry-url> \
|
||||
--docker-username=<USERNAME> \
|
||||
--docker-password=<TOKEN> \
|
||||
-n <namespace>
|
||||
```
|
||||
|
||||
### 2. Update Deployment
|
||||
|
||||
**deployment.yaml**:
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: web
|
||||
namespace: <namespace>
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: registry-secret
|
||||
containers:
|
||||
- name: web
|
||||
image: <registry>/web:main
|
||||
imagePullPolicy: Always
|
||||
```
|
||||
|
||||
### 3. Deploy to Kubernetes
|
||||
|
||||
```bash
|
||||
kubectl apply -f deployment.yaml
|
||||
```
|
||||
|
||||
### 4. Rollout New Version
|
||||
|
||||
**After pipeline builds new image**:
|
||||
|
||||
```bash
|
||||
# Force rollout restart (pulls latest image with same tag)
|
||||
kubectl rollout restart deployment/web -n <namespace>
|
||||
kubectl rollout restart deployment/api -n <namespace>
|
||||
|
||||
# Check rollout status
|
||||
kubectl rollout status deployment/web -n <namespace>
|
||||
```
|
||||
|
||||
**Or update image explicitly**:
|
||||
```bash
|
||||
kubectl set image deployment/web \
|
||||
web=<registry>/web:main \
|
||||
-n <namespace>
|
||||
|
||||
kubectl set image deployment/api \
|
||||
api=<registry>/api:main \
|
||||
-n <namespace>
|
||||
```
|
||||
|
||||
## Docker Layer Caching
|
||||
|
||||
The pipeline uses Docker layer caching to speed up builds:
|
||||
|
||||
**Cache Configuration**:
|
||||
```yaml
|
||||
cache-from: type=registry,ref=<registry>/web:buildcache
|
||||
cache-to: type=registry,ref=<registry>/web:buildcache,mode=max
|
||||
```
|
||||
|
||||
**Benefits**:
|
||||
- Faster builds (reuses unchanged layers)
|
||||
- Reduced build time from ~3min to ~30sec
|
||||
- Lower resource usage
|
||||
|
||||
**Cache Location**: Stored in registry as special tag `:buildcache`
|
||||
|
||||
## Parallel Builds
|
||||
|
||||
Both applications build in parallel:
|
||||
|
||||
```
|
||||
Start
|
||||
├─→ build-web job (3-5 min)
|
||||
└─→ build-api job (3-5 min)
|
||||
↓
|
||||
Complete (~5 min total)
|
||||
```
|
||||
|
||||
Without parallelization: ~10 minutes
|
||||
With parallelization: ~5 minutes
|
||||
|
||||
## Viewing Build Logs
|
||||
|
||||
### Via CI/CD Interface
|
||||
|
||||
1. Repository → **CI/CD** or **Actions**
|
||||
2. Click on workflow run
|
||||
3. Select job (`build-web` or `build-api`)
|
||||
4. View step-by-step logs
|
||||
|
||||
### Via CLI (if available)
|
||||
|
||||
```bash
|
||||
# List workflow runs
|
||||
<cli-tool> list runs
|
||||
|
||||
# View specific run logs
|
||||
<cli-tool> view run <run-id>
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Build Fails: Authentication Error
|
||||
|
||||
**Error**: `unauthorized: authentication required`
|
||||
|
||||
**Solution**:
|
||||
1. Verify registry secrets exist in repository settings
|
||||
2. Check token has appropriate permissions
|
||||
3. Regenerate token if expired
|
||||
|
||||
```bash
|
||||
# Test token manually
|
||||
docker login <registry-url> -u <USERNAME> -p <TOKEN>
|
||||
```
|
||||
|
||||
### Build Fails: Dockerfile Not Found
|
||||
|
||||
**Error**: `unable to prepare context: unable to evaluate symlinks in Dockerfile path`
|
||||
|
||||
**Solution**:
|
||||
1. Check Dockerfile exists in correct location:
|
||||
- `web/Dockerfile`
|
||||
- `api/Dockerfile`
|
||||
2. Verify workflow context path matches:
|
||||
```yaml
|
||||
context: ./web
|
||||
file: ./web/Dockerfile
|
||||
```
|
||||
|
||||
### Image Pull Fails in Kubernetes
|
||||
|
||||
**Error**: `ImagePullBackOff`
|
||||
|
||||
**Solution**:
|
||||
1. Verify registry secret exists:
|
||||
```bash
|
||||
kubectl get secret registry-secret -n <namespace>
|
||||
```
|
||||
|
||||
2. Check secret is referenced in deployment:
|
||||
```yaml
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: registry-secret
|
||||
```
|
||||
|
||||
3. Test manual pull:
|
||||
```bash
|
||||
docker pull <registry>/web:main
|
||||
```
|
||||
|
||||
### Workflow Doesn't Trigger
|
||||
|
||||
**Check**:
|
||||
1. ✅ Workflow file in appropriate CI/CD directory
|
||||
2. ✅ File is named correctly (`.yml` or `.yaml`)
|
||||
3. ✅ File is committed and pushed to repository
|
||||
4. ✅ CI/CD is enabled in repository settings
|
||||
|
||||
**Force trigger**:
|
||||
```bash
|
||||
git commit --allow-empty -m "Trigger workflow"
|
||||
git push
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Version Tagging
|
||||
|
||||
**For production deployments**:
|
||||
```bash
|
||||
# Tag release
|
||||
git tag -a v1.0.0 -m "Release v1.0.0"
|
||||
git push origin v1.0.0
|
||||
```
|
||||
|
||||
**Update workflow for semantic versioning**:
|
||||
```yaml
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
```
|
||||
|
||||
### Branch Strategy
|
||||
|
||||
**Recommended**:
|
||||
- `main` → production images
|
||||
- `develop` → staging images
|
||||
- `feature/*` → development images
|
||||
|
||||
**Kubernetes deployments**:
|
||||
```yaml
|
||||
# Production
|
||||
image: <registry>/web:main
|
||||
|
||||
# Staging
|
||||
image: <registry>/web:develop
|
||||
|
||||
# Development
|
||||
image: <registry>/web:feature-xyz
|
||||
```
|
||||
|
||||
### Security
|
||||
|
||||
**Protect main branch**:
|
||||
1. Repository Settings → **Branches** or **Protected Branches**
|
||||
2. Add branch protection for `main`
|
||||
3. Require pull/merge request reviews
|
||||
4. Enable status checks
|
||||
|
||||
**Rotate tokens regularly**:
|
||||
- Generate new registry token every 90 days
|
||||
- Update secrets in repository settings
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Multi-Stage Builds
|
||||
|
||||
Optimize Dockerfile for smaller images:
|
||||
|
||||
```dockerfile
|
||||
# Build stage
|
||||
FROM python:3.11-slim AS builder
|
||||
WORKDIR /app
|
||||
COPY requirements.txt .
|
||||
RUN pip install --user --no-cache-dir -r requirements.txt
|
||||
|
||||
# Runtime stage
|
||||
FROM python:3.11-slim
|
||||
WORKDIR /app
|
||||
COPY --from=builder /root/.local /root/.local
|
||||
COPY . .
|
||||
ENV PATH=/root/.local/bin:$PATH
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||
```
|
||||
|
||||
### Build Arguments
|
||||
|
||||
Pass build-time variables:
|
||||
|
||||
```yaml
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
build-args: |
|
||||
VERSION=${{ github.sha }}
|
||||
BUILD_DATE=${{ github.event.head_commit.timestamp }}
|
||||
```
|
||||
|
||||
### Matrix Builds
|
||||
|
||||
Build for multiple platforms:
|
||||
|
||||
```yaml
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [linux/amd64, linux/arm64]
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
platforms: ${{ matrix.platform }}
|
||||
```
|
||||
|
||||
## Monitoring Pipeline
|
||||
|
||||
### Metrics to Track
|
||||
|
||||
- ✅ Build success rate
|
||||
- ✅ Average build time
|
||||
- ✅ Cache hit rate
|
||||
- ✅ Image size trends
|
||||
|
||||
### Notifications
|
||||
|
||||
**Add Discord/Slack notifications** (example):
|
||||
|
||||
```yaml
|
||||
- name: Notify on failure
|
||||
if: failure()
|
||||
run: |
|
||||
curl -X POST ${{ secrets.WEBHOOK_URL }} \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"content":"Build failed for ${{ github.ref }}"}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Automated CI/CD pipeline for building and deploying containerized applications.*
|
||||
432
web/docs/getting-started.md
Normal file
432
web/docs/getting-started.md
Normal file
@@ -0,0 +1,432 @@
|
||||
# Getting Started
|
||||
|
||||
Quick start guide for working with the API Gateway infrastructure and applications.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Access to Kubernetes cluster with `kubectl` configured
|
||||
- Access to Gateway Dashboard
|
||||
- CLI tools installed (optional, for command-line configuration)
|
||||
- Git repository access for application code
|
||||
|
||||
## Quick Start - Local Development
|
||||
|
||||
### 1. Clone Repository
|
||||
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd <project-directory>
|
||||
```
|
||||
|
||||
### 2. Run Applications Locally
|
||||
|
||||
**Web Application**:
|
||||
```bash
|
||||
cd web
|
||||
pip install -r requirements.txt
|
||||
python main.py
|
||||
# Access at http://localhost:8000
|
||||
```
|
||||
|
||||
**API Application**:
|
||||
```bash
|
||||
cd api
|
||||
pip install -r requirements.txt
|
||||
python main.py
|
||||
# Swagger UI at http://localhost:8000/docs
|
||||
```
|
||||
|
||||
### 3. Build Docker Images
|
||||
|
||||
```bash
|
||||
# Web application
|
||||
docker build -t web-app ./web
|
||||
|
||||
# API application
|
||||
docker build -t api-app ./api
|
||||
```
|
||||
|
||||
## Deploying to Kubernetes
|
||||
|
||||
### 1. Prepare Namespace
|
||||
|
||||
```bash
|
||||
# Create namespace if it doesn't exist
|
||||
kubectl create namespace <namespace>
|
||||
|
||||
# Verify gateway components are running
|
||||
kubectl get pods -n <namespace>
|
||||
```
|
||||
|
||||
**Expected Components**:
|
||||
- ✅ Dashboard pod running
|
||||
- ✅ Developer Portal pod running
|
||||
- ✅ Data Plane Manager pod running
|
||||
- ✅ Gateway pods running (multiple replicas)
|
||||
- ✅ Database pod running
|
||||
|
||||
### 2. Create Kubernetes Manifests
|
||||
|
||||
**deployment.yaml**:
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: web
|
||||
namespace: <namespace>
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: web
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: web
|
||||
spec:
|
||||
containers:
|
||||
- name: web
|
||||
image: <registry>/web:latest
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
name: http
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8000
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8000
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: web-service
|
||||
namespace: <namespace>
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8000
|
||||
name: http
|
||||
selector:
|
||||
app: web
|
||||
```
|
||||
|
||||
### 3. Deploy Applications
|
||||
|
||||
```bash
|
||||
kubectl apply -f deployment.yaml
|
||||
|
||||
# Check deployment status
|
||||
kubectl get deployments -n <namespace>
|
||||
kubectl get pods -n <namespace> -l app=web
|
||||
```
|
||||
|
||||
### 4. Configure Container Registry Access (if needed)
|
||||
|
||||
```bash
|
||||
# Create registry secret
|
||||
kubectl create secret docker-registry registry-secret \
|
||||
--docker-server=<registry-server> \
|
||||
--docker-username=<USERNAME> \
|
||||
--docker-password=<TOKEN> \
|
||||
-n <namespace>
|
||||
|
||||
# Add to deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: registry-secret
|
||||
```
|
||||
|
||||
## Configuring Gateway Routes
|
||||
|
||||
### Method 1: Using CLI Tools
|
||||
|
||||
**1. Create configuration file** (`config.yaml`):
|
||||
|
||||
```yaml
|
||||
services:
|
||||
- name: web-service
|
||||
upstream:
|
||||
name: web-upstream
|
||||
scheme: http
|
||||
type: roundrobin
|
||||
discovery_type: kubernetes
|
||||
service_name: <namespace>/web-service:http
|
||||
routes:
|
||||
- name: web-route
|
||||
uris:
|
||||
- /*
|
||||
hosts:
|
||||
- app.domain.com
|
||||
plugins:
|
||||
redirect:
|
||||
http_to_https: true
|
||||
```
|
||||
|
||||
**2. Sync configuration**:
|
||||
|
||||
```bash
|
||||
<cli-tool> sync -f config.yaml \
|
||||
--server <dashboard-url> \
|
||||
--token <api-token> \
|
||||
--gateway-group default
|
||||
```
|
||||
|
||||
**3. Verify sync**:
|
||||
```bash
|
||||
# Expected output:
|
||||
[CLI] › ✔ success Create service: "web-service"
|
||||
[CLI] › ✔ success Create route: "web-route"
|
||||
```
|
||||
|
||||
### Method 2: Using Dashboard Web UI
|
||||
|
||||
**1. Access Dashboard**:
|
||||
- URL: Gateway Dashboard URL
|
||||
- Login with credentials
|
||||
|
||||
**2. Configure Service Discovery** (one-time setup):
|
||||
- Navigate: **Settings → Service Registry**
|
||||
- Click: **Add Service Registry**
|
||||
- Select: **Kubernetes**
|
||||
- Configure:
|
||||
```
|
||||
Name: kubernetes-cluster
|
||||
API Server: https://kubernetes.default.svc.cluster.local:443
|
||||
Token Path: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||
Namespace Filter: <namespace>
|
||||
```
|
||||
- Save and verify status shows "Connected"
|
||||
|
||||
**3. Create Service**:
|
||||
- Navigate: **Services**
|
||||
- Click: **Create Service**
|
||||
- Name: `web-service`
|
||||
- Upstream Type: **Service Discovery**
|
||||
- Discovery Type: **Kubernetes**
|
||||
- Service Name: `<namespace>/web-service:http`
|
||||
|
||||
**4. Create Route**:
|
||||
- In the service page, go to **Routes** tab
|
||||
- Click: **Create Route**
|
||||
- Name: `web-route`
|
||||
- Host: `app.domain.com`
|
||||
- Path: `/*`
|
||||
- Methods: GET, POST, PUT, DELETE
|
||||
- Add Plugin: **redirect** → `http_to_https: true`
|
||||
|
||||
**5. Publish Route**:
|
||||
- Find route in the Routes tab
|
||||
- Click: **Publish**
|
||||
- Select gateway group: **default**
|
||||
- Confirm
|
||||
|
||||
## Creating Ingress for External Access
|
||||
|
||||
**ingress.yaml**:
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: app-ingress
|
||||
namespace: <namespace>
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
tls:
|
||||
- hosts:
|
||||
- app.domain.com
|
||||
secretName: app-tls
|
||||
rules:
|
||||
- host: app.domain.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: gateway-service
|
||||
port:
|
||||
number: 80
|
||||
```
|
||||
|
||||
**Important**: Backend points to Gateway service, not application service directly.
|
||||
|
||||
```bash
|
||||
kubectl apply -f ingress.yaml
|
||||
```
|
||||
|
||||
## Verifying Service Discovery RBAC
|
||||
|
||||
Gateway needs permissions to discover Kubernetes services:
|
||||
|
||||
```bash
|
||||
# Check current permissions
|
||||
kubectl auth can-i list endpoints --as=system:serviceaccount:<namespace>:default -n <namespace>
|
||||
|
||||
# If needed, create ClusterRoleBinding
|
||||
kubectl create clusterrolebinding gateway-discovery \
|
||||
--clusterrole=view \
|
||||
--serviceaccount=<namespace>:default
|
||||
```
|
||||
|
||||
## Testing the Deployment
|
||||
|
||||
### 1. Test DNS Resolution
|
||||
|
||||
```bash
|
||||
# Add to /etc/hosts or configure DNS
|
||||
echo "<external-ip> app.domain.com" | sudo tee -a /etc/hosts
|
||||
```
|
||||
|
||||
### 2. Test HTTP to HTTPS Redirect
|
||||
|
||||
```bash
|
||||
curl -I http://app.domain.com
|
||||
|
||||
# Expected:
|
||||
# HTTP/1.1 301 Moved Permanently
|
||||
# Location: https://app.domain.com
|
||||
```
|
||||
|
||||
### 3. Test Application Access
|
||||
|
||||
```bash
|
||||
# Web application
|
||||
curl https://app.domain.com
|
||||
|
||||
# API health check
|
||||
curl https://app.domain.com/api/health
|
||||
```
|
||||
|
||||
### 4. Verify Service Discovery
|
||||
|
||||
```bash
|
||||
# Scale deployment
|
||||
kubectl scale deployment web -n <namespace> --replicas=5
|
||||
|
||||
# Check endpoints
|
||||
kubectl get endpoints -n <namespace> web-service
|
||||
|
||||
# Gateway automatically discovers all 5 pod endpoints
|
||||
# No configuration change needed
|
||||
```
|
||||
|
||||
## Accessing Gateway Dashboard
|
||||
|
||||
### Local Access (port-forward)
|
||||
|
||||
```bash
|
||||
kubectl port-forward -n <namespace> svc/dashboard-service 7080:7080
|
||||
|
||||
# Access at http://localhost:7080
|
||||
```
|
||||
|
||||
### Public Access
|
||||
|
||||
Direct access via configured URLs:
|
||||
- **Dashboard**: Management interface URL
|
||||
- **Developer Portal**: Developer portal URL
|
||||
|
||||
## CI/CD Pipeline Setup
|
||||
|
||||
### 1. Configure Repository Token
|
||||
|
||||
In repository settings:
|
||||
1. Go to **Settings → Secrets**
|
||||
2. Add authentication token
|
||||
3. Configure with appropriate permissions
|
||||
4. Enable container registry access
|
||||
|
||||
### 2. Push to Trigger Build
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Deploy applications"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
The pipeline will:
|
||||
- Build Docker images
|
||||
- Push to container registry
|
||||
- Tag with branch/version
|
||||
|
||||
### 3. Update Kubernetes Deployment
|
||||
|
||||
```bash
|
||||
# Manually trigger rollout
|
||||
kubectl rollout restart deployment/web -n <namespace>
|
||||
kubectl rollout restart deployment/api -n <namespace>
|
||||
|
||||
# Or update image in deployment
|
||||
kubectl set image deployment/web web=<registry>/web:latest -n <namespace>
|
||||
```
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
# Application logs
|
||||
kubectl logs -n <namespace> -l app=web --tail=50 -f
|
||||
|
||||
# Gateway logs
|
||||
kubectl logs -n <namespace> -l app.kubernetes.io/name=gateway --tail=50 -f
|
||||
|
||||
# Dashboard logs
|
||||
kubectl logs -n <namespace> -l app=dashboard --tail=50 -f
|
||||
```
|
||||
|
||||
### Check Route Configuration
|
||||
|
||||
**Via CLI**:
|
||||
```bash
|
||||
<cli-tool> dump \
|
||||
--server <dashboard-url> \
|
||||
--token <TOKEN>
|
||||
```
|
||||
|
||||
**Via Dashboard**:
|
||||
- Navigate: **Services → <service-name> → Routes**
|
||||
- View route details and publication status
|
||||
|
||||
### Update Route Configuration
|
||||
|
||||
```bash
|
||||
# Edit config file
|
||||
vim config.yaml
|
||||
|
||||
# Sync changes
|
||||
<cli-tool> sync -f config.yaml \
|
||||
--server <dashboard-url> \
|
||||
--token <TOKEN> \
|
||||
--gateway-group default
|
||||
```
|
||||
|
||||
### Monitor Gateway Metrics
|
||||
|
||||
**Prometheus**:
|
||||
```bash
|
||||
kubectl port-forward -n <namespace> svc/prometheus-server 9090:9090
|
||||
|
||||
# Access at http://localhost:9090
|
||||
```
|
||||
|
||||
**Dashboard Metrics**:
|
||||
- Navigate: **Monitoring** in Gateway Dashboard
|
||||
- View request rates, latency, error rates
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Configure advanced routing](api7-configuration.md)
|
||||
- [Set up monitoring and alerts](monitoring.md)
|
||||
- [Review troubleshooting guide](troubleshooting.md)
|
||||
- [Learn about the architecture](architecture.md)
|
||||
|
||||
---
|
||||
|
||||
*You're now ready to deploy and manage applications with the API Gateway infrastructure!*
|
||||
82
web/docs/index.md
Normal file
82
web/docs/index.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# API Gateway Infrastructure - Documentation
|
||||
|
||||
Welcome to the API Gateway infrastructure documentation. This guide covers the complete setup and configuration of the API Gateway system.
|
||||
|
||||
## Overview
|
||||
|
||||
This documentation provides comprehensive information about:
|
||||
|
||||
- **Architecture**: Understanding the API Gateway setup
|
||||
- **Applications**: Backend applications integration (Web & API)
|
||||
- **Configuration**: Gateway routes, services, and policies
|
||||
- **Deployment**: CI/CD pipeline automation
|
||||
- **Operations**: Monitoring, troubleshooting, and maintenance
|
||||
|
||||
## Quick Links
|
||||
|
||||
- [Architecture Overview](architecture.md)
|
||||
- [Getting Started](getting-started.md)
|
||||
- [Gateway Configuration](api7-configuration.md)
|
||||
- [Kubernetes Resources](kubernetes-resources.md)
|
||||
- [CI/CD Pipeline](cicd-pipeline.md)
|
||||
- [Troubleshooting Guide](troubleshooting.md)
|
||||
|
||||
## Infrastructure Components
|
||||
|
||||
### Gateway Control Plane
|
||||
|
||||
**Control Plane Components**
|
||||
- Dashboard: Web-based management interface
|
||||
- Developer Portal: API documentation and testing portal
|
||||
- DP Manager: Data plane management service
|
||||
- PostgreSQL Database: Configuration storage
|
||||
- Prometheus Monitoring: Metrics collection
|
||||
|
||||
**Gateway Data Plane**
|
||||
- Multiple replicas for high availability
|
||||
- ClusterIP service for internal communication
|
||||
- Gateway Groups for logical organization
|
||||
- External access via Ingress Controller
|
||||
|
||||
### Applications
|
||||
|
||||
- **Web Application**: Frontend application interface
|
||||
- **API Application**: Backend REST API services
|
||||
|
||||
### Domain Configuration
|
||||
|
||||
- **Wildcard Domain**: Support for subdomains
|
||||
- **Root Domain**: Primary domain access
|
||||
- **TLS**: Automated certificate management
|
||||
|
||||
## Technology Stack
|
||||
|
||||
- **API Gateway**: Enterprise API Gateway Solution
|
||||
- **Control Plane**: Centralized management interface
|
||||
- **Data Plane**: High-performance request processing
|
||||
- **Container Orchestration**: Kubernetes
|
||||
- **Ingress Controller**: External traffic management
|
||||
- **Certificate Management**: Automated TLS certificates
|
||||
- **CI/CD**: Automated deployment pipeline
|
||||
- **Applications**: Microservices architecture
|
||||
- **Documentation**: Technical documentation system
|
||||
|
||||
## Repository Structure
|
||||
|
||||
**Components**:
|
||||
- Web application container images
|
||||
- API service container images
|
||||
- Configuration management
|
||||
- Infrastructure as Code
|
||||
|
||||
## Getting Help
|
||||
|
||||
For issues or questions:
|
||||
|
||||
1. Check the [Troubleshooting Guide](troubleshooting.md)
|
||||
2. Review the gateway documentation
|
||||
3. Check application logs in the container platform
|
||||
|
||||
---
|
||||
|
||||
*Documentation Version: 1.0*
|
||||
446
web/docs/kubernetes-resources.md
Normal file
446
web/docs/kubernetes-resources.md
Normal file
@@ -0,0 +1,446 @@
|
||||
# Kubernetes Resources
|
||||
|
||||
Complete reference of all Kubernetes resources for the API Gateway deployment.
|
||||
|
||||
## Namespace Overview
|
||||
|
||||
**Namespace**: Dedicated namespace for gateway components
|
||||
**Environment Separation**: Development, Staging, Production
|
||||
**Resource Organization**: Logical grouping by function
|
||||
|
||||
## Helm Releases
|
||||
|
||||
### Control Plane Release
|
||||
|
||||
**Release Components**:
|
||||
- **Chart**: Control plane helm chart
|
||||
- **Status**: Deployed
|
||||
- **Management**: Dashboard, Portal, Data Plane Manager
|
||||
|
||||
**Key Configuration**:
|
||||
```yaml
|
||||
dashboard_configuration:
|
||||
database:
|
||||
dsn: postgres://username:***@postgresql-service:5432/dbname
|
||||
|
||||
postgresql:
|
||||
auth:
|
||||
password: ***
|
||||
primary:
|
||||
persistence:
|
||||
size: 10Gi
|
||||
readReplicas:
|
||||
persistence:
|
||||
size: 10Gi
|
||||
```
|
||||
|
||||
### Data Plane Release
|
||||
|
||||
**Release Components**:
|
||||
- **Chart**: Gateway data plane helm chart
|
||||
- **Status**: Deployed
|
||||
- **Function**: Request processing and routing
|
||||
|
||||
**Key Configuration**:
|
||||
```yaml
|
||||
gateway:
|
||||
extraEnvVars:
|
||||
- name: GATEWAY_GROUP_ID
|
||||
value: default
|
||||
replicaCount: 3
|
||||
|
||||
configuration:
|
||||
auth:
|
||||
tls:
|
||||
enabled: true
|
||||
existingSecret: gateway-tls-secret
|
||||
verify: true
|
||||
endpoint:
|
||||
- https://control-plane-endpoint:port
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
tls:
|
||||
existingCASecret: gateway-tls-secret
|
||||
```
|
||||
|
||||
## Deployments
|
||||
|
||||
### Dashboard
|
||||
|
||||
**Specification**:
|
||||
```yaml
|
||||
Replicas: 1 (configurable)
|
||||
Selector: app=dashboard
|
||||
Ports: Management ports (HTTP/HTTPS)
|
||||
```
|
||||
|
||||
### Developer Portal
|
||||
|
||||
**Specification**:
|
||||
```yaml
|
||||
Replicas: 1 (configurable)
|
||||
Selector: app=developer-portal
|
||||
Ports: Web service port
|
||||
```
|
||||
|
||||
### Data Plane Manager
|
||||
|
||||
**Specification**:
|
||||
```yaml
|
||||
Replicas: 1 (configurable)
|
||||
Selector: app=dp-manager
|
||||
Ports: Management and proxy ports
|
||||
```
|
||||
|
||||
### Gateway Data Plane
|
||||
|
||||
**Specification**:
|
||||
```yaml
|
||||
Replicas: 3+ (highly available)
|
||||
Strategy: RollingUpdate (25% max unavailable)
|
||||
Selector: app.kubernetes.io/name=gateway
|
||||
Ports: 9080 (HTTP), 9443 (HTTPS)
|
||||
|
||||
Volumes:
|
||||
- gateway-config (ConfigMap)
|
||||
- tls-certificates (Secret)
|
||||
- client-certificates (Secret)
|
||||
|
||||
Environment:
|
||||
- GATEWAY_GROUP_ID: default
|
||||
|
||||
Readiness Probe:
|
||||
tcp-socket: 9080
|
||||
initialDelay: 10s
|
||||
period: 10s
|
||||
```
|
||||
|
||||
### Monitoring Server
|
||||
|
||||
**Specification**:
|
||||
```yaml
|
||||
Replicas: 1
|
||||
Image: prometheus:latest
|
||||
Ports: 9090
|
||||
Volume: Persistent storage for metrics
|
||||
```
|
||||
|
||||
### Backend Applications
|
||||
|
||||
**Generic Application Template**:
|
||||
```yaml
|
||||
Replicas: Based on load requirements
|
||||
Ports: Application-specific
|
||||
Service: ClusterIP for internal access
|
||||
```
|
||||
|
||||
## StatefulSets
|
||||
|
||||
### PostgreSQL Database
|
||||
|
||||
**Specification**:
|
||||
```yaml
|
||||
Replicas: 1 (can be scaled for HA)
|
||||
Image: postgres:latest
|
||||
Ports: 5432
|
||||
Storage: Configurable persistent volume
|
||||
|
||||
Environment:
|
||||
- POSTGRES_USER: gateway_user
|
||||
- POSTGRES_PASSWORD: *** (from secret)
|
||||
- POSTGRES_DB: gateway_db
|
||||
```
|
||||
|
||||
**Persistent Storage**: Data persistence across pod restarts
|
||||
|
||||
## Services
|
||||
|
||||
### Control Plane Services
|
||||
|
||||
#### Dashboard Service
|
||||
```yaml
|
||||
Type: ClusterIP
|
||||
Ports:
|
||||
- HTTP Management Port
|
||||
- HTTPS Management Port
|
||||
Selector: app=dashboard
|
||||
```
|
||||
|
||||
#### Developer Portal Service
|
||||
```yaml
|
||||
Type: ClusterIP
|
||||
Ports:
|
||||
- Web Service Port
|
||||
Selector: app=developer-portal
|
||||
```
|
||||
|
||||
#### Data Plane Manager Service
|
||||
```yaml
|
||||
Type: ClusterIP
|
||||
Ports:
|
||||
- Management API Port
|
||||
- Configuration Proxy Port
|
||||
Selector: app=dp-manager
|
||||
```
|
||||
|
||||
#### PostgreSQL Service
|
||||
```yaml
|
||||
Type: ClusterIP
|
||||
Ports:
|
||||
- 5432/TCP
|
||||
Selector: app=postgresql
|
||||
```
|
||||
|
||||
#### PostgreSQL Headless Service
|
||||
```yaml
|
||||
Type: ClusterIP (None)
|
||||
Ports:
|
||||
- 5432/TCP
|
||||
Purpose: StatefulSet DNS resolution
|
||||
```
|
||||
|
||||
#### Monitoring Service
|
||||
```yaml
|
||||
Type: ClusterIP
|
||||
Ports:
|
||||
- 9090/TCP
|
||||
Selector: app=prometheus
|
||||
```
|
||||
|
||||
### Gateway Service
|
||||
|
||||
```yaml
|
||||
Type: ClusterIP
|
||||
Ports:
|
||||
- name: http-gateway
|
||||
port: 80
|
||||
targetPort: 9080
|
||||
- name: https-gateway
|
||||
port: 443
|
||||
targetPort: 9443
|
||||
Selector:
|
||||
app.kubernetes.io/name: gateway
|
||||
```
|
||||
|
||||
### Backend Application Services
|
||||
|
||||
```yaml
|
||||
Type: ClusterIP
|
||||
Ports: Application-specific
|
||||
Selector: app=<application-name>
|
||||
```
|
||||
|
||||
## Ingress Resources
|
||||
|
||||
### Dashboard Ingress
|
||||
```yaml
|
||||
Class: nginx
|
||||
Hosts:
|
||||
- dashboard.domain.com
|
||||
|
||||
TLS:
|
||||
- hosts: [dashboard.domain.com]
|
||||
secretName: dashboard-tls-secret
|
||||
|
||||
Backend:
|
||||
Service: dashboard-service
|
||||
Port: Management Port
|
||||
|
||||
Annotations:
|
||||
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: 10m
|
||||
```
|
||||
|
||||
### Developer Portal Ingress
|
||||
```yaml
|
||||
Class: nginx
|
||||
Hosts:
|
||||
- portal.domain.com
|
||||
|
||||
TLS:
|
||||
- hosts: [portal.domain.com]
|
||||
secretName: portal-tls-secret
|
||||
|
||||
Backend:
|
||||
Service: developer-portal-service
|
||||
Port: Web Port
|
||||
```
|
||||
|
||||
### Data Plane Manager Ingress
|
||||
```yaml
|
||||
Class: nginx
|
||||
Hosts:
|
||||
- dp-manager.domain.com
|
||||
|
||||
TLS:
|
||||
- hosts: [dp-manager.domain.com]
|
||||
secretName: dp-manager-tls-secret
|
||||
|
||||
Backend:
|
||||
Service: dp-manager-service
|
||||
Port: Management Port
|
||||
```
|
||||
|
||||
### Gateway Ingress
|
||||
```yaml
|
||||
Class: nginx
|
||||
|
||||
Hosts:
|
||||
- *.domain.com
|
||||
- domain.com
|
||||
|
||||
TLS:
|
||||
- hosts: [*.domain.com, domain.com]
|
||||
secretName: wildcard-tls-secret
|
||||
|
||||
Rules:
|
||||
- host: "*.domain.com"
|
||||
backend:
|
||||
service: gateway-service
|
||||
port: 80
|
||||
- host: domain.com
|
||||
backend:
|
||||
service: gateway-service
|
||||
port: 80
|
||||
```
|
||||
|
||||
## ConfigMaps
|
||||
|
||||
### Monitoring Configuration
|
||||
- Prometheus server configuration
|
||||
- Alert rules and thresholds
|
||||
|
||||
### Dashboard Configuration
|
||||
- Dashboard application settings
|
||||
- UI customization
|
||||
|
||||
### Developer Portal Configuration
|
||||
- Portal settings
|
||||
- API documentation configuration
|
||||
|
||||
### Data Plane Manager Configuration
|
||||
- Manager settings
|
||||
- Gateway group configurations
|
||||
|
||||
### Gateway Configuration
|
||||
- Gateway runtime settings
|
||||
- Backend connection configuration
|
||||
|
||||
### Certificate Authority
|
||||
- Kubernetes root CA certificate
|
||||
- Trust chain configuration
|
||||
|
||||
## Secrets
|
||||
|
||||
### TLS Certificates
|
||||
|
||||
**Control Plane Certificates**:
|
||||
- Dashboard TLS certificates
|
||||
- Developer Portal TLS certificates
|
||||
- Data Plane Manager TLS certificates
|
||||
|
||||
**Gateway Certificates**:
|
||||
- Gateway mutual TLS certificates
|
||||
- Internal communication certificates
|
||||
- Public-facing TLS certificates
|
||||
|
||||
**Application Certificates**:
|
||||
- Backend service certificates
|
||||
- Wildcard domain certificates
|
||||
|
||||
### Database Credentials
|
||||
|
||||
```yaml
|
||||
Type: Opaque
|
||||
Data:
|
||||
- database-password: ***
|
||||
- user-password: ***
|
||||
```
|
||||
|
||||
### Helm Release Secrets
|
||||
|
||||
- Helm release versioning secrets
|
||||
- Configuration state storage
|
||||
|
||||
## Persistent Volume Claims
|
||||
|
||||
### Database Storage
|
||||
|
||||
```yaml
|
||||
Size: 10Gi+ (configurable)
|
||||
Storage Class: Distributed storage
|
||||
Access Mode: RWO
|
||||
Purpose: Database persistence
|
||||
```
|
||||
|
||||
### Monitoring Storage
|
||||
|
||||
```yaml
|
||||
Size: 100Gi+ (based on retention)
|
||||
Storage Class: Local or network storage
|
||||
Access Mode: RWO
|
||||
Purpose: Metrics retention
|
||||
```
|
||||
|
||||
### Configuration Storage
|
||||
|
||||
```yaml
|
||||
Size: Based on requirements
|
||||
Storage Class: High-performance storage
|
||||
Access Mode: RWO/RWX as needed
|
||||
Purpose: Configuration persistence
|
||||
```
|
||||
|
||||
## Resource Management
|
||||
|
||||
### Useful Commands
|
||||
|
||||
**List all resources**:
|
||||
```bash
|
||||
kubectl get all -n <namespace>
|
||||
```
|
||||
|
||||
**Get specific resource details**:
|
||||
```bash
|
||||
kubectl describe deployment <deployment-name> -n <namespace>
|
||||
kubectl get svc <service-name> -n <namespace> -o yaml
|
||||
```
|
||||
|
||||
**Check pod logs**:
|
||||
```bash
|
||||
kubectl logs -n <namespace> <pod-name>
|
||||
kubectl logs -n <namespace> <pod-name> -f # Follow logs
|
||||
```
|
||||
|
||||
**Access services locally**:
|
||||
```bash
|
||||
# Forward dashboard to local port
|
||||
kubectl port-forward -n <namespace> svc/dashboard-service 7080:7080
|
||||
|
||||
# Forward gateway to local port
|
||||
kubectl port-forward -n <namespace> svc/gateway-service 8080:80
|
||||
```
|
||||
|
||||
**Scale deployments**:
|
||||
```bash
|
||||
kubectl scale deployment <deployment-name> -n <namespace> --replicas=<count>
|
||||
```
|
||||
|
||||
**Check Helm releases**:
|
||||
```bash
|
||||
helm list -n <namespace>
|
||||
helm get values <release-name> -n <namespace>
|
||||
helm status <release-name> -n <namespace>
|
||||
```
|
||||
|
||||
**Troubleshooting**:
|
||||
```bash
|
||||
kubectl get events -n <namespace>
|
||||
kubectl top pods -n <namespace>
|
||||
kubectl describe pod <pod-name> -n <namespace>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Complete Kubernetes resource reference for API Gateway infrastructure deployment.*
|
||||
72
web/docs/mkdocs.yml
Normal file
72
web/docs/mkdocs.yml
Normal file
@@ -0,0 +1,72 @@
|
||||
site_name: API7 Enterprise Demo Documentation
|
||||
site_description: Complete documentation for API7 Enterprise Gateway demo deployment
|
||||
site_author: CommandWare
|
||||
site_url: https://demo.commandware.it/docs
|
||||
|
||||
theme:
|
||||
name: material
|
||||
palette:
|
||||
- scheme: default
|
||||
primary: indigo
|
||||
accent: indigo
|
||||
toggle:
|
||||
icon: material/brightness-7
|
||||
name: Switch to dark mode
|
||||
- scheme: slate
|
||||
primary: indigo
|
||||
accent: indigo
|
||||
toggle:
|
||||
icon: material/brightness-4
|
||||
name: Switch to light mode
|
||||
features:
|
||||
- navigation.tabs
|
||||
- navigation.sections
|
||||
- navigation.expand
|
||||
- navigation.top
|
||||
- search.suggest
|
||||
- search.highlight
|
||||
- content.code.copy
|
||||
icon:
|
||||
repo: fontawesome/brands/git-alt
|
||||
|
||||
repo_name: demos/api7-demo
|
||||
repo_url: https://git.commandware.com/demos/api7-demo
|
||||
|
||||
nav:
|
||||
- Home: index.md
|
||||
- Getting Started: getting-started.md
|
||||
- Architecture:
|
||||
- Overview: architecture.md
|
||||
- Kubernetes Resources: kubernetes-resources.md
|
||||
- Configuration:
|
||||
- API7 Gateway: api7-configuration.md
|
||||
- CI/CD Pipeline: cicd-pipeline.md
|
||||
- Troubleshooting: troubleshooting.md
|
||||
|
||||
markdown_extensions:
|
||||
- admonition
|
||||
- pymdownx.details
|
||||
- pymdownx.superfences
|
||||
- pymdownx.highlight:
|
||||
anchor_linenums: true
|
||||
- pymdownx.inlinehilite
|
||||
- pymdownx.snippets
|
||||
- pymdownx.tabbed:
|
||||
alternate_style: true
|
||||
- tables
|
||||
- attr_list
|
||||
- md_in_html
|
||||
- toc:
|
||||
permalink: true
|
||||
|
||||
plugins:
|
||||
- search
|
||||
|
||||
extra:
|
||||
social:
|
||||
- icon: fontawesome/brands/git-alt
|
||||
link: https://git.commandware.com/demos/api7-demo
|
||||
version:
|
||||
provider: mike
|
||||
|
||||
copyright: Copyright © 2025 CommandWare
|
||||
702
web/docs/troubleshooting.md
Normal file
702
web/docs/troubleshooting.md
Normal file
@@ -0,0 +1,702 @@
|
||||
# Troubleshooting Guide
|
||||
|
||||
Common issues and solutions for API Gateway deployment.
|
||||
|
||||
## Gateway Issues
|
||||
|
||||
### Gateway Pods Not Starting
|
||||
|
||||
**Symptoms**:
|
||||
- Gateway pods in `CrashLoopBackOff` or `Error` state
|
||||
- Pods continuously restarting
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check pod status
|
||||
kubectl get pods -n <namespace> -l app.kubernetes.io/name=gateway
|
||||
|
||||
# View pod logs
|
||||
kubectl logs -n <namespace> <gateway-pod-name>
|
||||
|
||||
# Describe pod for events
|
||||
kubectl describe pod -n <namespace> <gateway-pod-name>
|
||||
```
|
||||
|
||||
**Common Causes & Solutions**:
|
||||
|
||||
**1. Configuration Store Connection Failure**
|
||||
```bash
|
||||
# Check Data Plane Manager is running
|
||||
kubectl get pods -n <namespace> -l app=dp-manager
|
||||
|
||||
# Verify configuration endpoint
|
||||
kubectl get configmap <gateway-configmap> -n <namespace> -o yaml | grep endpoint
|
||||
|
||||
# Expected: Configuration store endpoint URL
|
||||
```
|
||||
|
||||
**2. TLS Certificate Issues**
|
||||
```bash
|
||||
# Verify TLS secret exists
|
||||
kubectl get secret <gateway-tls-secret> -n <namespace>
|
||||
|
||||
# Check certificate validity
|
||||
kubectl get secret <gateway-tls-secret> -n <namespace> -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -dates
|
||||
```
|
||||
|
||||
**3. Configuration Error**
|
||||
```bash
|
||||
# Check gateway ConfigMap
|
||||
kubectl get configmap <gateway-configmap> -n <namespace> -o yaml
|
||||
|
||||
# Validate YAML syntax
|
||||
kubectl get configmap <gateway-configmap> -n <namespace> -o yaml | yq eval '.'
|
||||
```
|
||||
|
||||
### Gateway Returns 404 for All Routes
|
||||
|
||||
**Symptoms**:
|
||||
- All requests return HTTP 404
|
||||
- Routes configured but not working
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check if routes are published in Dashboard
|
||||
# Navigate: Services → <service> → Routes
|
||||
# Verify: Route status shows "Published"
|
||||
|
||||
# Check gateway logs for route loading
|
||||
kubectl logs -n <namespace> -l app.kubernetes.io/name=gateway --tail=100 | grep -i route
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
**1. Routes Not Published**
|
||||
- Routes synced via CLI are NOT active until published
|
||||
- Publish each route in Dashboard:
|
||||
- Services → Select service → Routes tab
|
||||
- Click "Publish" for each route
|
||||
- Select appropriate gateway group
|
||||
|
||||
**2. Wrong Gateway Group**
|
||||
```bash
|
||||
# Verify gateway group
|
||||
kubectl get deployment <gateway-deployment> -n <namespace> -o yaml | grep GATEWAY_GROUP
|
||||
|
||||
# Expected: Configured group name
|
||||
```
|
||||
|
||||
**3. Host Header Mismatch**
|
||||
```bash
|
||||
# Test with correct Host header
|
||||
curl -H "Host: app.domain.com" http://<gateway-ip>/
|
||||
|
||||
# Check route configuration
|
||||
<cli-tool> dump --server <dashboard-url> --token <TOKEN>
|
||||
```
|
||||
|
||||
### Gateway Service Unavailable (503)
|
||||
|
||||
**Symptoms**:
|
||||
- Requests return HTTP 503
|
||||
- Gateway is running but can't reach backends
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check backend service exists
|
||||
kubectl get svc -n <namespace> <backend-service-name>
|
||||
|
||||
# Check backend endpoints
|
||||
kubectl get endpoints -n <namespace> <backend-service-name>
|
||||
|
||||
# Check gateway logs
|
||||
kubectl logs -n <namespace> -l app.kubernetes.io/name=gateway --tail=100 | grep -i "503\|upstream"
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
**1. Backend Service Not Found**
|
||||
```bash
|
||||
# Verify service exists
|
||||
kubectl get svc -n <namespace>
|
||||
|
||||
# Check service name in route config matches
|
||||
<cli-tool> dump --server <URL> --token <TOKEN> | grep -A 5 upstream
|
||||
```
|
||||
|
||||
**2. No Healthy Endpoints**
|
||||
```bash
|
||||
# Check if pods are running
|
||||
kubectl get pods -n <namespace> -l app=<backend-app>
|
||||
|
||||
# Verify endpoints exist
|
||||
kubectl get endpoints -n <namespace> <service-name>
|
||||
|
||||
# If empty, check service selector
|
||||
kubectl get svc <service-name> -n <namespace> -o yaml | grep -A 3 selector
|
||||
kubectl get pods -n <namespace> --show-labels | grep <label>
|
||||
```
|
||||
|
||||
**3. Service Discovery Not Working**
|
||||
- See [Service Discovery Issues](#service-discovery-not-working)
|
||||
|
||||
## Service Discovery Issues
|
||||
|
||||
### Service Registry Not Found
|
||||
|
||||
**Error**: `service registry not found` or `discovery failed`
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check service registry in Dashboard
|
||||
# Navigate: Settings → Service Registry
|
||||
# Verify: Status shows "Connected" or "Healthy"
|
||||
|
||||
# Check gateway logs
|
||||
kubectl logs -n <namespace> -l app.kubernetes.io/name=gateway | grep -i discovery
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
**1. Service Registry Not Configured**
|
||||
- Dashboard → Settings → Service Registry → Add Service Registry
|
||||
- Type: Kubernetes
|
||||
- Configure:
|
||||
```
|
||||
Name: kubernetes-cluster
|
||||
API Server: https://kubernetes.default.svc.cluster.local:443
|
||||
Token Path: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||
```
|
||||
|
||||
**2. RBAC Permissions Missing**
|
||||
```bash
|
||||
# Check permissions
|
||||
kubectl auth can-i list endpoints --as=system:serviceaccount:<namespace>:default
|
||||
|
||||
# If "no", create ClusterRoleBinding
|
||||
kubectl create clusterrolebinding gateway-discovery \
|
||||
--clusterrole=view \
|
||||
--serviceaccount=<namespace>:default
|
||||
```
|
||||
|
||||
**3. Service Port Not Named**
|
||||
```bash
|
||||
# Check service definition
|
||||
kubectl get svc <service-name> -n <namespace> -o yaml
|
||||
|
||||
# Port MUST have a name:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8000
|
||||
name: http # ← Required for service discovery
|
||||
```
|
||||
|
||||
### Endpoints Not Discovered
|
||||
|
||||
**Symptoms**:
|
||||
- Service discovery configured but endpoints not updating
|
||||
- Scaling pods doesn't update gateway
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check service endpoints
|
||||
kubectl get endpoints -n <namespace> <service-name>
|
||||
|
||||
# Scale pods and verify endpoints update
|
||||
kubectl scale deployment <name> -n <namespace> --replicas=5
|
||||
kubectl get endpoints -n <namespace> <service-name>
|
||||
|
||||
# Check gateway discovers endpoints
|
||||
kubectl logs -n <namespace> -l app.kubernetes.io/name=gateway | grep -i endpoint
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
**1. Check Service Registry Connection**
|
||||
```bash
|
||||
# In Dashboard, verify registry status
|
||||
# Settings → Service Registry → kubernetes-cluster
|
||||
# Status should be "Connected"
|
||||
```
|
||||
|
||||
**2. Verify Service Name Format**
|
||||
```yaml
|
||||
# Format: <namespace>/<service-name>:<port-name>
|
||||
upstream:
|
||||
discovery_type: kubernetes
|
||||
service_name: <namespace>/web-service:http
|
||||
# NOT: web-service or web-service.<namespace>.svc.cluster.local
|
||||
```
|
||||
|
||||
**3. Restart Gateway Pods**
|
||||
```bash
|
||||
kubectl rollout restart deployment/<gateway-deployment> -n <namespace>
|
||||
```
|
||||
|
||||
## Ingress & Certificate Issues
|
||||
|
||||
### Certificate Not Trusted / Invalid
|
||||
|
||||
**Symptoms**:
|
||||
- Browser shows "Not Secure" warning
|
||||
- Certificate errors in logs
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check certificate
|
||||
kubectl get certificate -n <namespace>
|
||||
|
||||
# Describe certificate for errors
|
||||
kubectl describe certificate <cert-name> -n <namespace>
|
||||
|
||||
# Check cert-manager logs
|
||||
kubectl logs -n cert-manager -l app.kubernetes.io/name=cert-manager --tail=50
|
||||
|
||||
# Test certificate
|
||||
openssl s_client -connect demo.domain.com:443 -servername demo.domain.com < /dev/null 2>/dev/null | openssl x509 -noout -dates -issuer
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
**1. Certificate Not Ready**
|
||||
```bash
|
||||
# Check certificate status
|
||||
kubectl get certificate -n <namespace>
|
||||
|
||||
# If not "True", check cert-manager logs
|
||||
kubectl logs -n cert-manager -l app.kubernetes.io/name=cert-manager
|
||||
```
|
||||
|
||||
**2. DNS Challenge Failed**
|
||||
```bash
|
||||
# Check ClusterIssuer
|
||||
kubectl get clusterissuer
|
||||
|
||||
# Verify Cloudflare API token
|
||||
kubectl get secret cloudflare-api-token-secret -n cert-manager
|
||||
|
||||
# Check challenge status
|
||||
kubectl get challenge -A
|
||||
```
|
||||
|
||||
**3. Manual Certificate Creation**
|
||||
```bash
|
||||
# If cert-manager fails, use acme.sh
|
||||
export CF_Token="<CLOUDFLARE_TOKEN>"
|
||||
~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.domain.com" -d "domain.com"
|
||||
|
||||
# Create Kubernetes secret
|
||||
kubectl create secret tls wildcard-tls \
|
||||
--cert=~/.acme.sh/*.domain.com_ecc/fullchain.cer \
|
||||
--key=~/.acme.sh/*.domain.com_ecc/*.domain.com.key \
|
||||
-n <namespace>
|
||||
```
|
||||
|
||||
### LoadBalancer Stuck in Pending
|
||||
|
||||
**Symptoms**:
|
||||
- Ingress EXTERNAL-IP shows `<pending>`
|
||||
- Cannot access services externally
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check MetalLB
|
||||
kubectl get pods -n metallb-system
|
||||
|
||||
# Check IPAddressPool
|
||||
kubectl get ipaddresspool -A
|
||||
|
||||
# Check service
|
||||
kubectl describe svc -n ingress-nginx nginx-ingress-lb-custom
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
**1. MetalLB Not Running**
|
||||
```bash
|
||||
# Check MetalLB pods
|
||||
kubectl get pods -n metallb-system
|
||||
|
||||
# Restart if needed
|
||||
kubectl rollout restart deployment -n metallb-system
|
||||
```
|
||||
|
||||
**2. IP Pool Exhausted**
|
||||
```bash
|
||||
# Check IP pool configuration
|
||||
kubectl get ipaddresspool -A -o yaml
|
||||
|
||||
# Check allocated IPs
|
||||
kubectl get svc -A -o wide | grep LoadBalancer
|
||||
```
|
||||
|
||||
**3. Annotation Error**
|
||||
```bash
|
||||
# Check MetalLB annotation
|
||||
kubectl get svc <name> -n <namespace> -o yaml | grep metallb
|
||||
|
||||
# Correct format:
|
||||
metadata:
|
||||
annotations:
|
||||
metallb.universe.tf/loadBalancerIPs: "<external-ip>"
|
||||
```
|
||||
|
||||
### Ingress Returns 503 Backend Unavailable
|
||||
|
||||
**Symptoms**:
|
||||
- NGINX Ingress returns 503
|
||||
- Backend service is running
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check ingress
|
||||
kubectl describe ingress <name> -n <namespace>
|
||||
|
||||
# Check NGINX logs
|
||||
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx
|
||||
|
||||
# Check backend service
|
||||
kubectl get svc <backend-service> -n <namespace>
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
**1. Wrong Backend Service**
|
||||
```bash
|
||||
# Verify ingress points to Gateway Gateway, not application
|
||||
kubectl get ingress <name> -n <namespace> -o yaml | grep -A 5 backend
|
||||
|
||||
# Should be:
|
||||
backend:
|
||||
service:
|
||||
name: <gateway-deployment>-gateway
|
||||
port:
|
||||
number: 80
|
||||
```
|
||||
|
||||
**2. Service Port Mismatch**
|
||||
```bash
|
||||
# Check service ports
|
||||
kubectl get svc <gateway-deployment>-gateway -n <namespace>
|
||||
|
||||
# Ingress should point to port 80, not 9080
|
||||
```
|
||||
|
||||
## Control Plane Issues
|
||||
|
||||
### Dashboard Not Accessible
|
||||
|
||||
**Symptoms**:
|
||||
- Cannot access https://<dashboard-url>
|
||||
- Connection timeout or refused
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check dashboard pod
|
||||
kubectl get pods -n <namespace> -l app=<namespace>3-dashboard
|
||||
|
||||
# Check dashboard service
|
||||
kubectl get svc -n <namespace> <namespace>3-0-1759339083-dashboard
|
||||
|
||||
# Check ingress
|
||||
kubectl get ingress -n <namespace> <namespace>3-0-1759339083-dashboard
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
**1. Pod Not Running**
|
||||
```bash
|
||||
# Check pod status
|
||||
kubectl get pods -n <namespace> -l app=<namespace>3-dashboard
|
||||
|
||||
# View logs
|
||||
kubectl logs -n <namespace> -l app=<namespace>3-dashboard
|
||||
```
|
||||
|
||||
**2. Port Forward as Workaround**
|
||||
```bash
|
||||
kubectl port-forward -n <namespace> svc/<namespace>3-0-1759339083-dashboard 7080:7080
|
||||
|
||||
# Access at http://localhost:7080
|
||||
```
|
||||
|
||||
### PostgreSQL Connection Failed
|
||||
|
||||
**Symptoms**:
|
||||
- Dashboard/Portal shows database errors
|
||||
- Logs show "connection refused" to PostgreSQL
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check PostgreSQL pod
|
||||
kubectl get pods -n <namespace> -l app=postgresql
|
||||
|
||||
# Check PostgreSQL service
|
||||
kubectl get svc -n <namespace> postgresql
|
||||
|
||||
# Test connection from dashboard pod
|
||||
kubectl exec -n <namespace> -it <dashboard-pod> -- psql -h postgresql -U <namespace> -d <namespace>
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
**1. PostgreSQL Pod Not Running**
|
||||
```bash
|
||||
# Check pod status
|
||||
kubectl get pods -n <namespace> postgresql-0
|
||||
|
||||
# View logs
|
||||
kubectl logs -n <namespace> postgresql-0
|
||||
```
|
||||
|
||||
**2. Credentials Mismatch**
|
||||
```bash
|
||||
# Check credentials in secret
|
||||
kubectl get secret postgresql -n <namespace> -o jsonpath='{.data.postgres-password}' | base64 -d
|
||||
|
||||
# Compare with DSN in dashboard config
|
||||
kubectl get configmap <namespace>3-0-1759339083-dashboard-config -n <namespace> -o yaml | grep dsn
|
||||
```
|
||||
|
||||
**3. Storage Issues**
|
||||
```bash
|
||||
# Check PVC
|
||||
kubectl get pvc -n <namespace> data-postgresql-0
|
||||
|
||||
# If storage full, expand PVC (if storage class supports it)
|
||||
kubectl patch pvc data-postgresql-0 -n <namespace> -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'
|
||||
```
|
||||
|
||||
## Application Issues
|
||||
|
||||
### Image Pull Errors
|
||||
|
||||
**Error**: `ImagePullBackOff` or `ErrImagePull`
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check pod status
|
||||
kubectl get pods -n <namespace>
|
||||
|
||||
# Describe pod
|
||||
kubectl describe pod <pod-name> -n <namespace> | grep -A 10 Events
|
||||
|
||||
# Check image name
|
||||
kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.spec.containers[0].image}'
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
**1. Registry Authentication**
|
||||
```bash
|
||||
# Create registry secret
|
||||
kubectl create secret docker-registry registry-secret \
|
||||
--docker-server=<registry-url> \
|
||||
--docker-username=<USERNAME> \
|
||||
--docker-password=<TOKEN> \
|
||||
-n <namespace>
|
||||
|
||||
# Add to deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: registry-secret
|
||||
```
|
||||
|
||||
**2. Image Does Not Exist**
|
||||
```bash
|
||||
# Verify image exists
|
||||
docker pull <registry-url>/web:main
|
||||
|
||||
# Check available tags via Gitea UI or API
|
||||
curl -u <username>:<token> https://<registry-url>/api/v1/packages/demos
|
||||
```
|
||||
|
||||
**3. Wrong Image Name**
|
||||
```bash
|
||||
# Correct format:
|
||||
<registry-url>/web:main
|
||||
|
||||
# NOT:
|
||||
<registry-url>:main # Missing /web
|
||||
```
|
||||
|
||||
### Application Crashing
|
||||
|
||||
**Symptoms**:
|
||||
- Pods in `CrashLoopBackOff`
|
||||
- Application logs show errors
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check pod logs
|
||||
kubectl logs -n <namespace> <pod-name>
|
||||
|
||||
# Check previous pod logs (if restarted)
|
||||
kubectl logs -n <namespace> <pod-name> --previous
|
||||
|
||||
# Check events
|
||||
kubectl get events -n <namespace> --sort-by='.lastTimestamp' | tail -20
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
**1. Port Mismatch**
|
||||
```bash
|
||||
# Verify app runs on correct port
|
||||
# Check Dockerfile CMD or deployment env vars
|
||||
|
||||
# Common issue: App runs on 8000, container expects 3000
|
||||
```
|
||||
|
||||
**2. Missing Dependencies**
|
||||
```bash
|
||||
# Check application logs for import errors
|
||||
kubectl logs -n <namespace> <pod-name>
|
||||
|
||||
# Rebuild image with correct requirements.txt
|
||||
```
|
||||
|
||||
**3. Resource Limits**
|
||||
```bash
|
||||
# Check if OOMKilled
|
||||
kubectl describe pod <pod-name> -n <namespace> | grep -A 5 "Last State"
|
||||
|
||||
# If memory limit too low, increase:
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi # Increase from 256Mi
|
||||
```
|
||||
|
||||
## CLI / Configuration Issues
|
||||
|
||||
### CLI Sync Fails
|
||||
|
||||
**Error**: `failed to sync configuration` or authentication errors
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Test CLI connection
|
||||
<cli-tool>ping \
|
||||
--backend <namespace> \
|
||||
--server https://<dashboard-url> \
|
||||
--token <TOKEN> \
|
||||
--tls-skip-verify
|
||||
|
||||
# Validate configuration file
|
||||
<cli-tool>validate -f config.yaml
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
**1. Invalid Token**
|
||||
```bash
|
||||
# Generate new token in Dashboard
|
||||
# User → API Tokens → Generate Token
|
||||
|
||||
# Test with new token
|
||||
<cli-tool>sync -f config.yaml --server <URL> --token <NEW_TOKEN>
|
||||
```
|
||||
|
||||
**2. YAML Syntax Error**
|
||||
```bash
|
||||
# Validate YAML
|
||||
<cli-tool>validate -f config.yaml
|
||||
|
||||
# Or use yq/yamllint
|
||||
yq eval '.' config.yaml
|
||||
```
|
||||
|
||||
**3. SSL Certificate Error**
|
||||
```bash
|
||||
# Use --tls-skip-verify flag (for self-signed certs)
|
||||
<cli-tool>sync -f config.yaml --server <URL> --token <TOKEN> --tls-skip-verify
|
||||
```
|
||||
|
||||
### Configuration Not Applied
|
||||
|
||||
**Symptoms**:
|
||||
- CLI sync succeeds but changes not visible
|
||||
- Routes not working as expected
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Dump current configuration
|
||||
<cli-tool>dump --backend <namespace> --server <URL> --token <TOKEN> > current.yaml
|
||||
|
||||
# Compare with expected
|
||||
diff config.yaml current.yaml
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
**1. Routes Not Published**
|
||||
- Synced routes are NOT active until published
|
||||
- Publish via Dashboard UI
|
||||
|
||||
**2. Wrong Gateway Group**
|
||||
```bash
|
||||
# Specify correct gateway group
|
||||
<cli-tool>sync -f config.yaml --gateway-group default
|
||||
```
|
||||
|
||||
**3. Cache Issue**
|
||||
```bash
|
||||
# Restart gateway pods to force reload
|
||||
kubectl rollout restart deployment/<gateway-deployment> -n <namespace>
|
||||
```
|
||||
|
||||
## Useful Debugging Commands
|
||||
|
||||
### Check All Resources
|
||||
|
||||
```bash
|
||||
# All resources in namespace
|
||||
kubectl get all -n <namespace>
|
||||
|
||||
# Wide output with more details
|
||||
kubectl get all -n <namespace> -o wide
|
||||
|
||||
# All resource types including configmaps, secrets
|
||||
kubectl get all,cm,secret,ingress,pvc -n <namespace>
|
||||
```
|
||||
|
||||
### Log Collection
|
||||
|
||||
```bash
|
||||
# All gateway logs
|
||||
kubectl logs -n <namespace> -l app.kubernetes.io/name=gateway --all-containers=true --tail=200
|
||||
|
||||
# Dashboard logs
|
||||
kubectl logs -n <namespace> -l app=<namespace>3-dashboard --tail=100
|
||||
|
||||
# Stream logs in real-time
|
||||
kubectl logs -n <namespace> -l app.kubernetes.io/name=gateway -f
|
||||
```
|
||||
|
||||
### Network Testing
|
||||
|
||||
```bash
|
||||
# Test from within cluster
|
||||
kubectl run -it --rm debug --image=curlimages/curl --restart=Never -- sh
|
||||
|
||||
# Inside pod:
|
||||
curl http://<gateway-deployment>-gateway.<namespace>.svc.cluster.local
|
||||
curl http://web-service.<namespace>.svc.cluster.local
|
||||
```
|
||||
|
||||
### Performance Analysis
|
||||
|
||||
```bash
|
||||
# Check resource usage
|
||||
kubectl top pods -n <namespace>
|
||||
kubectl top nodes
|
||||
|
||||
# Describe for resource limits
|
||||
kubectl describe pod <pod-name> -n <namespace> | grep -A 5 Limits
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Comprehensive troubleshooting guide for API Gateway infrastructure deployment.*
|
||||
137
web/main.py
Normal file
137
web/main.py
Normal file
@@ -0,0 +1,137 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
import uvicorn
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
app = FastAPI(title="Web Demo Application")
|
||||
|
||||
# Build MkDocs documentation on startup
|
||||
def build_docs():
|
||||
docs_dir = os.path.join(os.path.dirname(__file__), "docs")
|
||||
site_dir = os.path.join(os.path.dirname(__file__), "site")
|
||||
|
||||
if os.path.exists(docs_dir):
|
||||
try:
|
||||
subprocess.run(
|
||||
["mkdocs", "build", "-f", os.path.join(docs_dir, "mkdocs.yml"), "-d", site_dir],
|
||||
check=True,
|
||||
capture_output=True
|
||||
)
|
||||
print(f"✓ Documentation built successfully at {site_dir}")
|
||||
return True
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"✗ Failed to build documentation: {e.stderr.decode()}")
|
||||
return False
|
||||
except FileNotFoundError:
|
||||
print("✗ MkDocs not installed. Install with: pip install mkdocs mkdocs-material")
|
||||
return False
|
||||
return False
|
||||
|
||||
# Build docs on startup
|
||||
@app.on_event("startup")
|
||||
async def startup_event():
|
||||
build_docs()
|
||||
|
||||
# Mount static documentation site at /docs
|
||||
site_dir = os.path.join(os.path.dirname(__file__), "site")
|
||||
if os.path.exists(site_dir):
|
||||
app.mount("/docs", StaticFiles(directory=site_dir, html=True), name="docs")
|
||||
|
||||
# Simple HTML template inline
|
||||
HTML_TEMPLATE = """
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Web Demo</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 50px auto;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.container {
|
||||
background-color: white;
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
h1 {
|
||||
color: #333;
|
||||
border-bottom: 2px solid #4CAF50;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.info-box {
|
||||
background-color: #e8f5e9;
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
border-left: 4px solid #4CAF50;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.metric {
|
||||
display: inline-block;
|
||||
margin: 10px 20px 10px 0;
|
||||
padding: 10px 20px;
|
||||
background-color: #2196F3;
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.doc-link {
|
||||
display: inline-block;
|
||||
margin: 20px 10px 0 0;
|
||||
padding: 12px 24px;
|
||||
background-color: #673AB7;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
.doc-link:hover {
|
||||
background-color: #512DA8;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Welcome to Web Demo Application</h1>
|
||||
<div class="info-box">
|
||||
<h2>Application Information</h2>
|
||||
<p><strong>Service:</strong> Web Frontend</p>
|
||||
<p><strong>Status:</strong> ✓ Running</p>
|
||||
<p><strong>Version:</strong> 1.0.0</p>
|
||||
</div>
|
||||
<h2>Metrics Dashboard</h2>
|
||||
<div>
|
||||
<span class="metric">Requests: 1,234</span>
|
||||
<span class="metric">Uptime: 99.9%</span>
|
||||
<span class="metric">Users: 567</span>
|
||||
</div>
|
||||
<div class="info-box">
|
||||
<h3>About</h3>
|
||||
<p>This is a demo FastAPI web application serving HTML content.
|
||||
It demonstrates a simple web interface with metrics and information display.</p>
|
||||
</div>
|
||||
<div>
|
||||
<a href="/docs/" class="doc-link">📚 View Documentation</a>
|
||||
<a href="/health" class="doc-link">🏥 Health Check</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
@app.get("/", response_class=HTMLResponse)
|
||||
async def root():
|
||||
"""Serve the main webpage"""
|
||||
return HTML_TEMPLATE
|
||||
|
||||
@app.get("/health")
|
||||
async def health():
|
||||
"""Health check endpoint"""
|
||||
return {"status": "healthy", "service": "web"}
|
||||
|
||||
if __name__ == "__main__":
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000)
|
||||
4
web/requirements.txt
Normal file
4
web/requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
fastapi==0.104.1
|
||||
uvicorn[standard]==0.24.0
|
||||
mkdocs==1.5.3
|
||||
mkdocs-material==9.5.3
|
||||
Reference in New Issue
Block a user