d.viti 741117dab8
All checks were successful
Helm Chart Build / lint-only (push) Has been skipped
Helm Chart Build / build-helm (push) Successful in 1m10s
Build and Deploy / build-api (push) Successful in 2m20s
Build and Deploy / build-web (push) Successful in 2m36s
Refactor ADC install and usage in job-adc-sync script
Simplify dependency installation and ADC binary setup. Replace ADC
command lookup logic with direct usage after installation.
2025-10-08 13:55:58 +02:00

API7 Enterprise Edition Demo

A comprehensive demo platform showcasing API7 Enterprise Edition (API7EE) as an API Gateway with two FastAPI microservices: a Web frontend with embedded documentation and an API backend with LLM integration. Features automated CI/CD via Gitea Actions, Helm-based deployment, and advanced API7 Gateway configurations including AI rate limiting.

📋 Table of Contents

🎯 Overview

This project demonstrates enterprise-grade API Gateway patterns using API7 Enterprise Edition, showcasing:

  • Microservices Architecture: Web frontend + API backend
  • AI Integration: LLM endpoints with OpenAI-compatible API
  • Advanced Rate Limiting: Token-based AI rate limiting + IP-based rate limiting
  • Service Discovery: Kubernetes-native service discovery via API7
  • Automated Deployment: Gitea Actions CI/CD + Helm charts
  • Production-Ready: TLS, monitoring, autoscaling, and security policies

Live Demo: https://api7-demo.commandware.it

🏗️ Architecture

┌─────────────────────────────────────────────────────────────┐
│                      Internet / Users                        │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│             NGINX Ingress Controller (TLS)                   │
│              cert-manager (Let's Encrypt)                    │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                  API7 Enterprise Gateway                     │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  Routes & Plugins:                                    │  │
│  │  • / → Web Service (Apache/Nginx)                    │  │
│  │  • /api → API Backend (Rate: 100 req/60s)           │  │
│  │  • /api/llm → LLM Endpoints (Rate: 100 tokens/60s)  │  │
│  └──────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘
                              │
                 ┌────────────┴────────────┐
                 ▼                         ▼
    ┌─────────────────────┐   ┌──────────────────────┐
    │   Web Service       │   │   API Service        │
    │   (apache/nginx)    │   │   (nginx)            │
    │                     │   │                      │
    │   • Frontend UI     │   │   • REST API         │
    │   • Documentation   │   │   • LLM Integration  │
    │   • API Proxy       │   │   • Swagger Docs     │
    │   Replicas: 2-10    │   │   Replicas: 3-20     │
    └─────────────────────┘   └──────────────────────┘
                                         │
                                         ▼
                              ┌──────────────────────┐
                              │  Open WebUI (LLM)    │
                              │  OpenAI-Compatible   │
                              └──────────────────────┘

Service Naming

Important: The Helm chart names services as apache-service and nginx-service for API7 routing:

  • Web Service: Deployed as apache-service (serves frontend and docs)
  • API Service: Deployed as nginx-service (serves REST API and LLM endpoints)

This naming convention is used in ADC configuration for consistent routing.

📁 Project Structure

api7ee/
├── web/                          # Web frontend application
│   ├── main.py                   # FastAPI app with templates & API proxy
│   ├── Dockerfile                # Multi-stage build with MkDocs
│   ├── requirements.txt          # Dependencies: fastapi, httpx, mkdocs
│   ├── templates/                # Jinja2 HTML templates
│   │   ├── base.html            # Base template
│   │   ├── index.html           # Dashboard
│   │   ├── items.html           # Items page
│   │   ├── users.html           # Users page
│   │   └── llm.html             # LLM chat interface
│   ├── static/                   # CSS and JavaScript assets
│   ├── docs/                     # MkDocs documentation source
│   │   ├── index.md
│   │   ├── getting-started.md
│   │   ├── architecture.md
│   │   ├── api7-configuration.md
│   │   ├── kubernetes-resources.md
│   │   ├── cicd-pipeline.md
│   │   └── troubleshooting.md
│   └── mkdocs.yml               # MkDocs configuration
├── api/                          # API backend application
│   ├── main.py                   # FastAPI app with REST + LLM endpoints
│   ├── Dockerfile                # Container image
│   ├── requirements.txt          # Dependencies: fastapi, httpx, pydantic
│   └── db.json                   # Sample data file
├── helm/                         # Helm chart for Kubernetes
│   └── api7ee-demo-k8s/
│       ├── Chart.yaml            # Chart metadata (v0.1.0)
│       ├── values.yaml           # Default configuration
│       ├── values-dev.yaml       # Development overrides
│       ├── values-production.yaml # Production overrides
│       └── templates/            # Kubernetes manifests
│           ├── deployment-web.yaml
│           ├── deployment-api.yaml
│           ├── service-web.yaml
│           ├── service-api.yaml
│           ├── ingress.yaml
│           ├── configmap-adc.yaml    # API7 ADC configuration
│           ├── job-adc-sync.yaml     # ADC sync job
│           ├── certificate.yaml      # cert-manager certificate
│           ├── hpa-web.yaml          # Horizontal Pod Autoscaler
│           ├── hpa-api.yaml
│           └── ...
├── .gitea/
│   └── workflows/
│       ├── build.yml             # Docker image builds
│       └── helm-build.yml        # Helm chart packaging
├── adc.yaml                      # Standalone API7 ADC configuration
└── README.md                     # This file

Features

Web Application (web/)

  • Interactive Dashboard: Modern UI with real-time stats
  • Embedded Documentation: MkDocs Material theme at /docs
  • API Proxy: Proxies requests to API backend
  • LLM Chat Interface: Chat with videogame expert AI
  • Health Checks: /health endpoint
  • Static Assets: Custom CSS and JavaScript

API Application (api/)

  • REST API: Items and Users CRUD operations
  • LLM Integration: OpenAI-compatible chat endpoint
  • Swagger Documentation: Auto-generated at /docs
  • Data Validation: Pydantic models
  • Health Endpoints: /health and /llm/health
  • Model Management: /llm/models endpoint

API7 Gateway Features

  • Advanced Rate Limiting:
    • Standard: 100 requests/60s per IP for /api/*
    • AI: 100 tokens/60s for /api/llm/* (token-based)
  • Service Discovery: Kubernetes-native discovery
  • TLS/SSL: Automatic certificate management
  • HTTP → HTTPS Redirect: Enforced on all routes
  • Prometheus Metrics: Built-in monitoring
  • Route Prioritization: LLM routes (priority 20) > API (10) > Web (1)

DevOps Features

  • CI/CD: Gitea Actions for automated builds
  • Helm Packaging: Automated chart publishing
  • Horizontal Autoscaling: HPA for both services
  • Pod Disruption Budgets: High availability
  • Security: Non-root containers, read-only root filesystem
  • Multi-Environment: Dev and production value files

🚀 Quick Start

Prerequisites

  • Docker (for local development)
  • Kubernetes cluster (v1.19+)
  • Helm 3.8.0+
  • API7 Enterprise Edition installed
  • kubectl configured

Local Development

Run Web Application

cd web
pip install -r requirements.txt

# Set API backend URL (optional)
export API_BASE_URL="http://localhost:8001"

python main.py

Access:

Run API Application

cd api
pip install -r requirements.txt

# Configure LLM endpoint (optional)
export OPENAI_API_BASE="http://localhost:11434/api"
export OPENAI_API_KEY="your-api-key"
export DEFAULT_LLM_MODEL="videogame-expert"

python main.py

Access:

Docker Development

# Build images
docker build -t web-app ./web
docker build -t api-app ./api

# Run containers
docker run -d -p 8000:8000 --name web web-app
docker run -d -p 8001:8001 --name api api-app

# With environment variables
docker run -d -p 8001:8001 \
  -e OPENAI_API_BASE="http://host.docker.internal:11434/api" \
  -e OPENAI_API_KEY="sk-xxx" \
  --name api api-app

🔄 CI/CD Pipeline

Docker Image Builds

Workflow: .gitea/workflows/build.yml

Triggers:

  • Push to any branch
  • Pull requests
  • Manual dispatch

Process:

  1. Checkout code
  2. Set up Docker Buildx
  3. Login to Gitea container registry
  4. Build and push images:
    • git.commandware.com/demos/api7-demo/web:<branch-name>
    • git.commandware.com/demos/api7-demo/api:<branch-name>

Helm Chart Publishing

Workflow: .gitea/workflows/helm-build.yml

Triggers:

  • Push to main branch (publishes)
  • Pull requests (lint only)
  • Manual dispatch

Process:

  1. Extract version from Chart.yaml
  2. Lint Helm chart
  3. Update image registries in values
  4. Package chart as .tgz
  5. Push to Gitea Helm registry: https://git.commandware.com/api/packages/demos/helm

Chart Versioning: Version is defined in helm/api7ee-demo-k8s/Chart.yaml (single source of truth)

Setup CI/CD

  1. Create Gitea Secrets:

    Repository Settings → Secrets → Add Secret
    - Name: USERNAME
    - Value: your-gitea-username
    
    - Name: TOKEN
    - Value: <gitea-token-with-write:package>
    
  2. Generate Token:

    • User Settings → Applications → Generate New Token
    • Scopes: write:package, read:package
  3. Push to Trigger:

    git push origin main
    

☸️ Kubernetes Deployment

Add Helm Repository

# Add the Helm repository
helm repo add api7ee https://git.commandware.com/api/packages/demos/helm

# Update repositories
helm repo update

# Search for available versions
helm search repo api7ee

Install

# Install with default values
helm install api7ee-demo api7ee/api7ee-demo-k8s \
  --namespace api7ee \
  --create-namespace

# Install with custom values
helm install api7ee-demo api7ee/api7ee-demo-k8s \
  --namespace api7ee \
  -f custom-values.yaml

# Install specific version with custom image tags
helm install api7ee-demo api7ee/api7ee-demo-k8s \
  --version 0.1.0 \
  --set web.image.tag=main \
  --set api.image.tag=main \
  --set api7.gateway.adminKey="your-admin-key" \
  --namespace api7ee

Configuration

Key values to customize:

# Custom domain
api7:
  hosts:
    - your-domain.com

# API7 Gateway connection
api7:
  gateway:
    adminUrl: http://api7ee3-0-xxx-dp-manager.api7ee.svc.cluster.local:7900
    adminKey: "your-admin-key"
    gatewayService: gateway-0-xxx-gateway

# Image tags
web:
  image:
    tag: "v1.0.0"
api:
  image:
    tag: "v1.0.0"

# Scaling
web:
  replicaCount: 3
api:
  replicaCount: 5
  autoscaling:
    enabled: true
    maxReplicas: 30

# TLS
api7:
  tls:
    certManager:
      enabled: true
      issuer: cloudflare-acme-prod

Manage Deployment

# Check status
helm list -n api7ee
kubectl get pods -n api7ee

# Upgrade
helm upgrade api7ee-demo api7ee/api7ee-demo-k8s \
  --namespace api7ee \
  --reuse-values \
  --set api.replicaCount=5

# Rollback
helm rollback api7ee-demo -n api7ee

# Uninstall
helm uninstall api7ee-demo -n api7ee

Using Local Helm Chart

# Install from local directory
helm install api7ee-demo ./helm/api7ee-demo-k8s \
  --namespace api7ee \
  --create-namespace

# Use production values
helm install api7ee-demo ./helm/api7ee-demo-k8s \
  -f ./helm/api7ee-demo-k8s/values-production.yaml \
  --namespace api7ee

Environment-Specific Deployments

Development:

helm install api7ee-dev ./helm/api7ee-demo-k8s \
  -f ./helm/api7ee-demo-k8s/values-dev.yaml \
  --namespace api7ee-dev

Production:

helm install api7ee-prod ./helm/api7ee-demo-k8s \
  -f ./helm/api7ee-demo-k8s/values-production.yaml \
  --namespace api7ee-prod

🔌 API7 Gateway Configuration

ADC (API7 Declarative CLI) Configuration

The Helm chart automatically configures API7 Gateway using ADC. Configuration is in helm/api7ee-demo-k8s/templates/configmap-adc.yaml.

Route Structure

1. Web Route (Priority: 1)

- name: apache-route
  uris: [/*]
  vars:
    - [uri, "~~", "^(?!/api)"] # Match all except /api/*
  plugins:
    redirect:
      http_to_https: true

2. API Route (Priority: 10)

- name: nginx-api-route
  uris: [/api, /api/*]
  plugins:
    redirect:
      http_to_https: true
    limit-count:
      count: 100
      time_window: 60
      key_type: "var"
      key: "remote_addr"

3. LLM Route (Priority: 20)

- name: nginx-api-llm-route
  uris: [/api/llm, /api/llm/*]
  plugins:
    redirect:
      http_to_https: true
    ai-rate-limiting:
      limit: 100
      time_window: 60
      limit_strategy: "total_tokens"

Manual ADC Sync

If you need to manually sync ADC configuration:

# Using standalone adc.yaml file
adc sync -f adc.yaml \
  --backend api7ee \
  --server https://api7-dashboard.commandware.it \
  --token <YOUR_API7_TOKEN> \
  --gateway-group default \
  --tls-skip-verify

# Publish routes via Dashboard
# Navigate to: Services → Routes → Click "Publish" → Select "default" gateway group

Service Discovery

API7 automatically discovers Kubernetes services:

upstream:
  type: roundrobin
  discovery_type: kubernetes # Helm uses direct node configuration
  nodes:
    - host: apache-service.api7ee.svc.cluster.local
      port: 80
      weight: 100

When pods scale, API7 automatically updates the upstream nodes.

Rate Limiting Configuration

Standard Rate Limiting (IP-based):

  • Plugin: limit-count
  • Limit: 100 requests per 60 seconds per IP
  • Applies to: /api/* routes (excluding /api/llm/*)

AI Rate Limiting (Token-based):

  • Plugin: ai-rate-limiting
  • Limit: 100 tokens per 60 seconds
  • Strategy: total_tokens (counts input + output tokens)
  • Applies to: /api/llm/* routes

TLS/SSL Configuration

Option 1: cert-manager (Recommended)

api7:
  tls:
    certManager:
      enabled: true
      issuer: cloudflare-acme-prod
      issuerKind: ClusterIssuer

Option 2: Existing Secret

api7:
  tls:
    enabled: true
    secretName: my-tls-secret

Option 3: Direct Certificates (Not recommended for production)

api7:
  tls:
    enabled: true
    certificate: |
      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----
    key: |
      -----BEGIN PRIVATE KEY-----
      ...
      -----END PRIVATE KEY-----

🛠️ Development

Environment Variables

Web Application:

API_BASE_URL=http://localhost:8001  # API backend URL

API Application:

OPENAI_API_BASE=http://localhost:11434/api  # LLM API endpoint
OPENAI_API_KEY=your-api-key                 # LLM API key
DEFAULT_LLM_MODEL=videogame-expert          # Default model

Testing Endpoints

# Web health
curl http://localhost:8000/health

# API health
curl http://localhost:8001/health

# LLM health
curl http://localhost:8001/llm/health

# Get items
curl http://localhost:8001/items

# LLM chat
curl -X POST http://localhost:8001/llm/chat \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "What is Zelda?",
    "max_tokens": 150,
    "model": "videogame-expert"
  }'

Building Documentation

cd web

# Serve documentation locally
mkdocs serve

# Build static site
mkdocs build -d site

🔧 Troubleshooting

Common Issues

1. Routes Return 404

Symptom: Routes synced but returning 404

Cause: Routes not published to gateway group

Solution:

# Check route status in API7 Dashboard
# Services → Select service → Routes → Check publication status

# Publish via Dashboard:
# Click "Publish" → Select "default" gateway group → Confirm

# Or enable autoPublish in Helm:
api7:
  autoPublish: true

2. ADC Sync Job Fails

Symptom: ADC sync job shows error status

Check logs:

kubectl logs -n api7ee -l app.kubernetes.io/component=adc-sync

# Common issues:
# - Incorrect adminKey
# - Wrong adminUrl (should point to dp-manager service)
# - Network connectivity to API7 Gateway

Verify API7 connection:

# Test API7 admin API
kubectl run -it --rm debug --image=curlimages/curl --restart=Never -- \
  curl -H "X-API-KEY: your-admin-key" \
  http://api7ee3-0-xxx-dp-manager.api7ee.svc.cluster.local:7900/apisix/admin/routes

3. Service Discovery Not Working

Check:

# Verify service exists
kubectl get svc -n api7ee apache-service nginx-service

# Check service endpoints
kubectl get endpoints -n api7ee

# Verify service has named ports
kubectl get svc apache-service -n api7ee -o yaml | grep -A5 ports

Ensure ports are named:

spec:
  ports:
    - port: 80
      targetPort: 8000
      name: http # ← Name is required

4. LLM Endpoints Failing

Check API configuration:

# Verify environment variables
kubectl get deployment nginx-service -n api7ee -o yaml | grep -A10 env

# Check API logs
kubectl logs -n api7ee -l app=nginx-service --tail=50

# Test LLM backend directly
curl http://localhost:11434/api/chat/completions \
  -H "Authorization: Bearer your-key" \
  -d '{"model":"videogame-expert","messages":[{"role":"user","content":"test"}]}'

5. Image Pull Errors

Solution:

# 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 Helm values
global:
  imagePullSecrets:
    - name: gitea-registry

6. Certificate Issues

Check cert-manager:

# Check certificate status
kubectl get certificate -n api7ee

# Check certificate details
kubectl describe certificate api7ee-tls -n api7ee

# Check cert-manager logs
kubectl logs -n cert-manager -l app=cert-manager --tail=50

# Check challenge status (for ACME)
kubectl get challenge -n api7ee

Getting Help

  1. Check logs:

    kubectl logs -n api7ee -l app.kubernetes.io/name=api7ee-demo-k8s --tail=100
    
  2. Check events:

    kubectl get events -n api7ee --sort-by='.lastTimestamp'
    
  3. Verify Helm installation:

    helm status api7ee-demo -n api7ee
    helm get values api7ee-demo -n api7ee
    
  4. Test connectivity:

    kubectl run -it --rm debug --image=nicolaka/netshoot --restart=Never -n api7ee -- bash
    # Inside pod:
    curl http://apache-service
    curl http://nginx-service
    

📚 Resources

Documentation

Support

📄 License

Demo project for API7 Enterprise Gateway evaluation.


Version: 0.1.0 | Last Updated: 2025-10-07

Description
Demo for API7 on kubernetes with MetaLLB and Nginx-Ingress (community)
Readme 415 KiB
Languages
Python 40%
HTML 32.5%
CSS 16.1%
JavaScript 6.2%
Smarty 3.5%
Other 1.7%