Data Team MICKong Gateway es un API Gateway open-source nativo en la nube. Gestiona enrutamiento, autenticación, rate limiting y observabilidad de servicios internos (FastAPI, Trino REST, PostgreSQL, Airflow). Conecta directamente con los clientes y protege los microservicios backend.
Kong corre en contenedor Docker:
Clientes externos / Internos
↓
Kong Gateway (proxy)
↓
┌───────┬───────┬────────┐
↓ ↓ ↓ ↓
FastAPI Trino PostgreSQL Airflow
(Data) (SQL) (Ops) (Orch)
| Componente | URL | Puerto |
|---|---|---|
| Kong Proxy | ||
| Admin API | ||
| Metrics/Status | — |
# Health check desde cliente
curl -i <tu-url>/status
# Debería retornar JSON con DB connection status
# {
# "database": {"reachable": true},
# "server": {...}
# }
Un Servicio en Kong apunta al backend real (ej: FastAPI app en <tu-url>)
# Crear servicio
curl -X POST <tu-url>/services \
-H "Content-Type: application/json" \
-d '{
"name": "data-api",
"url": "<tu-url>",
"port": "<puerto>",
"protocol": "http",
"host": "<tu-url>"
}'
# Respuesta: devuelve ID del servicio
# {
# "id": "abc-123-def",
# "name": "data-api",
# ...
# }
Una Ruta define cómo llega la solicitud externa a Kong y a qué Servicio redirige.
# Crear ruta: /api/data/* → servicio data-api
curl -X POST <tu-url>/services/data-api/routes \
-H "Content-Type: application/json" \
-d '{
"name": "data-api-route",
"paths": ["/api/data"],
"methods": ["GET", "POST", "PUT", "DELETE"],
"strip_path": true,
"preserve_host": false
}'
# Resultado:
# Cliente → <tu-url>/api/data/tables
# ↓ (Kong redirige eliminando /api/data)
# <tu-url>/tables
Opciones importantes:
| Opción | Descripción |
|---|---|
paths |
Rutas que Kong escucha (ej: /api/data, /tables) |
methods |
HTTP methods permitidos (GET, POST, etc.) |
strip_path |
Si true, elimina el path de Kong en redireccion |
preserve_host |
Si true, mantiene header Host original |
Requerir API Key para acceder a una ruta:
# 1. Crear Consumer (usuario/app que accede)
curl -X POST <tu-url>/consumers \
-d "username=analytics-app"
# 2. Agregar credencial (API Key)
curl -X POST <tu-url>/consumers/analytics-app/key-auth \
-d "key=super-secret-key-12345"
# 3. Activar plugin en la ruta
curl -X POST <tu-url>/routes/data-api-route/plugins \
-H "Content-Type: application/json" \
-d '{"name": "key-auth"}'
# Cliente ahora debe enviar:
curl -H "apikey: super-secret-key-12345" <tu-url>/api/data/tables
Permitir requests desde dominios externos (Superset, dashboards):
curl -X POST <tu-url>/routes/data-api-route/plugins \
-H "Content-Type: application/json" \
-d '{
"name": "cors",
"config": {
"origins": ["<tu-url>", "<tu-url>"],
"methods": ["GET", "POST", "OPTIONS"],
"allow_headers": ["Content-Type", "Authorization"],
"credentials": true
}
}'
Limitar requests por segundo/minuto:
curl -X POST <tu-url>/routes/data-api-route/plugins \
-H "Content-Type: application/json" \
-d '{
"name": "rate-limiting",
"config": {
"second": 100,
"minute": 10000,
"policy": "local"
}
}'
# Resultado:
# analytics-app está limitado a 100 req/seg y 10000 req/min
# Si excede → retorna HTTP 429 Too Many Requests
Modificar headers o body de requests/responses:
# Agregar header personalizado a todas las respuestas
curl -X POST <tu-url>/routes/data-api-route/plugins \
-H "Content-Type: application/json" \
-d '{
"name": "response-transformer",
"config": {
"add": {
"headers": ["X-API-Version:1.0", "X-Powered-By:Kong"]
}
}
}'
# O modificar body antes de enviar al backend
curl -X POST <tu-url>/routes/data-api-route/plugins \
-H "Content-Type: application/json" \
-d '{
"name": "request-transformer",
"config": {
"add": {
"headers": ["X-Request-ID:<valor-generado>"]
}
}
}'
Registrar todas las requests/responses:
curl -X POST <tu-url>/routes/data-api-route/plugins \
-H "Content-Type: application/json" \
-d '{
"name": "file-log",
"config": {
"path": "/var/log/kong/api-data.log"
}
}'
# Ver logs
docker logs dataskills-hub 2>&1 | grep "api-data.log"
Alternativa: usar HTTP Log para enviar logs a servidor externo:
curl -X POST <tu-url>/routes/data-api-route/plugins \
-H "Content-Type: application/json" \
-d '{
"name": "http-log",
"config": {
"http_endpoint": "<tu-url>/logs"
}
}'
# Listar todos los consumers
curl <tu-url>/consumers
# Crear consumer (aplicación o usuario)
curl -X POST <tu-url>/consumers \
-d "username=fastapi-processor" \
-d "custom_id=app-001"
# Ver credentials de un consumer
curl <tu-url>/consumers/fastapi-processor
# Eliminar consumer
curl -X DELETE <tu-url>/consumers/fastapi-processor
Un Consumer puede tener varias formas de autenticarse:
# Key Auth (API Key)
curl -X POST <tu-url>/consumers/fastapi-processor/key-auth \
-d "key=key-12345"
# Basic Auth (usuario:contraseña en base64)
curl -X POST <tu-url>/consumers/fastapi-processor/basic-auth \
-d "username=fastapi" \
-d "password=secure-password"
# OAuth2
curl -X POST <tu-url>/consumers/fastapi-processor/oauth2 \
-d "client_id=oauth-app-1" \
-d "client_secret=secret-123" \
-d "redirect_uris=<tu-url>/callback"
# Health status detallado
curl <tu-url>/status | jq .
# Resultado típico:
# {
# "database": {"reachable": true},
# "server": {"connections_accepted": 1250, ...}
# }
# Servicios
curl <tu-url>/services | jq '.data[] | {name, url}'
# Rutas
curl <tu-url>/routes | jq '.data[] | {name, paths, methods}'
# Plugins
curl <tu-url>/plugins | jq '.data[] | {name, service_id}'
Habilitar logging detallado para diagnosticar:
# Agregar verbose logging a toda ruta
curl -X POST <tu-url>/services/data-api/plugins \
-H "Content-Type: application/json" \
-d '{
"name": "request-size-limiting",
"config": {
"allowed_payload_size": 128 # 128 MB max
}
}'
# Test de ruta con verbose
curl -v -H "apikey: super-secret-key-12345" <tu-url>/api/data/tables
| Código | Significado | Solución |
|---|---|---|
| 404 | Ruta no encontrada | Verificar paths en route config |
| 401 | No autorizado | Revisar credenciales/plugin auth |
| 429 | Rate limit excedido | Esperar o aumentar límite |
| 502 | Backend no responde | Verificar servicio backend online |
| 503 | Kong sin conexión a DB | Revisar Docker / conectividad |
| Componente | Patrón | Ejemplo |
|---|---|---|
| Nombre Servicio | <app>-<función>-api |
data-processor-api |
| Ruta externa | /api/<v>/< recurso> |
/api/v1/tables |
| Consumer name | <nombre-app> |
analytics-consumer |
| Plugin scope | Aplicar a nivel ruta/svc | Específico, no global |
Recomendaciones por tipo de consumer:
| Tipo | req/seg | req/min | Caso de uso |
|---|---|---|---|
| Internal API | 1000 | 500000 | Apps de plataforma |
| Data Extract | 100 | 10000 | Superset, dashboards |
| Public API | 10 | 1000 | Clientes externos |
| Development | 50 | 5000 | Apps en desarrollo |
Buenas prácticas:
✓ Usar Key Auth para servicios internos (FastAPI, Trino)
✓ Rotar keys cada 90 días
✓ Almacenar keys en .env del cliente, NO en código
✓ Usar diferentes keys por entorno (dev, staging, prod)
✓ Revocar keys cuando app o persona se desactiva
Ejemplo en FastAPI cliente:
# .env
KONG_API_KEY=sk-data-12345-abc
# main.py
import os
from httpx import Client
client = Client(
base_url="<tu-url>",
headers={"apikey": os.getenv("KONG_API_KEY")}
)
response = client.get("/api/v1/tables")