Kaique Mitsuo Silva Yamamoto
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

ConceitoDescricao
ServiceUpstream API/microservico
RouteRegra de roteamento para um service
ConsumerUsuario/aplicacao que consome APIs
PluginExtensao de funcionalidade
UpstreamBalanceamento 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=true

Configuracao via Admin API

Criar Service

curl -X POST http://localhost:8001/services \
  -d name=my-api \
  -d url=http://api-backend:3000

Criar 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[]=POST

Criar Consumer

curl -X POST http://localhost:8001/consumers \
  -d username=mobile-app

Kong 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: 80

KongPlugin 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: 3600

Plugins 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: true

JWT 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:
    - bearer

Rate 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: false

Request 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: true

Logging

# 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: true

Plugins Customizados (Lua)

Estrutura

my-plugin/
├── handler.lua
└── schema.lua

handler.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 MyPlugin

schema.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-upstream

Health 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: 3

Decl (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

Recursos