Skip to content

Kong — 云原生 API 网关

架构概览

Kong 是基于 Nginx + OpenResty(Lua)构建的高性能 API 网关,支持插件化扩展。

Client ──► Kong Gateway ──► Upstream Services

         Plugin Chain:
           ├── Authentication(JWT/OAuth2/Key Auth)
           ├── Rate Limiting(限流)
           ├── Logging(日志)
           ├── Caching(缓存)
           └── Transformations(请求/响应转换)

         Data Store:
           ├── PostgreSQL(传统模式)
           └── DB-less(声明式配置)

部署模式

模式说明适用场景
传统模式配置存 PostgreSQL,Admin API 动态管理中大型团队
DB-less 模式声明式 YAML/JSON 配置,无数据库依赖K8s/GitOps
混合模式Control Plane(CP)+ Data Plane(DP)分离大规模生产
KonnectSaaS 托管 CP云原生

核心概念

Service(服务):上游服务的抽象
  └── Route(路由):匹配规则(Host/Path/Method)
        └── Plugin(插件):附加在 Route/Service/Consumer 上

Consumer(消费者):API 调用方身份
  └── Credential(凭证):API Key / JWT / OAuth Token

基础配置

创建 Service 和 Route

bash
# 创建 Service
curl -X POST http://localhost:8001/services \
  -d name=order-service \
  -d url=http://order-service:8080

# 创建 Route
curl -X POST http://localhost:8001/services/order-service/routes \
  -d name=order-route \
  -d 'paths[]=/api/orders' \
  -d 'methods[]=GET' \
  -d 'methods[]=POST' \
  -d strip_path=false

# 验证
curl http://localhost:8000/api/orders

声明式配置(DB-less)

yaml
# kong.yaml
_format_version: "3.0"

services:
  - name: order-service
    url: http://order-service:8080
    routes:
      - name: order-route
        paths:
          - /api/orders
        methods:
          - GET
          - POST
    plugins:
      - name: rate-limiting
        config:
          minute: 100
          hour: 1000
          policy: local

  - name: user-service
    url: http://user-service:8080
    routes:
      - name: user-route
        paths:
          - /api/users

consumers:
  - username: mobile-app
    keyauth_credentials:
      - key: my-api-key-123

常用插件

认证插件

Key Authentication

bash
# 启用插件
curl -X POST http://localhost:8001/services/order-service/plugins \
  -d name=key-auth \
  -d config.key_names=X-API-Key \
  -d config.hide_credentials=true

# 创建 Consumer 和 Key
curl -X POST http://localhost:8001/consumers -d username=mobile-app
curl -X POST http://localhost:8001/consumers/mobile-app/key-auth -d key=my-secret-key

# 调用时携带 Key
curl -H "X-API-Key: my-secret-key" http://localhost:8000/api/orders

JWT 认证

bash
# 启用 JWT 插件
curl -X POST http://localhost:8001/services/order-service/plugins \
  -d name=jwt

# 创建 Consumer 的 JWT 凭证
curl -X POST http://localhost:8001/consumers/mobile-app/jwt \
  -d algorithm=HS256 \
  -d secret=my-jwt-secret

# 生成 JWT Token(payload 必须包含 iss=key)
# Header: {"alg":"HS256","typ":"JWT"}
# Payload: {"iss":"<key>","exp":1234567890}

限流插件

bash
curl -X POST http://localhost:8001/services/order-service/plugins \
  -d name=rate-limiting \
  -d config.minute=60 \
  -d config.hour=1000 \
  -d config.day=10000 \
  -d config.policy=redis \
  -d config.redis_host=redis \
  -d config.redis_port=6379 \
  -d config.limit_by=consumer  # 按 Consumer 限流

请求转换插件

bash
# 添加请求头
curl -X POST http://localhost:8001/services/order-service/plugins \
  -d name=request-transformer \
  -d 'config.add.headers[]=X-Service-Name:kong-gateway' \
  -d 'config.add.headers[]=X-Request-ID:$(uuid)' \
  -d 'config.remove.headers[]=Authorization'  # 移除敏感头

# 响应转换
curl -X POST http://localhost:8001/services/order-service/plugins \
  -d name=response-transformer \
  -d 'config.add.headers[]=X-Powered-By:Kong'

熔断插件(Circuit Breaker)

bash
curl -X POST http://localhost:8001/services/order-service/plugins \
  -d name=request-termination \
  -d config.status_code=503 \
  -d config.message="Service temporarily unavailable"

# 更完整的熔断:使用 proxy-cache + 自定义 Lua 插件

Kong Ingress Controller(K8s)

yaml
# IngressClass
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: kong
spec:
  controller: ingress-controllers.konghq.com/kong

---
# Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: order-ingress
  annotations:
    konghq.com/strip-path: "true"
    konghq.com/plugins: rate-limit,jwt-auth
spec:
  ingressClassName: kong
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /orders
            pathType: Prefix
            backend:
              service:
                name: order-service
                port:
                  number: 8080

---
# KongPlugin CRD
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: rate-limit
plugin: rate-limiting
config:
  minute: 100
  policy: local

灰度发布

bash
# 创建两个 Upstream(v1 和 v2)
curl -X POST http://localhost:8001/upstreams -d name=order-upstream

# 添加 v1 目标(权重 90)
curl -X POST http://localhost:8001/upstreams/order-upstream/targets \
  -d target=order-v1:8080 \
  -d weight=90

# 添加 v2 目标(权重 10,灰度 10%)
curl -X POST http://localhost:8001/upstreams/order-upstream/targets \
  -d target=order-v2:8080 \
  -d weight=10

故障处理案例

案例一:上游服务超时

现象:Kong 返回 504 Gateway Timeout。

排查

bash
# 查看 Kong 错误日志
tail -f /usr/local/kong/logs/error.log

# 检查 Service 超时配置
curl http://localhost:8001/services/order-service

解决

bash
# 调整超时配置
curl -X PATCH http://localhost:8001/services/order-service \
  -d connect_timeout=5000 \
  -d write_timeout=60000 \
  -d read_timeout=60000

案例二:限流误杀正常请求

现象:正常用户请求被限流(429 Too Many Requests)。

排查

bash
# 查看限流计数(Redis 模式)
redis-cli keys "kong:rate-limiting:*"
redis-cli get "kong:rate-limiting:consumer:mobile-app:minute"

解决

  • 调整限流阈值
  • 改为按 Consumer 限流(而非按 IP)
  • 使用 sliding 窗口算法(更平滑)

案例三:PostgreSQL 连接耗尽

现象:Kong 启动慢,Admin API 响应超时。

解决

bash
# 调整 Kong 数据库连接池
# kong.conf
pg_pool_size = 30
pg_backlog = 100
pg_timeout = 5000

监控

bash
# Kong 暴露 Prometheus 指标(需启用插件)
curl -X POST http://localhost:8001/plugins \
  -d name=prometheus

# 访问指标
curl http://localhost:8001/metrics
指标说明
kong_http_requests_total请求总数(按状态码)
kong_latency_ms请求延迟(Kong 处理 + 上游)
kong_bandwidth_bytes流量字节数
kong_upstream_target_health上游健康状态

PaaS 中间件生态系统深度学习文档