# Ingress and Gateway Routing Learn how external traffic is routed through Kubernetes Ingress to the API7 Gateway, and then to backend services. ## Architecture Overview ```mermaid graph LR A[External User] -->|HTTPS| B[Ingress Controller] B -->|HTTP/HTTPS| C[API7 Gateway] C -->|Apply Plugins| C C -->|Route Traffic| D[Backend Service 1] C -->|Route Traffic| E[Backend Service 2] C -->|Route Traffic| F[Backend Service 3] G[cert-manager] -->|TLS Cert| B H[ADC ConfigMap] -->|Routing Rules| C ``` **Traffic Flow:** 1. **External request** arrives at Ingress Controller (NGINX) 2. **Ingress Controller** terminates TLS and forwards to API7 Gateway 3. **API7 Gateway** applies policies (rate limiting, CORS, auth) 4. **Gateway** routes to backend services based on ADC rules 5. **Backend services** process request and return response ## Ingress Configuration ### Current Setup The Helm chart configures Ingress to route **all traffic** through API7 Gateway: ```yaml # values.yaml ingress: enabled: true className: "nginx" hosts: - host: commandware.it paths: - path: / pathType: Prefix gateway: serviceName: gateway-0-1759393614-gateway port: 80 ``` Generated Ingress resource: ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: api7ee-demo annotations: cert-manager.io/cluster-issuer: cloudflare-acme-prod spec: ingressClassName: nginx tls: - hosts: - commandware.it secretName: api7ee-tls rules: - host: commandware.it http: paths: - path: / pathType: Prefix backend: service: name: gateway-0-1759393614-gateway port: number: 80 ``` ### Why Route Through Gateway? **With API7 Gateway (Recommended):** ``` User → Ingress → API7 Gateway → Backend ↓ TLS, Basic Routing ↓ Advanced Features: - Dynamic routing - Rate limiting - CORS policies - Authentication - Request transformation - Metrics & logging ``` **Direct to Service (Legacy):** ``` User → Ingress → Backend ↓ TLS, Basic Routing ❌ No advanced features ❌ No rate limiting ❌ No CORS ❌ No centralized auth ``` ## Gateway Routing Rules ### ADC Configuration API7 Gateway uses **ADC (API Declarative Configuration)** to define routing rules: ```yaml # Managed by Helm chart in ConfigMap services: - name: web-service hosts: - commandware.it upstream: discovery_type: kubernetes service_name: my-web-app namespace_id: default routes: - name: web-route uris: - /* priority: 1 plugins: cors: {...} redirect: http_to_https: true - name: api-service hosts: - commandware.it upstream: discovery_type: kubernetes service_name: my-api namespace_id: default routes: - name: api-route uris: - /api - /api/* priority: 10 plugins: limit-count: {...} cors: {...} ``` ### Route Priority Routes are evaluated by **priority** (higher number = higher priority): ```yaml routes: # Evaluated FIRST (highest priority) - name: api-llm-route uris: - /api/llm/* priority: 20 plugins: ai-rate-limiting: {...} # Evaluated SECOND - name: api-route uris: - /api/* priority: 10 plugins: limit-count: {...} # Evaluated LAST (lowest priority) - name: web-route uris: - /* priority: 1 ``` **Example Request Matching:** - `GET /api/llm/chat` → Matches `api-llm-route` (priority 20) - `GET /api/users` → Matches `api-route` (priority 10) - `GET /about` → Matches `web-route` (priority 1) ### URI Matching Patterns **Prefix matching:** ```yaml uris: - /api/* # Matches /api/users, /api/v1/products, etc. - /admin/* # Matches /admin/dashboard, /admin/users, etc. ``` **Exact matching:** ```yaml uris: - /health # Matches only /health - /ready # Matches only /ready ``` **Regex matching:** ```yaml vars: - - uri - "~~" - "^(?!/api)" # Match all URIs NOT starting with /api ``` ## TLS/SSL Configuration ### Certificate Management The setup uses **cert-manager** with Cloudflare ACME: ```yaml # values.yaml ingress: annotations: cert-manager.io/cluster-issuer: cloudflare-acme-prod tls: - secretName: api7ee-tls hosts: - commandware.it ``` Generated Certificate: ```yaml apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: api7ee-demo-tls spec: secretName: api7ee-tls issuerRef: name: cloudflare-acme-prod kind: ClusterIssuer dnsNames: - commandware.it duration: 2160h # 90 days renewBefore: 720h # Renew 30 days before expiry ``` ### HTTP to HTTPS Redirect API7 Gateway handles HTTP→HTTPS redirect: ```yaml plugins: redirect: http_to_https: true ``` **Request flow:** 1. User visits `http://commandware.it/api` 2. Gateway returns `301 Moved Permanently` 3. Browser redirects to `https://commandware.it/api` ## Advanced Routing Scenarios ### Multiple Domains Route different domains to different backends: ```yaml services: - name: main-site hosts: - commandware.it upstream: service_name: main-web routes: - uris: ["/*"] - name: api-site hosts: - api.commandware.it upstream: service_name: api-backend routes: - uris: ["/*"] ``` ### Path-Based Routing Route based on URL paths: ```yaml routes: # Route 1: Frontend SPA - name: frontend uris: - / - /app/* - /assets/* upstream: service_name: frontend-app # Route 2: API endpoints - name: backend-api uris: - /api/* upstream: service_name: backend-api # Route 3: Admin panel - name: admin uris: - /admin/* upstream: service_name: admin-panel plugins: key-auth: {...} # Require authentication ``` ### Header-Based Routing Route based on HTTP headers: ```yaml routes: # Route for API v2 clients - name: api-v2 uris: - /api/* vars: - - http_x_api_version - "==" - "v2" upstream: service_name: api-v2 # Route for API v1 clients (default) - name: api-v1 uris: - /api/* upstream: service_name: api-v1 ``` ### Method-Based Routing Route based on HTTP method: ```yaml routes: # Read operations → Read-only replica - name: read-ops uris: - /api/* methods: - GET - HEAD upstream: service_name: api-readonly # Write operations → Primary backend - name: write-ops uris: - /api/* methods: - POST - PUT - DELETE - PATCH upstream: service_name: api-primary ``` ## Configuration Examples ### Example 1: Microservices API ```yaml services: # User service - name: users-api hosts: - api.commandware.it upstream: discovery_type: kubernetes service_name: users-service routes: - uris: ["/users", "/users/*"] plugins: limit-count: count: 100 time_window: 60 # Orders service - name: orders-api hosts: - api.commandware.it upstream: discovery_type: kubernetes service_name: orders-service routes: - uris: ["/orders", "/orders/*"] plugins: key-auth: {} # Products service - name: products-api hosts: - api.commandware.it upstream: discovery_type: kubernetes service_name: products-service routes: - uris: ["/products", "/products/*"] ``` ### Example 2: API with WebSocket ```yaml services: - name: websocket-service hosts: - ws.commandware.it upstream: service_name: websocket-backend routes: # WebSocket endpoint - name: ws-route uris: - /ws enable_websocket: true # HTTP fallback - name: http-route uris: - /* ``` ### Example 3: Canary Deployment ```yaml services: # 90% traffic to stable version - name: app-stable hosts: - app.commandware.it upstream: service_name: app-v1 nodes: - weight: 90 routes: - uris: ["/*"] # 10% traffic to canary version - name: app-canary hosts: - app.commandware.it upstream: service_name: app-v2 nodes: - weight: 10 routes: - uris: ["/*"] ``` ## Monitoring and Debugging ### Check Ingress Status ```bash # Get Ingress resource kubectl get ingress -n api7ee # Describe Ingress kubectl describe ingress api7ee-demo -n api7ee # Check Ingress Controller logs kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx ``` ### Check Gateway Routing ```bash # View ADC configuration kubectl get configmap api7ee-demo-api7ee-demo-k8s-adc-config -n api7ee -o yaml # Check Gateway logs kubectl logs -n api7ee -l app.kubernetes.io/name=gateway # Test routing curl -v https://commandware.it/api/health ``` ### Verify TLS Certificate ```bash # Check certificate kubectl get certificate -n api7ee # Describe certificate kubectl describe certificate api7ee-demo-tls -n api7ee # View certificate secret kubectl get secret api7ee-tls -n api7ee -o yaml # Test TLS connection openssl s_client -connect commandware.it:443 -servername commandware.it ``` ## Troubleshooting ### 404 Not Found **Cause:** No route matches the request **Debug:** ```bash # Check ADC routes kubectl get configmap -n api7ee api7ee-demo-adc-config -o yaml | grep -A 10 "routes:" # Check Gateway logs kubectl logs -n api7ee -l app.kubernetes.io/name=gateway | grep 404 ``` ### 502 Bad Gateway **Cause:** Backend service is unavailable **Debug:** ```bash # Check backend service kubectl get svc my-backend -n api7ee # Check backend Pods kubectl get pods -l app=my-backend -n api7ee # Check service discovery kubectl get endpoints my-backend -n api7ee ``` ### TLS Certificate Issues **Cause:** cert-manager failed to issue certificate **Debug:** ```bash # Check certificate status kubectl describe certificate api7ee-demo-tls -n api7ee # Check cert-manager logs kubectl logs -n cert-manager -l app=cert-manager # Check certificate request kubectl get certificaterequest -n api7ee ``` ## Best Practices ### 1. Always Use Gateway for Production ✅ **Do:** Route through API7 Gateway for advanced features ❌ **Don't:** Route directly to backend services ### 2. Use Descriptive Route Names ```yaml # Good routes: - name: api-users-list - name: api-products-create - name: web-frontend-spa # Bad routes: - name: route1 - name: route2 ``` ### 3. Set Appropriate Priorities Higher priority for more specific routes: ```yaml # Specific route (high priority) - uris: ["/api/v2/users/*"] priority: 20 # General route (low priority) - uris: ["/api/*"] priority: 10 ``` ### 4. Enable TLS Everywhere Always use HTTPS in production: ```yaml plugins: redirect: http_to_https: true ``` ### 5. Monitor Gateway Metrics Set up monitoring for: - Request latency - Error rates (4xx, 5xx) - Upstream health - TLS certificate expiry ## Next Steps - [Configure Service Discovery](service-discovery.md) - [Manage Secrets Securely](secret-management.md) - [Set Up Rate Limiting](api7-configuration.md#rate-limiting) ## References - [Kubernetes Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) - [cert-manager Documentation](https://cert-manager.io/docs/) - [API7 Gateway Routing](https://docs.api7.ai/enterprise/key-concepts/routes/)