- Changed chart name from api7ee to api7ee-demo-k8s in Chart.yaml
- Renamed helm/api7ee directory to helm/api7ee-demo-k8s
- Updated all references in build.yml workflow
- Updated all references in helm-release.yml workflow
- Updated main README.md with new chart name
- Updated Helm chart README with new chart name
- Verified all old references have been replaced
- Chart packages correctly as api7ee-demo-k8s-{version}.tgz
551 lines
12 KiB
Markdown
551 lines
12 KiB
Markdown
# 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. Packages and publishes Helm chart
|
|
5. Implements layer caching for faster builds
|
|
|
|
**Triggers:**
|
|
- Any branch push (Docker images)
|
|
- Push to main branch (Helm chart)
|
|
- Version tags (Helm releases)
|
|
- Manual dispatch
|
|
|
|
**Registry:** `git.commandware.com/demos/api7-demo`
|
|
|
|
**Docker Images:**
|
|
- `git.commandware.com/demos/api7-demo/web:<branch-name>`
|
|
- `git.commandware.com/demos/api7-demo/api:<branch-name>`
|
|
|
|
**Helm Repository:**
|
|
- `https://git.commandware.com/api/packages/$OWNER/helm`
|
|
|
|
### 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+)
|
|
- Helm 3.8.0+
|
|
- API7 Enterprise Gateway installed
|
|
- Namespace: `api7ee`
|
|
|
|
### Deploy with Helm
|
|
|
|
The project includes a complete Helm chart for easy deployment of both web and API components.
|
|
|
|
#### Add Helm Repository
|
|
|
|
```bash
|
|
# Add the Gitea Helm repository
|
|
helm repo add api7ee https://git.commandware.com/api/packages/$OWNER/helm
|
|
helm repo update
|
|
```
|
|
|
|
#### Install the Chart
|
|
|
|
```bash
|
|
# Install with default values
|
|
helm install my-api7ee api7ee/api7ee-demo-k8s --namespace api7ee --create-namespace
|
|
|
|
# Install with custom values
|
|
helm install my-api7ee api7ee/api7ee-demo-k8s -f custom-values.yaml --namespace api7ee
|
|
|
|
# Install with specific image tags
|
|
helm install my-api7ee api7ee/api7ee-demo-k8s \
|
|
--set web.image.tag=v1.0.0 \
|
|
--set api.image.tag=v1.0.0 \
|
|
--namespace api7ee
|
|
```
|
|
|
|
#### Configuration Options
|
|
|
|
Key Helm values:
|
|
|
|
| Parameter | Description | Default |
|
|
|-----------|-------------|---------|
|
|
| `web.enabled` | Enable Web component | `true` |
|
|
| `web.replicaCount` | Number of Web replicas | `2` |
|
|
| `api.enabled` | Enable API component | `true` |
|
|
| `api.replicaCount` | Number of API replicas | `3` |
|
|
| `ingress.enabled` | Enable ingress | `true` |
|
|
| `ingress.hosts[0].host` | Ingress hostname | `demo.commandware.it` |
|
|
|
|
#### Upgrade/Uninstall
|
|
|
|
```bash
|
|
# Upgrade the release
|
|
helm upgrade my-api7ee api7ee/api7ee-demo-k8s --namespace api7ee
|
|
|
|
# Uninstall
|
|
helm uninstall my-api7ee --namespace api7ee
|
|
```
|
|
|
|
### Manual Deployment (Alternative)
|
|
|
|
**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
|