From c5b597c7c125b1eaa74dc9c3d5374d4a267c246d Mon Sep 17 00:00:00 2001 From: "d.viti" Date: Thu, 9 Oct 2025 16:00:29 +0200 Subject: [PATCH] Move documentation to MkDocs and add comprehensive guides MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reorganized documentation to be part of MkDocs site with three new comprehensive guides covering API7 Gateway configuration. Changes: 1. Documentation Structure: - Moved SECRET-MANAGEMENT.md from helm/ to web/docs/ - Created service-discovery.md with complete guide - Created ingress-routing.md with routing architecture - Moved externalsecret examples to web/docs/examples/ 2. New Documentation - Service Discovery: - How service discovery works (architecture diagram) - Benefits vs static configuration - Configuration examples - RBAC requirements - Advanced use cases (auto-scaling, rolling updates) - Load balancing algorithms - Monitoring and troubleshooting - Best practices 3. New Documentation - Ingress & Routing: - Complete traffic flow architecture - Ingress configuration explained - Gateway routing rules and priority - URI matching patterns (prefix, exact, regex) - TLS/SSL with cert-manager - Advanced routing scenarios: * Multiple domains * Path-based routing * Header-based routing * Method-based routing - Configuration examples (microservices, WebSocket, canary) - Monitoring and debugging - Troubleshooting common issues 4. MkDocs Navigation: - Updated mkdocs.yml with new pages in Configuration section - Added: Ingress & Routing - Added: Service Discovery - Added: Secret Management 5. Examples Directory: - Created web/docs/examples/ for configuration examples - Moved ExternalSecret examples with multiple providers: * AWS Secrets Manager * HashiCorp Vault * Azure Key Vault * GCP Secret Manager All documentation now integrated into MkDocs site with proper navigation, cross-references, and Material theme styling. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../externalsecret-api7.yaml.example | 93 --- web/docs/examples/externalsecret-api7.yaml | 120 ++++ web/docs/ingress-routing.md | 616 ++++++++++++++++++ .../docs/secret-management.md | 0 web/docs/service-discovery.md | 379 +++++++++++ web/mkdocs.yml | 3 + 6 files changed, 1118 insertions(+), 93 deletions(-) delete mode 100644 helm/api7ee-demo-k8s/templates/externalsecret-api7.yaml.example create mode 100644 web/docs/examples/externalsecret-api7.yaml create mode 100644 web/docs/ingress-routing.md rename helm/api7ee-demo-k8s/SECRET-MANAGEMENT.md => web/docs/secret-management.md (100%) create mode 100644 web/docs/service-discovery.md diff --git a/helm/api7ee-demo-k8s/templates/externalsecret-api7.yaml.example b/helm/api7ee-demo-k8s/templates/externalsecret-api7.yaml.example deleted file mode 100644 index 84e468c..0000000 --- a/helm/api7ee-demo-k8s/templates/externalsecret-api7.yaml.example +++ /dev/null @@ -1,93 +0,0 @@ -# Example ExternalSecret for API7 Gateway credentials -# This file is not deployed by default - it serves as an example. -# -# To use External Secrets Operator: -# 1. Install External Secrets Operator in your cluster -# 2. Configure a SecretStore (e.g., AWS Secrets Manager, Vault, etc.) -# 3. Rename this file to remove .example extension -# 4. Set api7.gateway.existingSecret to the secret name below -# 5. Adjust the backend configuration to match your SecretStore -# -# Documentation: https://external-secrets.io/ - -{{- if false }} # Change to 'if .Values.api7.gateway.useExternalSecret' to enable -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ include "api7ee.fullname" . }}-api7-admin-external - labels: - {{- include "api7ee.labels" . | nindent 4 }} - app.kubernetes.io/component: api7 -spec: - # Refresh interval for fetching secrets from external provider - refreshInterval: 1h - - # Reference to SecretStore - secretStoreRef: - name: vault-backend # Name of your SecretStore - kind: SecretStore # or ClusterSecretStore - - # Target Secret configuration - target: - name: {{ include "api7ee.fullname" . }}-api7-admin - creationPolicy: Owner - template: - type: Opaque - data: - # Map external secret keys to Kubernetes secret keys - admin-url: "{{ `{{ .adminUrl }}` }}" - admin-key: "{{ `{{ .adminKey }}` }}" - gateway-group: "{{ `{{ .group }}` }}" - - # Data to fetch from external provider - data: - - secretKey: adminUrl - remoteRef: - key: api7/gateway # Path in external secret store - property: admin_url # Property name - - - secretKey: adminKey - remoteRef: - key: api7/gateway - property: admin_key - - - secretKey: group - remoteRef: - key: api7/gateway - property: gateway_group - ---- -# Example for AWS Secrets Manager -# apiVersion: external-secrets.io/v1beta1 -# kind: SecretStore -# metadata: -# name: aws-secretsmanager -# spec: -# provider: -# aws: -# service: SecretsManager -# region: us-east-1 -# auth: -# jwt: -# serviceAccountRef: -# name: external-secrets-sa - ---- -# Example for HashiCorp Vault -# apiVersion: external-secrets.io/v1beta1 -# kind: SecretStore -# metadata: -# name: vault-backend -# spec: -# provider: -# vault: -# server: "https://vault.example.com" -# path: "secret" -# version: "v2" -# auth: -# kubernetes: -# mountPath: "kubernetes" -# role: "api7-role" -# serviceAccountRef: -# name: {{ include "api7ee.serviceAccountName" . }} -{{- end }} diff --git a/web/docs/examples/externalsecret-api7.yaml b/web/docs/examples/externalsecret-api7.yaml new file mode 100644 index 0000000..3cc5697 --- /dev/null +++ b/web/docs/examples/externalsecret-api7.yaml @@ -0,0 +1,120 @@ +# Example ExternalSecret for API7 Gateway credentials +# This file demonstrates how to use External Secrets Operator with API7 Gateway +# +# Documentation: https://external-secrets.io/ + +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: api7-gateway-credentials + namespace: api7ee + labels: + app.kubernetes.io/name: api7ee-demo + app.kubernetes.io/component: api7 +spec: + # Refresh interval for fetching secrets from external provider + refreshInterval: 1h + + # Reference to SecretStore + secretStoreRef: + name: vault-backend # Name of your SecretStore + kind: SecretStore # or ClusterSecretStore + + # Target Secret configuration + target: + name: api7-credentials + creationPolicy: Owner + template: + type: Opaque + data: + # Map external secret keys to Kubernetes secret keys + admin-url: "{{ .adminUrl }}" + admin-key: "{{ .adminKey }}" + gateway-group: "{{ .group }}" + + # Data to fetch from external provider + data: + - secretKey: adminUrl + remoteRef: + key: api7/gateway # Path in external secret store + property: admin_url # Property name + + - secretKey: adminKey + remoteRef: + key: api7/gateway + property: admin_key + + - secretKey: group + remoteRef: + key: api7/gateway + property: gateway_group + +--- +# Example SecretStore for AWS Secrets Manager +apiVersion: external-secrets.io/v1beta1 +kind: SecretStore +metadata: + name: aws-secretsmanager + namespace: api7ee +spec: + provider: + aws: + service: SecretsManager + region: us-east-1 + auth: + jwt: + serviceAccountRef: + name: external-secrets-sa + +--- +# Example SecretStore for HashiCorp Vault +apiVersion: external-secrets.io/v1beta1 +kind: SecretStore +metadata: + name: vault-backend + namespace: api7ee +spec: + provider: + vault: + server: "https://vault.example.com" + path: "secret" + version: "v2" + auth: + kubernetes: + mountPath: "kubernetes" + role: "api7-role" + serviceAccountRef: + name: api7ee-demo-api7ee-demo-k8s + +--- +# Example SecretStore for Azure Key Vault +apiVersion: external-secrets.io/v1beta1 +kind: SecretStore +metadata: + name: azure-keyvault + namespace: api7ee +spec: + provider: + azurekv: + vaultUrl: "https://my-vault.vault.azure.net" + authType: WorkloadIdentity + serviceAccountRef: + name: api7ee-demo-api7ee-demo-k8s + +--- +# Example SecretStore for GCP Secret Manager +apiVersion: external-secrets.io/v1beta1 +kind: SecretStore +metadata: + name: gcp-secretmanager + namespace: api7ee +spec: + provider: + gcpsm: + projectID: "my-project" + auth: + workloadIdentity: + clusterLocation: us-central1 + clusterName: my-cluster + serviceAccountRef: + name: api7ee-demo-api7ee-demo-k8s diff --git a/web/docs/ingress-routing.md b/web/docs/ingress-routing.md new file mode 100644 index 0000000..8a111bd --- /dev/null +++ b/web/docs/ingress-routing.md @@ -0,0 +1,616 @@ +# 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/) diff --git a/helm/api7ee-demo-k8s/SECRET-MANAGEMENT.md b/web/docs/secret-management.md similarity index 100% rename from helm/api7ee-demo-k8s/SECRET-MANAGEMENT.md rename to web/docs/secret-management.md diff --git a/web/docs/service-discovery.md b/web/docs/service-discovery.md new file mode 100644 index 0000000..90850bc --- /dev/null +++ b/web/docs/service-discovery.md @@ -0,0 +1,379 @@ +# Service Discovery + +Learn how API7 Gateway dynamically discovers backend services using Kubernetes service discovery. + +## Overview + +Service Discovery enables API7 Gateway to automatically discover and track backend Pod endpoints instead of using static upstream node configuration. This provides a dynamic, scalable, and resilient architecture. + +## Why Use Service Discovery? + +### Traditional Static Configuration + +```yaml +upstream: + nodes: + - host: 10.0.1.23 + port: 8080 + weight: 100 + - host: 10.0.1.24 + port: 8080 + weight: 100 +``` + +**Problems:** +- ❌ Manual updates required when Pods scale +- ❌ Stale Pod IPs after deployments +- ❌ No automatic health checks +- ❌ Downtime during updates + +### With Kubernetes Service Discovery + +```yaml +upstream: + discovery_type: kubernetes + service_name: my-service + namespace_id: default +``` + +**Benefits:** +- ✅ Automatic Pod discovery +- ✅ Real-time updates during scaling +- ✅ Health checks built-in +- ✅ Zero downtime deployments + +## How It Works + +```mermaid +graph LR + A[API7 Gateway] -->|Query Endpoints| B[Kubernetes API] + B -->|Return Pod IPs| A + A -->|Route Traffic| C[Pod 1] + A -->|Route Traffic| D[Pod 2] + A -->|Route Traffic| E[Pod 3] + + F[HPA/Deploy] -->|Scale/Update| B + B -->|Notify| A +``` + +1. **API7 Gateway** watches Kubernetes Endpoints API +2. **Kubernetes API** returns list of healthy Pod IPs +3. **Gateway** automatically adds/removes Pods from upstream +4. **Traffic** is load-balanced across discovered Pods + +## Configuration + +### Enable in Helm Chart + +Edit `values.yaml`: + +```yaml +api7: + serviceDiscovery: + enabled: true # Enable Kubernetes service discovery + namespace: "" # Leave empty to use release namespace +``` + +### ADC Configuration + +The Helm chart automatically generates ADC configuration with service discovery: + +```yaml +services: + - name: my-service + upstream: + name: my-upstream + type: roundrobin + discovery_type: kubernetes + service_name: my-service # Kubernetes Service name + namespace_id: default # Kubernetes namespace +``` + +### RBAC Requirements + +Service Discovery requires permissions to watch Kubernetes resources. These are automatically configured in `rbac-adc.yaml`: + +```yaml +rules: + # Allow reading services and endpoints for service discovery + - apiGroups: [""] + resources: ["services", "endpoints"] + verbs: ["get", "list", "watch"] +``` + +## Use Cases + +### 1. Auto-Scaling Applications + +When your application scales: + +```bash +# Scale deployment +kubectl scale deployment my-app --replicas=10 + +# API7 Gateway automatically discovers new Pods +# No configuration changes needed! +``` + +### 2. Rolling Updates + +During deployments: + +```bash +# Start rolling update +kubectl rollout restart deployment my-app + +# Gateway automatically: +# 1. Discovers new Pods +# 2. Adds them to upstream +# 3. Removes old Pods +# 4. Zero downtime! +``` + +### 3. Multi-Service Architecture + +Discover multiple backend services: + +```yaml +services: + - name: web-frontend + upstream: + discovery_type: kubernetes + service_name: web-frontend + namespace_id: production + + - name: api-backend + upstream: + discovery_type: kubernetes + service_name: api-backend + namespace_id: production + + - name: admin-api + upstream: + discovery_type: kubernetes + service_name: admin-api + namespace_id: admin +``` + +## Advanced Configuration + +### Cross-Namespace Discovery + +Discover services in different namespaces: + +```yaml +upstream: + discovery_type: kubernetes + service_name: shared-service + namespace_id: shared-services # Different namespace +``` + +!!! warning "RBAC Permissions" + Ensure the ServiceAccount has permissions to watch Endpoints in the target namespace. + +### Load Balancing Algorithms + +Combine service discovery with load balancing: + +```yaml +upstream: + discovery_type: kubernetes + service_name: my-service + namespace_id: default + type: roundrobin # or chash, least_conn, ewma +``` + +**Available algorithms:** +- `roundrobin`: Distribute requests evenly (default) +- `chash`: Consistent hashing (sticky sessions) +- `least_conn`: Send to Pod with fewest connections +- `ewma`: Exponentially weighted moving average + +### Health Checks + +API7 Gateway respects Kubernetes readiness probes: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: my-app +spec: + containers: + - name: app + readinessProbe: + httpGet: + path: /health + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 3 +``` + +Only Pods with passing readiness checks receive traffic. + +## Monitoring + +### Check Discovered Endpoints + +View upstream nodes in API7 Dashboard: + +```bash +# Port-forward to dashboard +kubectl port-forward -n api7ee svc/api7ee3-0-1759339083-dashboard 7443:7443 + +# Open browser +open https://localhost:7443 +``` + +Navigate to: **Gateway Groups → Upstreams → View Nodes** + +### Debug Service Discovery + +Check ADC sync logs: + +```bash +# View ADC sync job logs +kubectl logs -n api7ee job/api7ee-demo-api7ee-demo-k8s-adc-sync + +# Look for service discovery messages +# [INFO] Discovered 3 endpoints for service my-service +``` + +## Troubleshooting + +### No Endpoints Discovered + +**Symptoms:** Gateway shows 0 upstream nodes + +**Causes:** +1. Service doesn't exist +2. No Pods match Service selector +3. All Pods are not ready + +**Solution:** +```bash +# Check Service exists +kubectl get service my-service -n default + +# Check Endpoints +kubectl get endpoints my-service -n default + +# Check Pod readiness +kubectl get pods -l app=my-service -n default +``` + +### RBAC Permission Denied + +**Error:** `forbidden: User "system:serviceaccount:..." cannot list endpoints` + +**Solution:** +Verify RBAC permissions: + +```bash +# Check Role binding +kubectl get rolebinding -n api7ee | grep adc + +# Describe permissions +kubectl describe role api7ee-demo-api7ee-demo-k8s-adc -n api7ee +``` + +### Stale Endpoints + +**Symptoms:** Traffic sent to terminated Pods + +**Causes:** Kubernetes API not updating fast enough + +**Solution:** +Check Kubernetes API health: + +```bash +# Verify API server is responsive +kubectl get --raw /healthz + +# Check endpoint update timestamps +kubectl get endpoints my-service -o yaml | grep -i time +``` + +## Best Practices + +### 1. Use Service Discovery for All Dynamic Workloads + +✅ **Do:** +```yaml +upstream: + discovery_type: kubernetes + service_name: my-dynamic-app +``` + +❌ **Don't:** +```yaml +upstream: + nodes: + - host: pod-ip # Brittle, breaks on restart +``` + +### 2. Configure Readiness Probes + +Always configure readiness probes on Pods: + +```yaml +readinessProbe: + httpGet: + path: /ready + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 5 +``` + +### 3. Use Namespaces for Isolation + +Separate environments by namespace: + +```yaml +# Production +namespace_id: production + +# Staging +namespace_id: staging + +# Development +namespace_id: development +``` + +### 4. Monitor Discovery Performance + +Set up alerts for: +- Number of discovered endpoints +- Service discovery latency +- RBAC permission errors + +### 5. Test Failover Scenarios + +Regularly test: +- Pod termination +- Rolling updates +- Scale up/down events + +## Comparison: Static vs Service Discovery + +| Feature | Static Nodes | Service Discovery | +|---------|--------------|-------------------| +| Setup | Manual | Automatic | +| Scaling | Manual updates | Automatic | +| Health checks | Manual | Built-in | +| Deployments | Downtime risk | Zero downtime | +| Maintenance | High | Low | +| Flexibility | Low | High | +| Production-ready | ❌ | ✅ | + +## Next Steps + +- [Configure Secret Management](secret-management.md) +- [Set up Ingress Routing](kubernetes-resources.md#ingress) +- [Monitor Gateway Metrics](troubleshooting.md#monitoring) + +## References + +- [API7 Service Discovery Documentation](https://docs.api7.ai/enterprise/3.2.14.6/best-practice/service-discovery/) +- [Kubernetes Endpoints API](https://kubernetes.io/docs/concepts/services-networking/service/#endpoints) +- [Kubernetes Service Discovery](https://kubernetes.io/docs/concepts/services-networking/service/) diff --git a/web/mkdocs.yml b/web/mkdocs.yml index 44de420..18f3b97 100644 --- a/web/mkdocs.yml +++ b/web/mkdocs.yml @@ -41,6 +41,9 @@ nav: - Kubernetes Resources: kubernetes-resources.md - Configuration: - API7 Gateway: api7-configuration.md + - Ingress & Routing: ingress-routing.md + - Service Discovery: service-discovery.md + - Secret Management: secret-management.md - CI/CD Pipeline: cicd-pipeline.md - Troubleshooting: troubleshooting.md