Skip to main content

Apache APISIX

  • apache/apisix
    • Apache-2.0, Lua+Nginx/openresty+etcd
    • 支持 Golang 插件
    • 支持协议: HTTP, GRPC, Dubbo, MQTT
    • 也可以存储在 yaml - 但不可以编辑
      • config_center 配置
  • Admin API
    • Auth X-API-KEY: admin-ley
    • PUT 为新增
    • /apisix/admin/<资源>
      • routes, stream_routes, services, consumers, upstreams, ssl, global_rules,
      • plugin_configs, plugin_metadata
    • 信息
      • /apisix/admin/plugins/list
      • /apisix/admin/plugins/{plugin_name}
  • 参考
# 官方建议自行构建
# APISIX_VERSION=2.9 make build-on-alpine-cn
# apache/apisix:2.9-alpine
# 带 build 逻辑的 compose
# https://github.com/apache/apisix-docker/raw/master/example/docker-compose-alpine.yml

# make build-all-in-one
docker run -d \
-p 9080:9080 -p 9091:9091 -p 2379:2379 \
-v $PWD/all-in-one/apisix/config.yaml:/usr/local/apisix/conf/config.yaml \
apache/apisix:whole

# make build-dashboard
docker run -d \
-p 19080:9080 -p 19091:9091 -p 12379:2379 -p 19000:9000 \
-v $(pwd)/all-in-one/apisix/config.yaml:/usr/local/apisix/conf/config.yaml \
-v $(pwd)/all-in-one/apisix-dashboard/conf.yaml:/usr/local/apisix-dashboard/conf/conf.yaml \
apache/apisix-dashboard:whole
prometheus port 9091
plugin_attr:
prometheus:
export_addr:
ip: '0.0.0.0'
port: 9091

基本概念

  • Route/路由
    • =uri+plugins+upstream/service_id
  • Service/服务 - 路由集合
    • plugins+upstream
  • Upstream/上游
    • nodes
  • PubSub - 只支持 Kafka
  • xRPC - stream_routes - 实现 L4 代理转发
    • 内置 redis 协议 - 可植入错误
    • 可用于实现自定义协议
  • 外部插件
  • 预定义变量

服务发现

  • 通过 upstream.service_name 匹配使用, 发现的内容作为 nodes
  • 管理接口 /v1/discovery/{discovery_type}/dump
  • consule_kv
  • dns
  • eureka
  • nacos
  • tars
  • apisix/discovery/
  • kubernetes
    • 发现服务的 endpoints
discovery:
kubernetes:
service:
schema: https # https,http
host: ${KUBERNETES_SERVICE_HOST}
port: ${KUBERNETES_SERVICE_PORT}

# 如果在集群外运行 需要配置客户端信息
client:
token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
#token: |- # 静态 Token

# 选择生效的 namespace
namespace_selector:
# 匹配方式 equal, not_equal, match, not_match
# 值可以是数组
equal: default

# 通过 label 选择生效服务
label_selector: |-
first="a",second="b"

路由

{
"plugins": {
"key-auth": {},
// 限定针对 consumer 生效
"consumer-restriction": {
"blacklist": ["jack"]
}
},
"upstream": {
// grpc,grpcs
"schema": "http",
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/hello"
}

插件

  • 无服务器架构
  • 可观测性
  • 其它协议
    • mqtt-proxy - 基于 client_id 负载

通用

  • batch-requests
  • redirect - 重定向
    http_to_https: false # 与 url,regex_uri 三选一
    url: '' # 目标地址
    regex_uri: [] # 正则替换
    ret_code: 302 # HTTP 状态码
    encode_uri: false
    append_query_string: false
  • echo - 回显结果 - 用于测试
    before_body: ''
    body: ''
    after_body: ''
    headers: {}
  • gzip
  • real-ip
  • server-info - 向 ETCD 上报服务信息
    • 在配置中启用 conf/config.yaml
    • report_ttl=36 - 单位秒
    • 可请求 http://127.0.0.1:9090/v1/server_info
  • ext-plugin-pre-req - 前置外部插件
    # 插件和它的配置
    conf: [{ 'name': 'ext-plugin-A', 'value': '{"enable":"feature"}' }]
    allow_degradation: false
  • ext-plugin-post-req - 后置外部插件

传输

  • response-rewrite
  • proxy-rewrite
  • grpc-transcode
    # 上传 PB POST {"content":""} /admin/proto/{id}
    # 合并 proto protoc --include_imports --descriptor_set_out=proto.pb proto/helloworld.proto
    prodo_id: ""
    service: ""
    method: ""
    deadline: 0
    # enum_as_name, enum_as_value
    # int64_as_number, int64_as_string, int64_as_hexstring
    # auto_default_values, no_default_values, use_default_values, use_default_metatable
    # enable_hooks, disable_hooks
    pb_option: []
  • grpc-web
  • fault-injection
  • mocking

身份验证

  • key-auth
    • Consumer - 定义 消费者的 Token
      • key
    • Route - 定义获取 key 的方式
      • header = apikey
      • query = apikey
      • hide_credentials = false - 是否透传给 upstream
  • jwt-auth
    • Consumer
      • key
  • basic-auth
    • Consumer
      • username
      • password
    • Router
      • hide_credentials
  • authz-keycloak - OIDC 认证逻辑+Keycloak 授权判断逻辑
# 🌟 推荐设置自动发现,减少配置量
discovery: # <endpoint>/.well-known/uma2-configuration
token_endpoint:
resource_registration_endpoint:
client_id:
client_secret:
grant_type: urn:ietf:params:oauth:grant-type:uma-ticket
policy_enforcement_mode: ENFORCING # PERMISSIVE
# 一般格式为 资源名#scope名
permissions: []
# 加载针对资源的权限 - 需要让插件能请求 token - 因此需要 client_id 和 client_secret
lazy_load_paths: false
http_method_as_scope: false # 一般配合 lazy_load_paths 使用
timeout: 3000
access_token_expires_in: 300
access_token_expires_leeway: 0
refresh_token_expires_in: 3600
refresh_token_expires_leeway: 0
ssl_verify: true
cache_ttl_seconds: 86400 # 24h - 缓存 发现配置
keepalive: true
keepalive_timeout: 60000
keepalive_pool: 5
# 默认返回 {"error_description":"not_authorized"}
access_denied_redirect_uri:
# 配置后可使用 POST username+password 获取 token
password_grant_token_generation_incoming_uri:
  • forward-auth
  • openid-connect - OIDC 认证
  • authz-casdoor
  • wolf-rbac
  • hmac-auth
  • authz-casbin - 从文件加载 casbin 配置进行验证
  • ldap-auth
  • opa

安全防护

  • cors
  • uri-blocker
  • ip-restriction
  • ua-restriction
  • referer-restriction
  • consumer-restriction
  • csrf
  • public-api - 暴露插件里的接口
    • uri
  • consumer-restriction - 限定 consumer
    # consumer_name - 限定 consumer 访问 service, route
    # service_id,route_id - 在 consumer 上定义, 限定访问 service,route
    type: consumer_name
    whitelist: []
    blacklist: []
    rejected_code: 403
    rejected_code: ""
    allowed_by_methods: [] # 允许的 HTTP 方法

流量控制

  • limit-req - leaky bucket
  • limit-conn - 限定连接数
  • limit-count - 限定时间范围内请求
  • proxy-cache
    cache_strategy: disk # memory
    cache_zone: disk_cache_one
    cache_key: ['$host', '$request_uri'] # ["$host", "$uri", "-cache-id"]
    cache_bypass: []
    cache_method: ['GET', 'HEAD']
    cache_http_status: [200, 301, 404]
    hide_cache_headers: false
    cache_control: false
    no_cache: []
    cache_ttl: 300
  • request-validation - JSON Schema 校验
  • proxy-mirror
  • api-breaker - 熔断
  • traffic-split
  • request-id
    header_name: X-Request-Id
    include_in_response: true
    algorithm: uuid # snowflake, nanoid
  • proxy-control
  • client-control
    max_body_size: 0 # 控制最大 body

GraphQL

  • 暴露变量用于路由
    • graphql_operation - query, mutation
    • graphql_name, graphql_root_fields
{
"methods": ["POST"],
"uri": "/_graphql",
"vars": [
["graphql_operation", "==", "query"],
["graphql_name", "==", "getRepo"],
["graphql_root_fields", "has", "owner"]
],
"upstream": {
"type": "roundrobin",
"nodes": {
"192.168.1.200:4000": 1
}
}
}

Helm

IngressController

  • CRD ApisixRoute, ApisixUpstream ApisixTls ApisixClusterConfig ApisixConsumer
apiVersion: apisix.apache.org/v2beta3
kind: ApisixRoute
metadata:
name: httpbin-route
spec:
http:
- name: rule1
match:
hosts:
- httpbin.com
paths:
- /ip
backends:
- serviceName: httpbin-service-e2e-test
servicePort: 80