Files
api7-demo/README.md
d.viti 11d116bdd1
Some checks failed
Helm Chart Build / lint-only (push) Has been skipped
Helm Chart Build / build-helm (push) Failing after 9s
Build and Deploy / build-web (push) Successful in 37s
Build and Deploy / build-api (push) Successful in 38s
Simplify Helm workflow to build on main branch only
- Removed tag-based triggers and release creation
- Renamed workflow from helm-release.yml to helm-build.yml
- Simplified to always build and publish on main branch push
- Version always comes from Chart.yaml (no modifications)
- Removed all release-related logic and conditions
- Kept PR linting for validation
- Cleaner and simpler workflow focused on continuous delivery
- Updated README to reflect the new workflow structure
2025-10-03 02:42:25 +02:00

558 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 CI/CD workflows automatically:
**`.gitea/workflows/build.yml`**:
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
**`.gitea/workflows/helm-build.yml`**:
1. Packages Helm charts on every main branch push
2. Uses version from Chart.yaml (single source of truth)
3. Publishes charts to Gitea Helm registry
4. Validates charts on pull requests (lint only)
**Triggers:**
- Any branch push (Docker images)
- Push to main branch (Helm chart)
- Pull requests (Helm lint only)
- 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