d.viti 20c9d2eaf4
Some checks failed
Helm Chart Build and Release / lint-only (push) Has been skipped
Helm Chart Build and Release / build-and-release-helm (push) Failing after 11s
Build and Deploy / build-web (push) Successful in 37s
Build and Deploy / build-api (push) Successful in 36s
Simplify Helm versioning to always use Chart.yaml version
- Removed automatic version generation from tags or timestamps
- Always use version directly from Chart.yaml (single source of truth)
- Tag triggers now only determine if it's a release (not version)
- Release is triggered when tag matches Chart.yaml version
- Manual dispatch version is now for validation only
- Removed version modification during packaging
- Simplified packaging process to use Chart's own version
- Removed --devel flag as all versions are now stable
- Better separation: version managed in Chart.yaml, release triggered by tags
2025-10-03 02:37:50 +02:00
2025-10-03 01:20:15 +02:00

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:

cd web
pip install -r requirements.txt
python main.py
# Access at http://localhost:8000

API Application:

cd api
pip install -r requirements.txt
python main.py
# Swagger at http://localhost:8000/docs

Docker

Build and run Web:

docker build -t web-app ./web
docker run -p 8000:8000 web-app

Build and run API:

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:

    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

# Add the Gitea Helm repository
helm repo add api7ee https://git.commandware.com/api/packages/$OWNER/helm
helm repo update

Install the Chart

# 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

# 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:

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

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:

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

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

# 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

# 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:

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:

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:

kubectl create clusterrolebinding api7-gateway-discovery \
  --clusterrole=view \
  --serviceaccount=<API7_NAMESPACE>:default

Ingress Configuration

Example ingress for API7 Gateway:

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:

# 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:

# 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

🔐 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

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%