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-KEY header、?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 配置提供了完整的参考。