Files
api7-demo/README.md
d.viti a379b26808 Consolidate all Helm build and release tasks into single workflow
- Removed build-helm job from build.yml (Docker builds only now)
- Created comprehensive helm-release.yml that handles:
  - Development builds on main branch pushes (with dev suffix)
  - Release builds on version tags (v*.*.*)
  - Manual releases via workflow_dispatch
  - PR linting without publishing
- Added intelligent version detection:
  - Development versions get timestamp suffix
  - Release versions use clean semver
  - Manual dispatch can specify custom version
- Improved release process with proper Gitea API integration
- Added conditional release creation only for tagged versions
- Updated README to document the new workflow structure
- Separated concerns: build.yml for Docker, helm-release.yml for Helm
2025-10-03 02:35:16 +02:00

559 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-release.yml`**:
1. Packages Helm charts on every main branch push
2. Creates development versions for main branch builds
3. Creates release versions for tags (v*.*.*)
4. Publishes charts to Gitea Helm registry
5. Creates GitHub releases for tagged versions
**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