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)分离 | 大规模生产 |
| Konnect | SaaS 托管 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/ordersJWT 认证:
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 | 上游健康状态 |