一、apisix介绍
APISIX 是一个微服务API网关,具有高性能、可扩展性等优点。它基于 nginx(openresty)和 Lua 实现功能,借鉴了Kong的思路,将Kong底层的关系型数据库(Postgres)替换成了NoSQL型的 etcd,这使得 APISIX 相较于 Kong 在性能上有了很大提升,在启用各类插件的情况下,Apache APISIX 的性能据说是 Kong 的 10 倍,极具吸引力。
且相较于 Kong 来说,源码更为简洁,二次开发难度更低,但是相对的,开源时间较短,在插件功能完备性上不如Kong,比如缺少关于灰度相关的插件,但是其已纳入Apache 基金会孵化,社区也较为活跃,后期的发展空间较为可观。
和传统的API网关相比,APISIX 和 Kong 一样也是通过插件的形式来提供负载均衡、日记记录、身份鉴权、流量控制等功能。
apisix更多的介绍可参考官网:
https://apisix.apache.org/
https://apisix.apache.org/zh/docs/apisix/getting-started
这里主要介绍apisix的api,apisix其它功能,在此不多加介绍。
、apisix环境搭建
# 二、apisix安装
apisix可以很容易的安装在eks、k8s等之上,在此我基于docker-compose的方式进行搭建,便于后续api功能的尝试,具体的安装步骤见下链接:
https://apisix.apache.org/zh/docs/apisix/getting-started
安装完成后,基本环境见下截图:
图中可以看出:除了安装完成apisix之外,还额外安装了两个demo:web1和web2,以及grafana和apisix dashboard。
访问apisix dashboard:
http://192.168.13.210:9000/routes/list
我们可以在apisix dashboard上配置或创建:router、upstream、service、plugin、consumer等资源,在此我只介绍通过apisix api的方式进行资源的相关操作。
三、apisix admin api官网解释
https://apisix.apache.org/zh/docs/apisix/admin-api
官网的上诉链接对apisix admin api的解释足够详细,在此不再赘述。
四、apisix admin api实际使用
4.1、环境介绍
ip | port | 备注 |
---|---|---|
192.168.13.210 | 9081 | web1 |
192.168.13.210 | 9082 | web2 |
192.168.13.220 | 9080 | apisix admin api port |
4.2、一个完整的例子
4.2.1、添加upstream
# 生产环境中,建议使用post,由系统自动生成upstream_id,防止put时覆盖掉已有的upstream_id。
curl "http://127.0.0.1:9080/apisix/admin/upstreams" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X POST -d '
{
"type": "roundrobin",
"nodes": {
"192.168.13.210:9082": 1
},
"scheme": "http",
"name": "web2-upstream",
"desc": "web2 upstream"
}'
4.2.2、获取添加的upstream的upstream_id
[root@kafka-01 apache-apisix-sample]# curl http://127.0.0.1:9080/apisix/admin/upstreams -X GET -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1"
{"count":1,"node":{"nodes":[{"value":{"type":"roundrobin","hash_on":"vars","desc":"web2 upstream","scheme":"http","id":"00000000000000000065","create_time":1652780907,"update_time":1652780907,"nodes":{"192.168.13.210:9082":1},"pass_host":"pass","name":"web2-upstream"},"modifiedIndex":66,"createdIndex":66,"key":"\/apisix\/upstreams\/00000000000000000065"}],"dir":true,"key":"\/apisix\/upstreams"},"action":"get"}
upstream_id为:00000000000000000065。
4.2.3、添加route
curl "http://127.0.0.1:9080/apisix/admin/routes" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X POST -d '
{
"methods": ["GET"],
"name": "web2-route",
"host": "web2.com",
"desc": "web2 route",
"uri": "/*",
"upstream_id": "00000000000000000065"
}'
解释:
这条路由配置意味着,当它们满足下述的所有规则时,所有匹配的入站请求都将被转发到192.168.13.210:9082这个上游服务:
1、请求的 HTTP 方法为 GET
2、请求头包含 host 字段,且它的值为web2.com
3、请求路径匹配 /*,* 意味着任意的子路径
4.2.4、测试
[root@kafka-01 apache-apisix-sample]# curl http://127.0.0.1:9080 -X GET -H "Host: web2.com"
hello web2
结果为:hello web2即为成功
4.3、patch
基于上面4.2对其进行修改
4.3.1 upstream添加node
curl "http://127.0.0.1:9080/apisix/admin/upstreams/00000000000000000065" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PATCH -d '
{
"nodes": {
"192.168.13.210:9081": 1
}
}'
测试:
curl http://127.0.0.1:9080 -X GET -H "Host: web2.com",结果为:
hello web1
hello web2
hello web1
hello web2
4.3.2 upstream修改node
curl "http://127.0.0.1:9080/apisix/admin/upstreams/00000000000000000065" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PATCH -d '
{
"nodes": {
"192.168.13.210:9081": 2 # 修改了权重
}
}'
测试:
curl http://127.0.0.1:9080 -X GET -H "Host: web2.com",结果为:
hello web1
hello web2
hello web1
4.3.3 upstream删除node
curl "http://127.0.0.1:9080/apisix/admin/upstreams/00000000000000000065" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PATCH -d '
{
"nodes": {
"192.168.13.210:9081": null
}
}'
curl http://127.0.0.1:9080 -X GET -H "Host: web2.com",结果为:
hello web2
hello web2
hello web2
4.3.4、upstream替换node
curl "http://127.0.0.1:9080/apisix/admin/upstreams/00000000000000000065/nodes" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PATCH -d '
{
"192.168.13.21:9081": 1
}'
curl http://127.0.0.1:9080 -X GET -H "Host: web2.com",结果为:
502
4.4、service
地址:/apisix/admin/services/{id}
说明:Service 是某类 API 的抽象(也可以理解为一组 Route 的抽象)。它通常与上游服务抽象是一一对应的,Route 与 Service 之间,通常是 N:1 的关系。
4.4.1、一个例子
4.4.1.1、创建upstream
curl "http://127.0.0.1:9080/apisix/admin/upstreams" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X POST -d '
{
"type": "roundrobin",
"nodes": {
"192.168.13.210:9081": 1
},
"scheme": "http",
"name": "web1-service-upstream",
"desc": "web1 service upstream"
}'
4.4.1.2、创建service
curl "http://127.0.0.1:9080/apisix/admin/services" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X POST -d '
{
"name": "web1-service",
"desc": "web1 service",
"upstream_id": "00000000000000000075" # 4.3.1.1中创建的upstream的upstream_id
}'
4.4.1.3、添加一组<两个路由>
# 路由1
curl "http://127.0.0.1:9080/apisix/admin/routes" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X POST -d '
{
"methods": ["GET"],
"name": "web1-service-route-01",
"host": "web1-service-route-01.com",
"desc": "web1 service route 01",
"uri": "/*",
"service_id": "408127894154379971" # 4.3.1.2中创建的serivice的service_id
}'
# 路由2
curl "http://127.0.0.1:9080/apisix/admin/routes" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X POST -d '
{
"methods": ["GET"],
"name": "web1-service-route-02",
"host": "web1-service-route-02.com",
"desc": "web1 service route 02",
"uri": "/*",
"service_id": "408127894154379971"
}'
4.4.1.4、验证
# Host: web1-service-route-01.com
[root@kafka-01 apache-apisix-sample]# curl http://127.0.0.1:9080 -X GET -H "Host: web1-service-route-01.com"
hello web1
# Host: web1-service-route-02.com
[root@kafka-01 apache-apisix-sample]# curl http://127.0.0.1:9080 -X GET -H "Host: web1-service-route-02.com"
hello web1
4.5、认证<authentication>
4.5.1、key-auth
# 官网文档
https://apisix.apache.org/zh/docs/apisix/plugins/key-auth
4.5.1.1、创建consumer
curl "http://127.0.0.1:9080/apisix/admin/consumers" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PUT -d '
{
"username": "zhangsan",
"plugins": {
"key-auth": {
"key": "key-for-zhangsan"
}
}
}'
4.5.1.2、将consumer绑定到route
# 在4.2.3中我们已经创建了一个route:web2-route,在此我将zhangsan这个consumer绑定到这个肉特上面
确认route:web2-route的route_id
curl http://127.0.0.1:9080/apisix/admin/routes -X GET -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1"
得到web2-route的route_id为:00000000000000000067
绑定route:
curl "http://127.0.0.1:9080/apisix/admin/routes/00000000000000000067" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PATCH -d '
{
"plugins": {
"key-auth": {}
}
}'
4.5.1.3 验证
[root@kafka-01 apache-apisix-sample]# curl http://127.0.0.1:9080 -X GET -H "Host: web2.com" -H "apikey: key-for-zhangsan"
hello web1
4.5.2 jwt-auth
4.5.2.1、简介
`jwt-auth` 是一个认证插件,它需要与 `consumer` 一起配合才能工作。
添加 JWT Authentication 到一个 `service` 或 `route`。 然后 `consumer` 将其密钥添加到查询字符串参数、请求头或 `cookie` 中以验证其请求。
有关 JWT 的更多信息,可参考 [JWT](https://jwt.io/) 查看更多信息。
`jwt-auth` 插件可以与 HashiCorp Vault 集成,用于存储和获取密钥,从其加密的 KV 引擎获取 RSA 密钥对。 阅读下面的 [例子](https://apisix.apache.org/zh/docs/apisix/plugins/jwt-auth#enable-jwt-auth-with-vault-compatibility) 来了解它如何工作。
4.5.2.2、consumer端属性
4.5.2.3、router端属性
4.5.2.4、创建consumer
在4.4.1中,我们创建了一个service:web1-service,并且绑定了两个路由:web1-service-route-01、web1-service-route-02,在此我以这个service为例,配置jwt-auth认证插件。
curl "http://127.0.0.1:9080/apisix/admin/consumers" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PUT -d '
{
"username": "jwt_auth_consumer",
"desc": "jwt-auth consumer",
"plugins": {
"jwt-auth": {
"algorithm": "HS256",
"exp": 86400,
"key": "jwt-auth-consumer-key",
"secret": "jwt-auth-consumer-secret"
}
}
}'
4.5.2.5、service中开启jwt-auth认证
# 查看service的service_id
curl http://127.0.0.1:9080/apisix/admin/services -X GET -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1"
得到service:web1-service的service_id为:408127894154379971
# 使用patch修改web1-service增加plugin
curl "http://127.0.0.1:9080/apisix/admin/services/408127894154379971" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PATCH -d '
{
"plugins": {
"jwt-auth": {}
}
}'
4.5.2.6、暴露sign接口
访问接口,要先生成token,生成token的接口我们需要使用public-api的方式进行暴露:
https://apisix.apache.org/zh/docs/apisix/plugins/public-api/
# 暴露接口
curl "http://127.0.0.1:9080/apisix/admin/routes/jas" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PUT -d '
{
"methods": ["GET", "POST"],
"name": "public-api-route",
"desc": "expose jwt-auth public api",
"uri": "/apisix/plugin/jwt/sign",
"plugins": {
"public-api": {}
}
}'
4.5.2.7、生成token
[root@kafka-01 apache-apisix-sample]# curl http://127.0.0.1:9080/apisix/plugin/jwt/sign?key=jwt-auth-consumer-key -i
HTTP/1.1 200 OK
Date: Wed, 18 May 2022 05:11:27 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: APISIX/2.13.1
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NTI5MzcwODcsImtleSI6Imp3dC1hdXRoLWNvbnN1bWVyLWtleSJ9.nsiHJ7XZQLackjZQELAiyundsFZJzdhy1dFLpcQZ1d4
4.5.2.8、验证
不带token:
# web1-service-route-01.com
[root@kafka-01 apache-apisix-sample]# curl http://127.0.0.1:9080/ -H "Host: web1-service-route-01.com" -i -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1"
结果为:
HTTP/1.1 401 Unauthorized
Date: Wed, 18 May 2022 05:16:20 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: APISIX/2.13.1
{"message":"Missing JWT token in request"}
# web1-service-route-02.com
[root@kafka-01 apache-apisix-sample]# curl http://127.0.0.1:9080/ -H "Host: web1-service-route-02.com" -i -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1"
结果为:
HTTP/1.1 401 Unauthorized
Date: Wed, 18 May 2022 05:16:14 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: APISIX/2.13.1
{"message":"Missing JWT token in request"}
带token
# web1-service-route-01.com
[root@kafka-01 apache-apisix-sample]# curl http://127.0.0.1:9080/ -H "Host: web1-service-route-01.com" -i -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -H "Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NTI5MzcwODcsImtleSI6Imp3dC1hdXRoLWNvbnN1bWVyLWtleSJ9.nsiHJ7XZQLackjZQELAiyundsFZJzdhy1dFLpcQZ1d4"
结果为:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 10
Connection: keep-alive
Date: Wed, 18 May 2022 05:12:42 GMT
Server: APISIX/2.13.1
hello web1
# web1-service-route-02.com
[root@kafka-01 apache-apisix-sample]# curl http://127.0.0.1:9080/ -H "Host: web1-service-route-02.com" -i -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -H "Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NTI5MzcwODcsImtleSI6Imp3dC1hdXRoLWNvbnN1bWVyLWtleSJ9.nsiHJ7XZQLackjZQELAiyundsFZJzdhy1dFLpcQZ1d4"
结果为:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 10
Connection: keep-alive
Date: Wed, 18 May 2022 05:14:34 GMT
Server: APISIX/2.13.1
hello web1