Arquitetura software
Kong API Gateway
Kong e um API Gateway e plataforma de microservicos que fornece gerenciamento de trafego, seguranca, observabilidade e extensibilidade.
Conceitos Principais
| Conceito | Descricao |
|---|---|
| Service | Upstream API/microservico |
| Route | Regra de roteamento para um service |
| Consumer | Usuario/aplicacao que consome APIs |
| Plugin | Extensao de funcionalidade |
| Upstream | Balanceamento de carga |
Instalacao
Docker
# docker-compose.yml
version: '3.8'
services:
kong-database:
image: postgres:15
environment:
POSTGRES_USER: kong
POSTGRES_DB: kong
POSTGRES_PASSWORD: kong
volumes:
- kong_data:/var/lib/postgresql/data
kong-migration:
image: kong:3.5
command: kong migrations bootstrap
environment:
KONG_DATABASE: postgres
KONG_PG_HOST: kong-database
KONG_PG_USER: kong
KONG_PG_PASSWORD: kong
depends_on:
- kong-database
kong:
image: kong:3.5
environment:
KONG_DATABASE: postgres
KONG_PG_HOST: kong-database
KONG_PG_USER: kong
KONG_PG_PASSWORD: kong
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_ADMIN_LISTEN: 0.0.0.0:8001
ports:
- "8000:8000" # Proxy
- "8443:8443" # Proxy SSL
- "8001:8001" # Admin API
- "8444:8444" # Admin SSL
depends_on:
- kong-migration
volumes:
kong_data:Kubernetes (Helm)
helm repo add kong https://charts.konghq.com
helm install kong kong/kong \
--set ingressController.installCRDs=false \
--set proxy.type=LoadBalancer \
--set admin.enabled=true \
--set admin.http.enabled=trueConfiguracao via Admin API
Criar Service
curl -X POST http://localhost:8001/services \
-d name=my-api \
-d url=http://api-backend:3000Criar Route
curl -X POST http://localhost:8001/services/my-api/routes \
-d name=my-api-route \
-d paths[]=/api/v1 \
-d methods[]=GET \
-d methods[]=POSTCriar Consumer
curl -X POST http://localhost:8001/consumers \
-d username=mobile-appKong Ingress Controller (Kubernetes)
Service e Ingress
apiVersion: v1
kind: Service
metadata:
name: my-api
annotations:
konghq.com/plugins: rate-limiting,cors
spec:
ports:
- port: 80
targetPort: 3000
selector:
app: my-api
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-api
annotations:
konghq.com/strip-path: "true"
spec:
ingressClassName: kong
rules:
- host: api.example.com
http:
paths:
- path: /v1
pathType: Prefix
backend:
service:
name: my-api
port:
number: 80KongPlugin CRD
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: rate-limiting
plugin: rate-limiting
config:
minute: 100
policy: local
---
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: cors
plugin: cors
config:
origins:
- "https://app.example.com"
methods:
- GET
- POST
- PUT
- DELETE
headers:
- Authorization
- Content-Type
credentials: true
max_age: 3600Plugins Essenciais
Autenticacao
Key Authentication
# Habilitar plugin
curl -X POST http://localhost:8001/services/my-api/plugins \
-d name=key-auth
# Criar API key para consumer
curl -X POST http://localhost:8001/consumers/mobile-app/key-auth \
-d key=my-secret-key# Kubernetes
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: key-auth
plugin: key-auth
config:
key_names:
- apikey
- X-API-Key
hide_credentials: trueJWT Authentication
curl -X POST http://localhost:8001/services/my-api/plugins \
-d name=jwt
# Criar credenciais JWT
curl -X POST http://localhost:8001/consumers/mobile-app/jwt \
-d algorithm=RS256 \
-d rsa_public_key="-----BEGIN PUBLIC KEY-----..."OAuth 2.0 / OIDC
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: oidc
plugin: openid-connect
config:
issuer: https://keycloak.example.com/realms/myrealm
client_id: kong
client_secret: ${OIDC_CLIENT_SECRET}
scopes:
- openid
- profile
auth_methods:
- bearerRate Limiting
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: rate-limiting
plugin: rate-limiting
config:
second: 10
minute: 100
hour: 1000
policy: redis
redis_host: redis
redis_port: 6379
fault_tolerant: true
hide_client_headers: falseRequest Transformer
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: request-transformer
plugin: request-transformer
config:
add:
headers:
- "X-Request-ID:$(uuid)"
- "X-Forwarded-Service:my-api"
remove:
headers:
- "X-Internal-Header"
rename:
headers:
- "Authorization:X-Original-Auth"Response Transformer
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: response-transformer
plugin: response-transformer
config:
add:
headers:
- "X-Kong-Proxy:true"
remove:
headers:
- "Server"
- "X-Powered-By"Prometheus (Metricas)
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: prometheus
plugin: prometheus
config:
status_code_metrics: true
latency_metrics: true
bandwidth_metrics: true
upstream_health_metrics: trueLogging
# HTTP Log
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: http-log
plugin: http-log
config:
http_endpoint: http://logstash:8080
method: POST
content_type: application/json
flush_timeout: 2
retry_count: 3
---
# File Log
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: file-log
plugin: file-log
config:
path: /var/log/kong/requests.log
reopen: truePlugins Customizados (Lua)
Estrutura
my-plugin/
├── handler.lua
└── schema.luahandler.lua
local MyPlugin = {
PRIORITY = 1000,
VERSION = "1.0.0",
}
function MyPlugin:access(conf)
-- Executado em cada request
local request_id = kong.request.get_header("X-Request-ID")
if not request_id then
request_id = kong.tools.uuid()
kong.service.request.set_header("X-Request-ID", request_id)
end
kong.log.info("Processing request: ", request_id)
-- Validacao customizada
if conf.require_auth then
local auth_header = kong.request.get_header("Authorization")
if not auth_header then
return kong.response.exit(401, { message = "Unauthorized" })
end
end
end
function MyPlugin:header_filter(conf)
-- Modificar headers da resposta
kong.response.set_header("X-Plugin-Version", self.VERSION)
end
function MyPlugin:log(conf)
-- Executado apos a resposta
local latency = kong.response.get_latency()
kong.log.info("Request completed in ", latency, "ms")
end
return MyPluginschema.lua
local typedefs = require "kong.db.schema.typedefs"
return {
name = "my-plugin",
fields = {
{ consumer = typedefs.no_consumer },
{ protocols = typedefs.protocols_http },
{ config = {
type = "record",
fields = {
{ require_auth = { type = "boolean", default = true } },
{ custom_header = { type = "string", default = "X-Custom" } },
{ allowed_ips = { type = "array", elements = { type = "string" } } },
},
},
},
},
}Load Balancing
Upstream e Targets
# Criar upstream
curl -X POST http://localhost:8001/upstreams \
-d name=my-api-upstream
# Adicionar targets
curl -X POST http://localhost:8001/upstreams/my-api-upstream/targets \
-d target=api-1:3000 \
-d weight=100
curl -X POST http://localhost:8001/upstreams/my-api-upstream/targets \
-d target=api-2:3000 \
-d weight=100
# Configurar service para usar upstream
curl -X PATCH http://localhost:8001/services/my-api \
-d host=my-api-upstreamHealth Checks
apiVersion: configuration.konghq.com/v1
kind: KongIngress
metadata:
name: health-check
upstream:
healthchecks:
active:
healthy:
interval: 5
successes: 2
unhealthy:
interval: 5
http_failures: 3
http_path: /health
timeout: 3
passive:
healthy:
successes: 5
unhealthy:
http_failures: 3Decl (Declarative Config)
# kong.yml
_format_version: "3.0"
_transform: true
services:
- name: my-api
url: http://api-backend:3000
routes:
- name: my-api-route
paths:
- /api/v1
strip_path: true
plugins:
- name: rate-limiting
config:
minute: 100
- name: key-auth
consumers:
- username: mobile-app
keyauth_credentials:
- key: my-secret-key
- username: web-app
keyauth_credentials:
- key: another-secret-key
plugins:
- name: prometheus
config:
status_code_metrics: true# Aplicar configuracao
kong config db_import kong.yml
# Ou modo DB-less
export KONG_DATABASE=off
export KONG_DECLARATIVE_CONFIG=/path/to/kong.yml