Move documentation to MkDocs and add comprehensive guides
All checks were successful
Helm Chart Build / lint-only (push) Has been skipped
Helm Chart Build / build-helm (push) Successful in 9s
Build and Deploy / build-api (push) Successful in 44s
Build and Deploy / build-web (push) Successful in 1m10s

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 <noreply@anthropic.com>
This commit is contained in:
d.viti
2025-10-09 16:00:29 +02:00
parent 694709ae9a
commit c5b597c7c1
6 changed files with 1118 additions and 93 deletions

View File

@@ -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

616
web/docs/ingress-routing.md Normal file
View File

@@ -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/)

View File

@@ -0,0 +1,233 @@
# Secret Management for API7 Gateway
This document explains how to manage API7 Gateway credentials securely.
## Overview
API7 Gateway requires the following credentials:
- **Admin URL**: Dashboard admin API endpoint
- **Admin Key**: Authentication token for admin API
- **Gateway Group**: Logical grouping of gateway instances
## Configuration Options
### Option 1: Inline Configuration (Development Only)
**⚠️ NOT RECOMMENDED for production**
Credentials are stored directly in `values.yaml`:
```yaml
api7:
gateway:
existingSecret: "" # Leave empty
adminUrl: https://api7ee3-0-1759339083-dashboard:7443
adminKey: "your-admin-key"
group: default
```
The chart will create a Kubernetes Secret automatically.
### Option 2: Existing Secret (Recommended)
**✅ RECOMMENDED for production**
Create a Secret manually or using a secret management tool, then reference it:
```yaml
api7:
gateway:
existingSecret: "api7-credentials" # Name of your secret
existingSecretKeys:
adminUrl: admin-url
adminKey: admin-key
group: gateway-group
```
#### Create Secret Manually
```bash
kubectl create secret generic api7-credentials \
--from-literal=admin-url=https://api7ee3-0-1759339083-dashboard:7443 \
--from-literal=admin-key=YOUR_ADMIN_KEY \
--from-literal=gateway-group=default \
-n api7ee
```
#### Get Admin Key from API7 Enterprise
```bash
# Get admin key from API7 Enterprise installation
kubectl get secret -n api7ee api7ee3-0-1759339083 \
-o jsonpath='{.data.admin_key}' | base64 -d
```
### Option 3: External Secrets Operator
**✅ RECOMMENDED for production with centralized secret management**
Use External Secrets Operator to sync secrets from external providers like:
- AWS Secrets Manager
- HashiCorp Vault
- Azure Key Vault
- GCP Secret Manager
- And more...
#### Step 1: Install External Secrets Operator
```bash
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets -n external-secrets-system --create-namespace
```
#### Step 2: Configure SecretStore
Example for HashiCorp Vault:
```yaml
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
```
#### Step 3: Create ExternalSecret
See `templates/externalsecret-api7.yaml.example` for a complete example.
```yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: api7-credentials-external
namespace: api7ee
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: SecretStore
target:
name: api7-credentials
creationPolicy: Owner
data:
- secretKey: admin-url
remoteRef:
key: api7/gateway
property: admin_url
- secretKey: admin-key
remoteRef:
key: api7/gateway
property: admin_key
- secretKey: gateway-group
remoteRef:
key: api7/gateway
property: gateway_group
```
#### Step 4: Configure Helm Values
```yaml
api7:
gateway:
existingSecret: "api7-credentials" # Created by ExternalSecret
```
## Secret Keys
The Secret must contain these keys (default names):
| Key | Description | Example |
|-----|-------------|---------|
| `admin-url` | Dashboard admin API URL | `https://api7ee3-0-1759339083-dashboard:7443` |
| `admin-key` | Dashboard admin API key | `edd1c9f034335f136f87ad84b625c8f1` |
| `gateway-group` | Gateway group name | `default` |
### Custom Key Names
If your Secret uses different key names, configure them:
```yaml
api7:
gateway:
existingSecret: "my-custom-secret"
existingSecretKeys:
adminUrl: dashboard_url # Your custom key name
adminKey: api_token # Your custom key name
group: group_name # Your custom key name
```
## Security Best Practices
1. **Never commit secrets to Git**
- Use `.gitignore` for values files containing secrets
- Use secret management tools for production
2. **Use RBAC to restrict secret access**
- Limit which ServiceAccounts can read secrets
- Use namespace isolation
3. **Rotate credentials regularly**
- Update admin keys periodically
- Use External Secrets Operator for automatic rotation
4. **Enable audit logging**
- Monitor secret access in Kubernetes audit logs
- Alert on unauthorized access attempts
5. **Use encryption at rest**
- Enable Kubernetes secret encryption
- Use external KMS for additional security
## Troubleshooting
### Secret not found
```bash
# Check if secret exists
kubectl get secret -n api7ee
# Describe the secret
kubectl describe secret api7-credentials -n api7ee
```
### Invalid credentials
```bash
# View secret data (base64 encoded)
kubectl get secret api7-credentials -n api7ee -o yaml
# Decode and verify values
kubectl get secret api7-credentials -n api7ee \
-o jsonpath='{.data.admin-key}' | base64 -d
```
### ADC sync job fails
```bash
# Check job logs
kubectl logs -n api7ee job/api7ee-demo-api7ee-demo-k8s-adc-sync
# Common issues:
# - Wrong admin URL (check DNS resolution)
# - Invalid admin key (verify key is correct)
# - TLS certificate issues (use tlsSkipVerify: true for self-signed)
```
## References
- [External Secrets Operator Documentation](https://external-secrets.io/)
- [Kubernetes Secrets](https://kubernetes.io/docs/concepts/configuration/secret/)
- [API7 Enterprise Documentation](https://docs.api7.ai/enterprise/)

View File

@@ -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/)