APISIX-02-Admin管理接口
模块概览
Admin模块是 APISIX 的管理接口层,提供 RESTful API 用于配置管理。通过 Admin API 可以动态创建、更新、删除所有配置对象,配置秒级生效无需重启。
核心职责
- 提供统一的 REST风格 配置管理接口(GET、POST、PUT、DELETE、PATCH)
- 校验配置 schema,防止非法配置写入
- 管理配置对象:Routes、Services、Upstreams、Consumers、SSL、Plugins、Global Rules等
- 支持 API Key 认证和基于角色的访问控制(admin/viewer)
- 配置数据持久化到 etcd,触发数据面热更新
对外 API清单
- /apisix/admin/routes:路由管理
- /apisix/admin/services:服务管理
- /apisix/admin/upstreams:上游管理
- /apisix/admin/consumers:消费者管理
- /apisix/admin/ssls:SSL证书管理
- /apisix/admin/plugins:插件列表查询
- /apisix/admin/plugin_metadata:插件元数据管理
- /apisix/admin/plugin_configs:插件配置复用
- /apisix/admin/global_rules:全局规则管理
- /apisix/admin/stream_routes:Stream路由管理
- /apisix/admin/consumer_groups:消费者组管理
- /apisix/admin/secrets:密钥管理
- /apisix/admin/schema:Schema查询
认证与授权
- API Key 认证:通过
X-API-KEYheader、?api_key=xxx参数或Cookie传递 - 角色:admin(读写)、viewer(只读)
- 可禁用认证:
admin_key_required: false(开发环境)
监听端口
- 默认端口:9180
- 可配置 HTTPS:
https_admin: true - CORS 支持:
enable_admin_cors: true
模块架构图
flowchart TB
Client[管理员/控制台] -->|HTTP/HTTPS| AdminAPI[Admin API<br/>端口9180]
AdminAPI --> Auth[认证模块<br/>check_token]
Auth -->|验证通过| Router[路由分发<br/>admin/init.lua]
Auth -->|验证失败| Reject[401 Unauthorized]
Router --> Routes[Routes资源<br/>admin/routes.lua]
Router --> Services[Services资源<br/>admin/services.lua]
Router --> Upstreams[Upstreams资源<br/>admin/upstreams.lua]
Router --> Consumers[Consumers资源<br/>admin/consumers.lua]
Router --> SSL[SSL资源<br/>admin/ssl.lua]
Router --> Plugins[Plugins资源<br/>admin/plugins.lua]
Router --> GlobalRules[Global Rules资源<br/>admin/global_rules.lua]
Router --> Others[其他资源...]
subgraph ResourceLayer[资源层]
Routes
Services
Upstreams
Consumers
SSL
Plugins
GlobalRules
Others
end
ResourceLayer --> Resource[通用资源模块<br/>admin/resource.lua]
Resource --> Validate[Schema校验<br/>core.schema.check]
Resource --> Checker[自定义校验<br/>checker函数]
Resource --> Encrypt[敏感数据加密<br/>encrypt_conf]
Resource --> Etcd[(etcd集群)]
Etcd -.->|watch| DataPlane[数据面<br/>APISIX Worker]
style AdminAPI fill:#4A90E2,color:#fff
style Auth fill:#E8F4F8
style Router fill:#FFF4E6
style ResourceLayer fill:#F0F0F0
style Resource fill:#E8F4F8
核心数据结构
1. 请求响应结构
classDiagram
class AdminRequest {
+string method
+string uri
+string X-API-KEY
+object body
+object uri_args
}
class AdminResponse {
+number code
+string X-API-VERSION
+AdminResponseBody body
}
class AdminResponseBody {
+string key
+object value
+number createdIndex
+number modifiedIndex
+string error_msg
}
class AdminListResponse {
+number count
+table list
+string next
}
AdminRequest --> AdminResponse
AdminResponse --> AdminResponseBody
AdminResponse --> AdminListResponse
2. 资源对象 (resource.lua)
classDiagram
class Resource {
+string name
+string kind
+table schema
+function checker
+function encrypt_conf
+table list_filter_fields
+get(resource, id) ResponseBody
+post(resource, id, body) ResponseBody
+put(resource, id, body) ResponseBody
+patch(resource, id, body, sub_path) ResponseBody
+delete(resource, id) ResponseBody
}
class ResourceInstance {
+string name
+table schema
+function checker
}
Resource --> ResourceInstance : creates
Admin API 路由机制
1. 路由表定义
admin/init.lua
local uri_route = {
-- HEAD请求(健康检查)
{
paths = [[/apisix/admin]],
methods = {"HEAD"},
handler = head,
},
-- 通用资源CRUD
{
paths = [[/apisix/admin/*]],
methods = {"GET", "PUT", "POST", "DELETE", "PATCH"},
handler = run,
},
-- 插件列表查询
{
paths = [[/apisix/admin/plugins/list]],
methods = {"GET"},
handler = get_plugins_list,
},
-- Schema校验
{
paths = [[/apisix/admin/schema/validate/*]],
methods = {"POST"},
handler = schema_validate,
},
-- 插件热重载
{
paths = reload_event, -- /apisix/admin/plugins/reload
methods = {"PUT"},
handler = post_reload_plugins,
},
}
2. URI解析规则
URI格式:/apisix/admin/{resource}/{id}/{sub_path}
解析示例
| URI | resource | id | sub_path |
|---|---|---|---|
/apisix/admin/routes/1 |
routes | 1 | - |
/apisix/admin/services/2 |
services | 2 | - |
/apisix/admin/consumers/jack/credentials/key-auth-1 |
credentials | key-auth-1 | jack |
/apisix/admin/schema/plugins/limit-count |
plugins | limit-count | schema |
解析代码
local function run()
local uri_segs = core.utils.split_uri(ngx.var.uri)
-- /apisix/admin/routes/1
-- uri_segs = {"", "apisix", "admin", "routes", "1"}
local seg_res = uri_segs[4] -- "routes"
local seg_id = uri_segs[5] -- "1"
local seg_sub_path = core.table.concat(uri_segs, "/", 6) -- ""
-- 特殊处理:/apisix/admin/schema/plugins/limit-count
if seg_res == "schema" and seg_id == "plugins" then
seg_res = uri_segs[5] -- "plugins"
seg_id = uri_segs[6] -- "limit-count"
seg_sub_path = core.table.concat(uri_segs, "/", 7)
end
-- 特殊处理:/apisix/admin/consumers/jack/credentials/key-auth-1
if seg_res == "consumers" and uri_segs[6] == "credentials" then
seg_sub_path = seg_id .. "/" .. seg_sub_path -- "jack/"
seg_res = uri_segs[6] -- "credentials"
seg_id = uri_segs[7] -- "key-auth-1"
end
-- 获取资源处理器
local resource = resources[seg_res]
if not resource then
return core.response.exit(404, {error_msg = "Unsupported resource type: " .. seg_res})
end
-- 调用资源方法(GET/POST/PUT/DELETE/PATCH)
local method = str_lower(get_method())
local code, data = resource[method](resource, seg_id, req_body, seg_sub_path, uri_args)
core.response.exit(code, data)
end
Routes API 详解
API: 创建路由
基本信息
- 路径:
PUT /apisix/admin/routes/{id} - 方法:PUT
- 认证:需要 admin 角色
- 幂等性:是(相同 ID 覆盖)
请求结构体
{
"uri": "/api/users/*",
"name": "用户API路由",
"desc": "用户管理接口",
"priority": 0,
"methods": ["GET", "POST"],
"host": "api.example.com",
"hosts": ["api.example.com", "*.example.com"],
"remote_addr": "192.168.1.0/24",
"remote_addrs": ["192.168.1.0/24", "10.0.0.0/8"],
"vars": [
["arg_id", "==", "123"]
],
"filter_func": "function(vars) return vars.arg_id == '123' end",
"plugins": {
"limit-count": {
"count": 100,
"time_window": 60,
"rejected_code": 429
},
"key-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:8080": 1,
"127.0.0.1:8081": 2
},
"timeout": {
"connect": 60,
"send": 60,
"read": 60
}
},
"upstream_id": "1",
"service_id": "1",
"plugin_config_id": "1",
"enable_websocket": false,
"status": 1
}
字段说明
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| uri | string | 是* | - | URI匹配模式,支持前缀匹配 /api/* |
| uris | array[string] | 是* | - | 多个URI(与uri二选一) |
| name | string | 否 | - | 路由名称 |
| desc | string | 否 | - | 路由描述 |
| priority | integer | 否 | 0 | 优先级,数值越大优先级越高 |
| methods | array[string] | 否 | - | HTTP方法列表,不填表示匹配所有方法 |
| host | string | 否 | - | 域名匹配 |
| hosts | array[string] | 否 | - | 多个域名(与host二选一) |
| remote_addr | string | 否 | - | 客户端IP或CIDR |
| remote_addrs | array[string] | 否 | - | 多个客户端IP(与remote_addr二选一) |
| vars | array | 否 | - | Nginx变量匹配表达式 |
| filter_func | string | 否 | - | 自定义Lua函数字符串 |
| plugins | object | 否 | - | 插件配置 |
| upstream | object | 否 | - | 上游配置(与upstream_id二选一) |
| upstream_id | string | 否 | - | 上游ID引用 |
| service_id | string | 否 | - | 服务ID引用 |
| plugin_config_id | string | 否 | - | 插件配置ID引用 |
| script | string | 否 | - | 脚本路由 |
| enable_websocket | boolean | 否 | false | 启用WebSocket |
| timeout | object | 否 | - | 超时配置 |
| status | integer | 否 | 1 | 启用状态(1启用,0禁用) |
* uri 和 uris 至少填一个
响应结构体
成功响应(201)
{
"key": "/apisix/routes/1",
"value": {
"id": "1",
"uri": "/api/users/*",
"methods": ["GET", "POST"],
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:8080": 1
}
},
"create_time": 1640000000,
"update_time": 1640000000
}
}
错误响应(400)
{
"error_msg": "invalid configuration: property \"uri\" is required"
}
核心代码:check_conf
admin/routes.lua
local function check_conf(id, conf, need_id, schema, opts)
opts = opts or {}
-- 互斥字段检查
if conf.host and conf.hosts then
return nil, {error_msg = "only one of host or hosts is allowed"}
end
if conf.remote_addr and conf.remote_addrs then
return nil, {error_msg = "only one of remote_addr or remote_addrs is allowed"}
end
-- Schema校验
local ok, err = core.schema.check(schema, conf)
if not ok then
return nil, {error_msg = "invalid configuration: " .. err}
end
-- 校验内联upstream
if conf.upstream then
local ok, err = apisix_upstream.check_upstream_conf(conf.upstream)
if not ok then
return nil, {error_msg = err}
end
end
-- 校验upstream_id引用
if conf.upstream_id and not opts.skip_references_check then
local key = "/upstreams/" .. conf.upstream_id
local res, err = core.etcd.get(key)
if not res or res.status ~= 200 then
return nil, {error_msg = "failed to fetch upstream info by upstream id"}
end
end
-- 校验service_id引用
if conf.service_id and not opts.skip_references_check then
local key = "/services/" .. conf.service_id
local res, err = core.etcd.get(key)
if not res or res.status ~= 200 then
return nil, {error_msg = "failed to fetch service info by service id"}
end
end
-- 校验插件配置
if conf.plugins then
local ok, err = schema_plugin(conf.plugins)
if not ok then
return nil, {error_msg = err}
end
end
-- 校验vars表达式
if conf.vars then
local ok, err = expr.new(conf.vars)
if not ok then
return nil, {error_msg = "failed to validate the 'vars' expression: " .. err}
end
end
-- 校验filter_func
if conf.filter_func then
local func, err = loadstring("return " .. conf.filter_func)
if not func or type(func()) ~= "function" then
return nil, {error_msg = "invalid filter_func"}
end
end
return true
end
调用链
sequenceDiagram
autonumber
participant Client as 客户端
participant AdminAPI as admin/init.lua
participant Routes as admin/routes.lua
participant Resource as admin/resource.lua
participant Schema as core.schema
participant Plugin as plugin模块
participant Upstream as upstream模块
participant Etcd as etcd
Client->>AdminAPI: PUT /apisix/admin/routes/1
AdminAPI->>AdminAPI: check_token()<br/>验证API Key
AdminAPI->>AdminAPI: 解析URI<br/>seg_res="routes", seg_id="1"
AdminAPI->>AdminAPI: 解析请求体<br/>JSON decode
AdminAPI->>Routes: resource.put(resource, "1", body)
Routes->>Resource: resource.put()
Resource->>Routes: checker(id, conf)<br/>check_conf()
Routes->>Routes: 互斥字段检查<br/>host vs hosts
Routes->>Schema: core.schema.check(route_schema, conf)
Schema-->>Routes: ok
Routes->>Upstream: check_upstream_conf(conf.upstream)
Upstream->>Schema: core.schema.check(upstream_schema)
Upstream-->>Routes: ok
Routes->>Etcd: GET /upstreams/1<br/>验证upstream_id引用
Etcd-->>Routes: 200 OK
Routes->>Plugin: schema_plugin(conf.plugins)
Plugin->>Plugin: check_single_plugin_schema("limit-count")
Plugin-->>Routes: ok
Routes-->>Resource: ok
Resource->>Routes: encrypt_conf(id, conf)
Routes->>Routes: 加密upstream.tls.client_key
Routes->>Routes: 加密plugins敏感字段
Resource->>Etcd: PUT /apisix/routes/1<br/>value=conf
Etcd-->>Resource: 200 OK + modifiedIndex
Resource-->>AdminAPI: 201, {key, value}
AdminAPI->>AdminAPI: strip_etcd_resp()<br/>清理etcd元数据
AdminAPI->>AdminAPI: v3_adapter.filter()<br/>API版本适配
AdminAPI-->>Client: 201 Created
Note over Etcd: === 数据面自动更新 ===
Etcd->>DataPlane: watch event (PUT /apisix/routes/1)
DataPlane->>DataPlane: filter(route)<br/>预处理配置
DataPlane->>DataPlane: 重建radixtree路由树
使用示例
示例1:创建基础路由
curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d '{
"uri": "/api/users",
"methods": ["GET"],
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:8080": 1
}
}
}'
示例2:创建带插件的路由
curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/2 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d '{
"uri": "/api/users/*",
"methods": ["GET", "POST", "PUT", "DELETE"],
"plugins": {
"limit-count": {
"count": 100,
"time_window": 60,
"key_type": "var",
"key": "remote_addr"
},
"key-auth": {},
"prometheus": {}
},
"upstream_id": "1"
}'
示例3:创建带vars匹配的路由
curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/3 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d '{
"uri": "/api/users/*",
"vars": [
["arg_version", "==", "v2"]
],
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:8082": 1
}
}
}'
API: 查询路由列表
基本信息
- 路径:
GET /apisix/admin/routes - 方法:GET
- 认证:需要 admin 或 viewer 角色
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| page | integer | 否 | 页码(从1开始) |
| page_size | integer | 否 | 每页数量 |
响应结构体
{
"list": [
{
"key": "/apisix/routes/1",
"value": {
"id": "1",
"uri": "/api/users",
"methods": ["GET"],
"upstream": {...},
"create_time": 1640000000,
"update_time": 1640000000
},
"modifiedIndex": 123
},
{
"key": "/apisix/routes/2",
"value": {...},
"modifiedIndex": 124
}
],
"count": 2
}
使用示例
# 查询所有路由
curl http://127.0.0.1:9180/apisix/admin/routes \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1"
# 分页查询
curl "http://127.0.0.1:9180/apisix/admin/routes?page=1&page_size=10" \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1"
API: 查询单个路由
基本信息
- 路径:
GET /apisix/admin/routes/{id} - 方法:GET
响应结构体
{
"key": "/apisix/routes/1",
"value": {
"id": "1",
"uri": "/api/users",
"methods": ["GET"],
"upstream": {...},
"plugins": {...},
"create_time": 1640000000,
"update_time": 1640000000
},
"modifiedIndex": 123
}
使用示例
curl http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1"
API: 更新路由(PATCH)
基本信息
- 路径:
PATCH /apisix/admin/routes/{id} - 方法:PATCH
- 说明:部分更新,仅修改指定字段
请求结构体
{
"methods": ["GET", "POST", "PUT"],
"plugins": {
"limit-count": {
"count": 200
}
}
}
核心代码:PATCH实现
function _M.patch(resource, id, conf, sub_path)
-- 获取现有配置
local key = "/" .. resource.name .. "/" .. id
local res, err = core.etcd.get(key)
if not res or res.status ~= 200 then
return 404, {error_msg = "route not found"}
end
local old_conf = res.body.node.value
-- 合并配置
if sub_path and sub_path ~= "" then
-- 更新嵌套字段:PATCH /routes/1/plugins/limit-count
local sub_keys = core.utils.split_uri(sub_path)
local target = old_conf
for i = 1, #sub_keys - 1 do
target = target[sub_keys[i]]
end
target[sub_keys[#sub_keys]] = conf
else
-- 更新顶层字段
for k, v in pairs(conf) do
old_conf[k] = v
end
end
-- 校验合并后的配置
local ok, err = resource.checker(id, old_conf)
if not ok then
return 400, err
end
-- 写入etcd
local res, err = core.etcd.atomic_set(key, old_conf, nil, res.body.node.modifiedIndex)
if not res then
return 503, {error_msg = "failed to update route: " .. err}
end
return 200, {key = key, value = old_conf}
end
使用示例
# 更新插件配置
curl -X PATCH http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d '{
"plugins": {
"limit-count": {
"count": 200,
"time_window": 60
}
}
}'
# 更新嵌套字段
curl -X PATCH http://127.0.0.1:9180/apisix/admin/routes/1/plugins/limit-count \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d '{
"count": 300
}'
API: 删除路由
基本信息
- 路径:
DELETE /apisix/admin/routes/{id} - 方法:DELETE
- 幂等性:是(重复删除返回200)
响应结构体
{
"deleted": "1",
"key": "/apisix/routes/1"
}
使用示例
curl -X DELETE http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1"
Services API 详解
API: 创建服务
基本信息
- 路径:
PUT /apisix/admin/services/{id} - 方法:PUT
请求结构体
{
"name": "用户服务",
"desc": "用户管理微服务",
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:8080": 1,
"127.0.0.1:8081": 1
}
},
"plugins": {
"limit-count": {
"count": 1000,
"time_window": 60
}
},
"enable_websocket": false
}
字段说明
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 否 | 服务名称 |
| desc | string | 否 | 服务描述 |
| upstream | object | 否 | 上游配置(与upstream_id二选一) |
| upstream_id | string | 否 | 上游ID引用 |
| plugins | object | 否 | 插件配置 |
| enable_websocket | boolean | 否 | 启用WebSocket |
| hosts | array[string] | 否 | 域名列表 |
使用场景
Service 用于抽象通用配置,可被多个 Route 引用:
# 1. 创建Service
curl -X PUT http://127.0.0.1:9180/apisix/admin/services/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d '{
"upstream": {
"type": "roundrobin",
"nodes": {"127.0.0.1:8080": 1}
},
"plugins": {
"limit-count": {"count": 100, "time_window": 60}
}
}'
# 2. 创建Route引用Service
curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d '{
"uri": "/api/users",
"service_id": "1"
}'
# 3. Route可以覆盖Service的插件
curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/2 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d '{
"uri": "/api/orders",
"service_id": "1",
"plugins": {
"limit-count": {"count": 50, "time_window": 60}
}
}'
Upstreams API 详解
API: 创建上游
请求结构体
{
"name": "用户服务集群",
"desc": "用户服务的上游节点",
"type": "roundrobin",
"nodes": [
{"host": "127.0.0.1", "port": 8080, "weight": 1, "priority": 0},
{"host": "127.0.0.1", "port": 8081", "weight": 2, "priority": 0},
{"host": "127.0.0.1", "port": 8082", "weight": 1, "priority": -1}
],
"scheme": "http",
"hash_on": "vars",
"key": "remote_addr",
"retries": 2,
"retry_timeout": 0,
"timeout": {
"connect": 60,
"send": 60,
"read": 60
},
"keepalive_pool": {
"size": 320,
"idle_timeout": 60,
"requests": 1000
},
"pass_host": "pass",
"upstream_host": "api.example.com",
"service_name": "user-service",
"discovery_type": "consul",
"checks": {
"active": {
"type": "http",
"http_path": "/health",
"timeout": 1,
"healthy": {
"interval": 5,
"successes": 2
},
"unhealthy": {
"interval": 5,
"http_failures": 3
}
},
"passive": {
"healthy": {
"http_statuses": [200, 201],
"successes": 3
},
"unhealthy": {
"http_statuses": [500, 502, 503, 504],
"http_failures": 3
}
}
}
}
字段说明
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| type | string | 是 | 负载均衡类型(roundrobin/chash/ewma/least_conn) |
| nodes | array[object] | 是* | 节点列表(与service_name二选一) |
| service_name | string | 是* | 服务发现服务名 |
| discovery_type | string | 否 | 服务发现类型(consul/eureka/nacos/kubernetes) |
| hash_on | string | 否 | 哈希键类型(vars/header/cookie/consumer) |
| key | string | 否 | 哈希键名称 |
| scheme | string | 否 | 协议(http/https/grpc/grpcs) |
| retries | integer | 否 | 重试次数 |
| timeout | object | 否 | 超时配置 |
| checks | object | 否 | 健康检查配置 |
| pass_host | string | 否 | Host传递策略(pass/rewrite/node) |
使用示例
示例1:静态节点
curl -X PUT http://127.0.0.1:9180/apisix/admin/upstreams/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d '{
"type": "roundrobin",
"nodes": [
{"host": "127.0.0.1", "port": 8080, "weight": 1}
]
}'
示例2:服务发现(Consul)
curl -X PUT http://127.0.0.1:9180/apisix/admin/upstreams/2 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d '{
"service_name": "user-service",
"discovery_type": "consul",
"type": "roundrobin"
}'
示例3:一致性哈希
curl -X PUT http://127.0.0.1:9180/apisix/admin/upstreams/3 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d '{
"type": "chash",
"hash_on": "header",
"key": "User-ID",
"nodes": [
{"host": "127.0.0.1", "port": 8080, "weight": 1}
]
}'
Consumers API 详解
API: 创建消费者
请求结构体
{
"username": "jack",
"desc": "用户Jack",
"plugins": {
"key-auth": {
"key": "auth-key-jack"
},
"limit-count": {
"count": 200,
"time_window": 60,
"rejected_code": 429
}
},
"group_id": "developer"
}
字段说明
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| username | string | 是 | 消费者用户名(唯一) |
| desc | string | 否 | 描述 |
| plugins | object | 是 | 认证插件配置(至少一个认证插件) |
| group_id | string | 否 | 消费者组ID |
使用示例
# 1. 创建Consumer
curl -X PUT http://127.0.0.1:9180/apisix/admin/consumers \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d '{
"username": "jack",
"plugins": {
"key-auth": {
"key": "auth-key-jack"
}
}
}'
# 2. 在Route启用key-auth插件
curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d '{
"uri": "/api/users",
"plugins": {
"key-auth": {}
},
"upstream_id": "1"
}'
# 3. 使用API Key访问
curl http://127.0.0.1:9080/api/users \
-H "apikey: auth-key-jack"
SSL API 详解
API: 创建SSL证书
请求结构体
{
"cert": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
"key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----",
"snis": ["api.example.com", "*.example.com"],
"client": {
"ca": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
"depth": 1,
"skip_mtls_uri_regex": ["/health", "/metrics"]
},
"ssl_protocols": ["TLSv1.2", "TLSv1.3"],
"type": "server"
}
字段说明
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| cert | string | 是 | 服务器证书(PEM格式) |
| key | string | 是 | 服务器私钥(PEM格式) |
| snis | array[string] | 是 | SNI列表,支持泛域名 |
| client | object | 否 | 客户端证书验证配置(mTLS) |
| ssl_protocols | array[string] | 否 | TLS协议版本 |
| type | string | 否 | 证书类型(server/client) |
使用示例
curl -X PUT http://127.0.0.1:9180/apisix/admin/ssls/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
--data-raw '{
"cert": "'"$(cat server.crt)"'",
"key": "'"$(cat server.key)"'",
"snis": ["api.example.com"]
}'
最佳实践
1. 配置对象设计模式
模式1:Route直接配置(简单场景)
# 适用于:单一路由,配置简单
curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/1 \
-d '{
"uri": "/api/users",
"upstream": {
"type": "roundrobin",
"nodes": {"127.0.0.1:8080": 1}
}
}'
模式2:Service复用(通用配置)
# 1. 创建Service(通用插件和上游)
curl -X PUT http://127.0.0.1:9180/apisix/admin/services/1 \
-d '{
"upstream_id": "1",
"plugins": {"limit-count": {"count": 100, "time_window": 60}}
}'
# 2. 多个Route引用同一Service
curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/1 \
-d '{"uri": "/api/users", "service_id": "1"}'
curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/2 \
-d '{"uri": "/api/orders", "service_id": "1"}'
模式3:Upstream独立管理(多路由共享)
# 1. 创建Upstream(可被多个Route/Service引用)
curl -X PUT http://127.0.0.1:9180/apisix/admin/upstreams/1 \
-d '{
"type": "roundrobin",
"nodes": {"127.0.0.1:8080": 1},
"checks": {...} # 健康检查配置
}'
# 2. 多个Route引用
curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/1 \
-d '{"uri": "/api/users", "upstream_id": "1"}'
模式4:Plugin Config复用(插件配置)
# 1. 创建Plugin Config
curl -X PUT http://127.0.0.1:9180/apisix/admin/plugin_configs/1 \
-d '{
"plugins": {
"cors": {...},
"limit-count": {...},
"prometheus": {}
}
}'
# 2. Route引用Plugin Config
curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/1 \
-d '{"uri": "/api/users", "plugin_config_id": "1", "upstream_id": "1"}'
2. 批量操作
场景:批量创建多个路由
#!/bin/bash
for i in {1..10}; do
curl -X PUT "http://127.0.0.1:9180/apisix/admin/routes/$i" \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d "{
\"uri\": \"/api/service$i/*\",
\"upstream_id\": \"1\"
}"
done
3. 配置版本管理
使用modifiedIndex乐观锁
# 1. 获取当前配置和版本号
res=$(curl -s http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: xxx")
modified_index=$(echo $res | jq -r '.modifiedIndex')
# 2. 基于版本号更新(CAS操作)
curl -X PUT "http://127.0.0.1:9180/apisix/admin/routes/1?ttl=0" \
-H "X-API-KEY: xxx" \
-H "If-Match: $modified_index" \
-d '{...}'
4. 安全加固
4.1 修改Admin API Key
# config.yaml
deployment:
admin:
admin_key:
- name: admin
key: "your-secret-admin-key-here" # 修改为强密码
role: admin
- name: viewer
key: "your-secret-viewer-key-here"
role: viewer
4.2 限制Admin API访问来源
# config.yaml
deployment:
admin:
allow_admin:
- 127.0.0.1/24
- 10.0.0.0/8
4.3 启用HTTPS
# config.yaml
deployment:
admin:
https_admin: true
admin_listen:
port: 9180
admin_api_mtls:
admin_ssl_cert: "/path/to/admin-cert.pem"
admin_ssl_cert_key: "/path/to/admin-key.pem"
时序图:Admin API请求处理流程
sequenceDiagram
autonumber
participant Client as 客户端/Dashboard
participant Nginx as Nginx
participant AdminInit as admin/init.lua
participant Resource as admin/resource.lua
participant Schema as core.schema
participant Etcd as etcd
participant DataPlane as 数据面Worker
Client->>Nginx: PUT /apisix/admin/routes/1
Nginx->>AdminInit: http_admin()
AdminInit->>AdminInit: set_ctx_and_check_token()
AdminInit->>AdminInit: 创建api_ctx
AdminInit->>AdminInit: check_token(api_ctx)
alt API Key不存在
AdminInit-->>Client: 401 Unauthorized<br/>"missing apikey"
end
alt API Key错误
AdminInit-->>Client: 401 Unauthorized<br/>"wrong apikey"
end
alt Viewer角色使用PUT/DELETE
AdminInit-->>Client: 401 Unauthorized<br/>"invalid method for role viewer"
end
AdminInit->>AdminInit: split_uri(ngx.var.uri)
AdminInit->>AdminInit: 解析 resource, id, sub_path
AdminInit->>AdminInit: get_body(MAX_REQ_BODY)
AdminInit->>AdminInit: json.decode(req_body)
AdminInit->>Resource: routes.put(resource, "1", body)
Resource->>Resource: checker(id, body)
Resource->>Schema: core.schema.check(route_schema, body)
Schema-->>Resource: ok
Resource->>Resource: 校验upstream_id引用
Resource->>Etcd: GET /apisix/upstreams/1
Etcd-->>Resource: 200 OK
Resource->>Resource: 校验service_id引用
Resource->>Resource: 校验plugins配置
Resource->>Resource: 校验vars表达式
alt 校验失败
Resource-->>AdminInit: 400, {error_msg}
AdminInit-->>Client: 400 Bad Request
end
Resource->>Resource: encrypt_conf(id, body)
Resource->>Resource: 加密敏感字段
Resource->>Etcd: PUT /apisix/routes/1<br/>value=body
Etcd-->>Resource: 200 OK<br/>modifiedIndex=124
Resource->>Resource: 构建响应<br/>{key, value, modifiedIndex}
Resource-->>AdminInit: 201, response_data
AdminInit->>AdminInit: strip_etcd_resp(data)
AdminInit->>AdminInit: 移除etcd元数据
AdminInit->>AdminInit: v3_adapter.filter(data)
AdminInit->>AdminInit: set_header("X-API-VERSION", "v2")
AdminInit-->>Client: 201 Created<br/>{key, value}
Note over Etcd,DataPlane: === 配置自动同步到数据面 ===
Etcd->>DataPlane: watch event<br/>(PUT /apisix/routes/1)
DataPlane->>DataPlane: filter(route)<br/>预处理配置
DataPlane->>DataPlane: checker(route)<br/>校验配置
DataPlane->>DataPlane: routes.values["1"] = route
DataPlane->>DataPlane: 重建radixtree路由树
DataPlane->>DataPlane: routes.conf_version++
Note over DataPlane: 下一个请求立即使用新配置
本文档完整覆盖了 APISIX Admin API 的架构、所有核心接口的详细说明、请求响应结构、调用链、使用示例和最佳实践,为通过 Admin API 管理 APISIX 配置提供了完整的参考。