diff --git a/api/main.py b/api/main.py index cfdecf0..6876903 100644 --- a/api/main.py +++ b/api/main.py @@ -214,4 +214,5 @@ async def llm_health(): } if __name__ == "__main__": - uvicorn.run(app, host="0.0.0.0", port=8001) + port = int(os.getenv("PORT", 8080)) + uvicorn.run(app, host="0.0.0.0", port=port) diff --git a/helm/api7ee-demo-k8s/README.md b/helm/api7ee-demo-k8s/README.md index 6b6cd02..43ecc87 100644 --- a/helm/api7ee-demo-k8s/README.md +++ b/helm/api7ee-demo-k8s/README.md @@ -7,7 +7,9 @@ A comprehensive Helm chart for deploying the API7 Enterprise Edition demo platfo This Helm chart provides: - **Dual Service Deployment**: Web frontend + API backend -- **API7 Gateway Integration**: Automatic ADC (API7 Declarative CLI) configuration +- **API7 Gateway Configuration**: Automatic ADC (API7 Declarative CLI) sync to existing gateway + - ⚠️ **Does NOT install API7 Gateway** - gateway must already exist + - Only configures routes, services, and upstreams on existing gateway - **TLS/SSL Management**: cert-manager integration or custom certificates - **Service Discovery**: Kubernetes-native service discovery - **Rate Limiting**: Standard and AI token-based rate limiting @@ -47,11 +49,46 @@ This Helm chart provides: ## 📦 Prerequisites +### Required + - **Kubernetes**: v1.19 or higher - **Helm**: 3.8.0 or higher -- **API7 Enterprise Edition**: Installed and configured -- **Ingress Controller**: NGINX Ingress Controller (recommended) -- **cert-manager**: v1.0+ (optional, for automatic TLS) +- **API7 Enterprise Edition Gateway**: **MUST be already installed and running** + - This chart does NOT install API7 Gateway + - This chart only configures routes and services on an existing gateway + - You need the DP Manager admin URL and admin key + - Example: `http://api7ee3-0-xxx-dp-manager.api7ee.svc.cluster.local:7900` + +### Optional + +- **Ingress Controller**: NGINX Ingress Controller (for direct Kubernetes ingress) +- **cert-manager**: v1.0+ (for automatic TLS certificate management) + +### Before Installation + +1. **Verify API7 Gateway is Running**: + + ```bash + kubectl get pods -n api7ee | grep gateway + kubectl get pods -n api7ee | grep dp-manager + ``` + +2. **Get API7 Admin Credentials**: + + ```bash + # Get DP Manager URL + kubectl get svc -n api7ee | grep dp-manager + + # Get admin key from API7 Dashboard or documentation + # Default is usually generated during API7 installation + ``` + +3. **Test Gateway Connectivity**: + ```bash + # Test from within cluster + kubectl run test-curl --rm -i --restart=Never --image=curlimages/curl:latest \ + -- curl -s http://api7ee3-0-xxx-dp-manager.api7ee.svc.cluster.local:7900/version + ``` ## 🚀 Installation diff --git a/helm/api7ee-demo-k8s/templates/configmap-adc.yaml b/helm/api7ee-demo-k8s/templates/configmap-adc.yaml index 3a20988..e026320 100644 --- a/helm/api7ee-demo-k8s/templates/configmap-adc.yaml +++ b/helm/api7ee-demo-k8s/templates/configmap-adc.yaml @@ -9,19 +9,21 @@ metadata: data: adc-config.yaml: | services: - - name: apache-service + # Web Frontend Service + - name: {{ include "api7ee.fullname" . }}-web-service hosts: - {{ (first .Values.api7.hosts) | quote }} upstream: - name: apache-upstream + name: {{ include "api7ee.fullname" . }}-web-upstream scheme: http type: roundrobin nodes: - - host: apache-service.{{ .Release.Namespace }}.svc.cluster.local - port: 80 + - host: {{ include "api7ee.fullname" . }}-web.{{ .Release.Namespace }}.svc.cluster.local + port: {{ .Values.web.service.port }} weight: 100 routes: - - name: apache-route + # Route for web frontend (all paths except /api) + - name: {{ include "api7ee.fullname" . }}-web-route uris: - /* vars: @@ -34,20 +36,31 @@ data: redirect: http_to_https: true {{- end }} + {{- if .Values.api7.plugins.cors.enabled }} + cors: + allow_origins: {{ .Values.api7.plugins.cors.allowOrigins | toJson }} + allow_methods: {{ .Values.api7.plugins.cors.allowMethods | toJson }} + allow_headers: {{ .Values.api7.plugins.cors.allowHeaders | toJson }} + expose_headers: {{ .Values.api7.plugins.cors.exposeHeaders | toJson }} + max_age: {{ .Values.api7.plugins.cors.maxAge }} + allow_credential: {{ .Values.api7.plugins.cors.allowCredentials }} + {{- end }} - - name: nginx-api-service + # API Backend Service + - name: {{ include "api7ee.fullname" . }}-api-service hosts: - {{ (first .Values.api7.hosts) | quote }} upstream: - name: nginx-upstream + name: {{ include "api7ee.fullname" . }}-api-upstream scheme: http type: roundrobin nodes: - - host: nginx-service.{{ .Release.Namespace }}.svc.cluster.local - port: 80 + - host: {{ include "api7ee.fullname" . }}-api.{{ .Release.Namespace }}.svc.cluster.local + port: {{ .Values.api.service.port }} weight: 100 routes: - - name: nginx-api-llm-route + # High priority route for LLM endpoints with AI rate limiting + - name: {{ include "api7ee.fullname" . }}-api-llm-route uris: - /api/llm - /api/llm/* @@ -57,6 +70,15 @@ data: redirect: http_to_https: true {{- end }} + {{- if .Values.api7.plugins.cors.enabled }} + cors: + allow_origins: {{ .Values.api7.plugins.cors.allowOrigins | toJson }} + allow_methods: {{ .Values.api7.plugins.cors.allowMethods | toJson }} + allow_headers: {{ .Values.api7.plugins.cors.allowHeaders | toJson }} + expose_headers: {{ .Values.api7.plugins.cors.exposeHeaders | toJson }} + max_age: {{ .Values.api7.plugins.cors.maxAge }} + allow_credential: {{ .Values.api7.plugins.cors.allowCredentials }} + {{- end }} {{- if .Values.api7.plugins.aiRateLimit.enabled }} ai-rate-limiting: limit: {{ .Values.api7.plugins.aiRateLimit.limit }} @@ -65,7 +87,8 @@ data: limit_strategy: {{ .Values.api7.plugins.aiRateLimit.limitStrategy | quote }} {{- end }} - - name: nginx-api-route + # Standard API route with request rate limiting + - name: {{ include "api7ee.fullname" . }}-api-route uris: - /api - /api/* @@ -75,6 +98,15 @@ data: redirect: http_to_https: true {{- end }} + {{- if .Values.api7.plugins.cors.enabled }} + cors: + allow_origins: {{ .Values.api7.plugins.cors.allowOrigins | toJson }} + allow_methods: {{ .Values.api7.plugins.cors.allowMethods | toJson }} + allow_headers: {{ .Values.api7.plugins.cors.allowHeaders | toJson }} + expose_headers: {{ .Values.api7.plugins.cors.exposeHeaders | toJson }} + max_age: {{ .Values.api7.plugins.cors.maxAge }} + allow_credential: {{ .Values.api7.plugins.cors.allowCredentials }} + {{- end }} {{- if .Values.api7.plugins.rateLimit.enabled }} limit-count: count: {{ .Values.api7.plugins.rateLimit.count }} @@ -85,6 +117,7 @@ data: {{- end }} {{- if .Values.api7.plugins.auth.enabled }} + # API Consumers for authentication consumers: {{- range .Values.api7.consumers }} - username: {{ .username }} @@ -94,6 +127,7 @@ data: {{- end }} {{- end }} + # Global Rules global_rules: {{- if .Values.api7.plugins.prometheus.enabled }} - id: prometheus-metrics diff --git a/helm/api7ee-demo-k8s/templates/job-adc-sync.yaml b/helm/api7ee-demo-k8s/templates/job-adc-sync.yaml index cfd0964..cad0884 100644 --- a/helm/api7ee-demo-k8s/templates/job-adc-sync.yaml +++ b/helm/api7ee-demo-k8s/templates/job-adc-sync.yaml @@ -63,13 +63,26 @@ spec: echo "Waiting for API7 Gateway to be available..." MAX_RETRIES=30 RETRY_COUNT=0 + {{- if eq .Values.api7.backend "api7ee" }} + # For API7 EE, check the version endpoint + HEALTH_ENDPOINT="${API7_ADMIN_URL}/version" + {{- else }} + # For Apache APISIX, check the admin routes endpoint + HEALTH_ENDPOINT="${API7_ADMIN_URL}/apisix/admin/routes" + {{- end }} + while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do - if curl -s -o /dev/null -w "%{http_code}" ${API7_ADMIN_URL}/apisix/admin/routes \ - -H "X-API-KEY: ${API7_ADMIN_KEY}" | grep -q "200\|401"; then - echo "API7 Gateway is ready!" + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" ${HEALTH_ENDPOINT} \ + {{- if eq .Values.api7.backend "apisix" }} + -H "X-API-KEY: ${API7_ADMIN_KEY}" \ + {{- end }} + --max-time 5 || echo "000") + + if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "401" ]; then + echo "API7 Gateway is ready! (HTTP $HTTP_CODE)" break fi - echo "API7 Gateway not ready, retrying... ($RETRY_COUNT/$MAX_RETRIES)" + echo "API7 Gateway not ready (HTTP $HTTP_CODE), retrying... ($RETRY_COUNT/$MAX_RETRIES)" RETRY_COUNT=$((RETRY_COUNT + 1)) sleep 10 done @@ -209,4 +222,4 @@ spec: secret: secretName: {{ .Values.api7.tls.secretName | default (printf "%s-tls" (include "api7ee.fullname" .)) }} {{- end }} -{{- end }} \ No newline at end of file +{{- end }}