kong 网关简介,基本使用说明

创作人 Leo


编辑时间 Wed May 20,2020 at 17:42


简介

kong 网关提供了路由,熔断,服务降级等基本功能,通过官方插件可以实现更加高级的功能,比如服务鉴权,跨域功能,还可以通过开发插件实现更加高级的功能
kong 通过反向代理的形式提供 gateway 服务;流量首先经过 kong 网关,kong 通过 serveice + router + plugins 对流量进行处理,最后转发到目标服务(或者直接拒绝访问目标服务)

安装: docker 安装

虽然 docker 安装比较简单,但是不利于后面开发自定义插件,这里介绍在 mac 本机环境安装:

  1. 首先安装 PostgreSQL

  2. brew 安装 kong

    $ brew tap kong/kong  
    $ brew install kong
    
  3. 将 brew 下载好的 kong 和 openresty 的 bin 目录挂载到 PATH(如果之前安装过 nginx 最好卸载掉,openresty 兼容 nginx)

  4. 进入 PostgreSQL 管理界面双击一个实例,进入命令行后执行 CREATE USER kong; CREATE DATABASE kong OWNER kong;

  5. 执行 kong migrations bootstrap

  6. kong start

  7. 浏览器输入 http://localhost:8001 确定 kong 启动成功

参考: mac 安装

角色

service 一个 service 即为一个 kong 网关反向代理的服务
routes 指定请求如何到达目标服务(或者直接拦截,禁止到达目标服务),一个 service 会有多个 routes
Consumers 代表终端用户,通过 Consumers 层控制哪些用户能够到达目标服务
Kong Manager 网页 kong 管理工具(仅企业版)
Admin API RESTful API 形式的管理工具
Plugins 插件,通过 Plugins 可以扩展 kong 的功能。例如: key-auth plugin 可以通过检测 access key 限制 api 访问;kong 提供了很多扩展功能,包括 access control, caching, rate limiting, logging 等,管理员也可以根据需求自己用 lua 编写 plugin

alt 角色图示

常用系统插件

Rate Limiting plugin 限制一段时间内 http 请求数量(服务限流)
Rate Limiting Advanced plugin 通过请求头和服务进一步限制(仅企业版)

Proxy Caching plugin 反代内容缓存,同 nginx Reverse Proxy with Caching Proxy Caching Advanced plugin 支持 redis

Key Auth plugin 通过检测 access key 限制 api 访问
Key Auth - Encrypted plugin 可以将加密后的 access key 保存到 kong 的内置数据

Load Balancing 负载均衡

User Authorization (RBAC) RBAC 鉴权机制(仅企业版)

Developer Portal (仅企业版)

开始之前

目标:
将 kong.localstudy.com 的请求通过 kong 网关进行代理,最终路由到 inner-1.localstudy.com
也就是说 kong.localstudy.com 是我们 app 的对外域名,inner-1.localstudy.com 是我们保护起来的真正服务

首先创建一个本地测试服务 inner-1.localstudy.com
并且将 kong.localstudy.com 反带到 kong 的代理端口(实际线上程序可以考虑将 kong 代理直接端口设置为 80,让 dns 直接定位到 kong 服务)

修改 nginx 配置

$ cat /usr/local/etc/nginx/servers/localstudy.com 
server {
    listen 80;
    server_name inner-1.localstudy.com;
    root /Users/xxx/Documents/Sites/kongtest;
    include conf.d/php.conf;
    index index.html index.php index.phtml;
}
server {
    listen 80;
    server_name kong.localstudy.com kong2.localstudy.com kong3.localstudy.com;
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
    }
}

修改 /etc/hosts

$ cat /etc/hosts
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1	localhost
255.255.255.255	broadcasthost
::1             localhost

127.0.0.1 kong.localstudy.com kong2.localstudy.com kong3.localstudy.com
127.0.0.1 inner-1.localstudy.com

注意:
如果 docker 安装的,由于 docker 跟外部使用虚拟ip进行通信,所以代理服务 inner-1.localstudy.com 不能设置 127.0.0.1,可以设置为局域网地址

docker 安装查看错误日志

docker logs kong

基本操作

Kong 网关在 8001 端口(默认)提供 RESTful Admin API,用来提供 Services、Routes 管理(增删改查)

通过 RESTful API (8001 端口) 添加一个服务

$ curl -i -X POST http://127.0.0.1:8001/services \
>  --data name=test_service \
>  --data url='http://inner-1.localstudy.com'
HTTP/1.1 201 Created
Date: Fri, 15 May 2020 06:52:10 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/2.0.4
Content-Length: 301
X-Kong-Admin-Latency: 202

{"host":"inner-1.localstudy.com","created_at":1589525530,"connect_timeout":60000,"id":"5a5887ae-4cf9-44bd-b9e6-181453867439","protocol":"http","name":"test_service","read_timeout":60000,"port":80,"path":null,"updated_at":1589525530,"retries":5,"write_timeout":60000,"tags":null,"client_certificate":null}
$ 

name:应该具有唯一性,代表该服务的名字
url:需要 kong upstream 的 host

删除服务

leoismac2:servers bitz$ curl -i -X DELETE http://127.0.0.1:8001/services/test_service
HTTP/1.1 204 No Content
Date: Sat, 16 May 2020 02:55:33 GMT
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/2.0.4
X-Kong-Admin-Latency: 59

查询所有服务

$ curl "http://127.0.0.1:8001/services"
{"next":null,"data":[{"host":"inner-1.localstudy.com","created_at":1589525530,"connect_timeout":60000,"id":"5a5887ae-4cf9-44bd-b9e6-181453867439","protocol":"http","name":"test_service","read_timeout":60000,"port":80,"path":null,"updated_at":1589525530,"retries":5,"write_timeout":60000,"tags":null,"client_certificate":null}]}

查询单个服务

$ curl "http://127.0.0.1:8001/services/test_service"
{"host":"inner-1.localstudy.com","created_at":1589525530,"connect_timeout":60000,"id":"5a5887ae-4cf9-44bd-b9e6-181453867439","protocol":"http","name":"test_service","read_timeout":60000,"port":80,"path":null,"updated_at":1589525530,"retries":5,"write_timeout":60000,"tags":null,"client_certificate":null}
$ curl "http://127.0.0.1:8001/services/5a5887ae-4cf9-44bd-b9e6-181453867439"
{"host":"inner-1.localstudy.com","created_at":1589525530,"connect_timeout":60000,"id":"5a5887ae-4cf9-44bd-b9e6-181453867439","protocol":"http","name":"test_service","read_timeout":60000,"port":80,"path":null,"updated_at":1589525530,"retries":5,"write_timeout":60000,"tags":null,"client_certificate":null}

有了服务,必须至少要有一个路由,才能让kong转发
配置一个 router 将指定 host 和指定 uri 的请求定位到我们刚刚新建的 service

设置路由

$ curl -i -X POST http://127.0.0.1:8001/services/test_service/routes \
>   --data 'name=test_route' \
>   --data 'paths=/'
HTTP/1.1 201 Created
Date: Sat, 16 May 2020 03:24:38 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/2.0.4
Content-Length: 428
X-Kong-Admin-Latency: 16

{"id":"e945c2d4-0393-4e5b-8fdb-d5807a2b8d0b","path_handling":"v0","paths":["\/"],"destinations":null,"headers":null,"protocols":["http","https"],"methods":null,"snis":null,"service":{"id":"2c0e7685-bdc1-4800-ad83-bf6faad6c06f"},"name":"test_route","strip_path":true,"preserve_host":false,"regex_priority":0,"updated_at":1589599478,"sources":null,"hosts":null,"https_redirect_status_code":426,"tags":null,"created_at":1589599478}

修改路由

$ curl -i -X PATCH http://127.0.0.1:8001/services/test_service/routes/test_route \
>   --data 'name=test_route' \
>   --data 'hosts=kong.localstudy.com' \
>   --data 'paths=/' \
>   --data "preserve_host=false" \
>   --data "strip_path=false" 
HTTP/1.1 200 OK
Date: Sat, 16 May 2020 03:32:12 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/2.0.4
Content-Length: 448
X-Kong-Admin-Latency: 12

{"id":"e945c2d4-0393-4e5b-8fdb-d5807a2b8d0b","path_handling":"v0","paths":["\/"],"destinations":null,"headers":null,"protocols":["http","https"],"methods":null,"snis":null,"service":{"id":"2c0e7685-bdc1-4800-ad83-bf6faad6c06f"},"name":"test_route","strip_path":false,"preserve_host":false,"regex_priority":0,"updated_at":1589599932,"sources":null,"hosts":["kong.localstudy.com"],"https_redirect_status_code":426,"tags":null,"created_at":1589599478}

参数说明:

name :路由名称
hosts :匹配 http 头 Host 为该值的请求
paths :匹配路径

preserve_host : 使用访问 kong 时提供的host
设 kong.localstudy.com 为请求 kong 的 host
设 inner-1.localstudy.com 为目标服务的 host(这个 host 需要在创建 service 时提供给 kong)
设置为 true :在代理到目标服务时,kong 会将请求 host 设置为 kong.localstudy.com
设置为 false :kong 会将请求 host 设置为 inner-1.localstudy.com,也就是我们在 service 创建时提供的 host

strip_path :将匹配到的 path 前缀切除
设路由为 /mock
设置为true,请求 /mock/data,发送到实际服务时 /data
设置为false,请求 /mock/data,发送到实际服务时 /mock/data

删除路由

$ curl -i -X DELETE http://127.0.0.1:8001/services/test_service/routes/test_route
HTTP/1.1 204 No Content
Date: Sat, 16 May 2020 03:23:55 GMT
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/2.0.4
X-Kong-Admin-Latency: 12

插件 plugin

官方插件集 kong hub

官方提供了很多好用的插件,这些插件按照功能分组为:

AUTHENTICATION 验证类
basic、HMAC、JWT、Key Auth、LDAP、OAuth 2.0、Session

SECURITY 安全类
ACME、Bot Detection(机器人发现)、CORS 跨域、IP Restriction ip黑白名单

TRAFFIC CONTROL 流量控制
ACL 鉴权、Proxy Cache 为通用请求响应提供缓存服务、Rate Limiting 限流、Request Size Limiting 阻止大于指定大小的请求、Request Termination 为所有请求提供一个指定的相应、Response Rate Limiting 通过相应头进行限流

更多信息可以通过访问插件集了解,还有很多企业级的和第三方提供的没有列出来
下面通过配置访问限流介绍插件的基本使用

Rate Limiting 限流

为什么限制用户访问频次
1. 防止服务过载
2. 可以限制服务总量
3. 限制每个用户或指定用户一段时间的请求数

注意:该插件仅部分兼容 DB-Less 模式

为了测试先配置一个路由

curl -i -X POST http://127.0.0.1:8001/services/test_service/routes \
  --data 'name=test_route_d' \
  --data 'hosts=kong.localstudy.com' \
  --data 'paths=/mock' \
  --data "preserve_host=false" \
  --data "strip_path=false" 

配置限流

$ curl -i -X POST http://127.0.0.1:8001/plugins \
> --data "name=rate-limiting" \
> --data "service.id=2c0e7685-bdc1-4800-ad83-bf6faad6c06f" \
> --data "route.id=f1f9e227-7e3e-4e53-aaac-87c5014ee557" \
> --data "config.minute=2" \
> --data "config.limit_by=consumer" \
> --data "config.policy=local"
HTTP/1.1 201 Created
Date: Tue, 19 May 2020 03:43:38 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/2.0.4
Content-Length: 560
X-Kong-Admin-Latency: 139

{"created_at":1589859818,"config":{"minute":2,"policy":"local","month":null,"redis_timeout":2000,"limit_by":"consumer","hide_client_headers":false,"second":null,"day":null,"redis_password":null,"year":null,"redis_database":0,"hour":null,"redis_port":6379,"redis_host":null,"fault_tolerant":true},"id":"b364fd1e-4b61-4fcc-bcd3-5c9320fe06a4","service":{"id":"2c0e7685-bdc1-4800-ad83-bf6faad6c06f"},"enabled":true,"protocols":["grpc","grpcs","http","https"],"name":"rate-limiting","consumer":null,"route":{"id":"f1f9e227-7e3e-4e53-aaac-87c5014ee557"},"tags":null}

$ 

参数说明

  1. name 插件名
  2. service.id 目标服务id
  3. route.id 目标路由id
  4. config.minute 每分钟访问频次(second,minute,hour,day,month,year 至少设置一个)
  5. config.limit_by 限制目标,默认 consumer
    consumer 用户(访问 kong 的一个实体,代表一个实际用户或者一个外部服务)
    还可以配置 consumer, credential, ip, service
  6. config.policy 限制模式
    local 本地模式,调用计数保存在节点机内存
    cluster 集群模式,调用计数保存在数据库,所有节点共享
    redis 调用计数保存在 redis ,所有节点共享
    DB-Less 模式下必须明确配置 local 或者 redis

现在我们访问该路由下的一个 uri
http://kong.localstudy.com/mock/data/h.php
第三次会出现

{
    "message": "API rate limit exceeded"
}
插件开发

通过开发自定义插件,可以扩展 kong 的功能
一个自定义的插件就是一个 lua 模块集合
kong 将会自动加载 kong.plugins.{plugin_name}.{module_name} 命名的 lua 模块集
其中有两个 module 是必须的:
handler.lua
schema.lua
一个简单 plugin 目录:

simple-plugin
├── handler.lua
└── schema.lua

还有一些扩展 module,复杂 plugin 目录:

complete-plugin
├── api.lua
├── daos.lua
├── handler.lua
├── migrations
│   ├── init.lua
│   └── 000_base_complete_plugin.lua
└── schema.lua

modules 介绍:

文件名 必须 介绍
handler.lua Y plugin 的基础文件,他是一个 interface 的实现,每个函数会在对应的请求周期被执行
schema.lua Y plugin 的配置文件
api.lua N 给 Admin 提供一些 API 接口
daos.lua N 如果插件需要存储数据到数据库,在这里定义要用的数据模型
migrations/*.lua N 数据迁移定义( (e.g. creation of tables))
leotest 插件示例

首先建立插件文件夹:/Users/xxx/Downloads/lua_modules/kong/plugins/leotest

然后建立必要文件,目录结构:

$ pwd
/Users/xxx/Downloads/lua_modules/kong/plugins/leotest
$ ls
handler.lua     schema.lua
$ 

handler.lua

local LeotestHandler = {}

LeotestHandler.PRIORITY = 12
LeotestHandler.VERSION = "1.0.0"

local FORBIDDEN = 200
local degrade_msg = "Service is not allowed"
local degrade_code= 600

function LeotestHandler:access(conf)
    ngx.log(ngx.ERR, "debug:LeotestHandler".. conf.test_params)
    return kong.response.exit(FORBIDDEN, {
        msg     = degrade_msg,
        status  = degrade_code
    }) 
end

return LeotestHandler

lua 的一个模块就是一个 table 结构(这一点有点像 js 的类用 json 声明)
PRIORITY 代表 kong 加载该插件的优先级,有时可能需要加载一些插件之后再加载这个插件 查看官方插件优先级
VERSION 插件版本号
LeotestHandler 实现对应接口,以便于在 Request 的声明周期对应阶段执行,参考 官方说明,access 阶段在代理到 upstream service 之前执行

schema.lua

local typedefs = require "kong.db.schema.typedefs"

return {
  name = "leotest",
  fields = {
    { protocols = typedefs.protocols_http },
    { config = {
        type = "record",
        fields = {
          { test_params = { type = "string", default = '0' }, },
    }, }, },
  },
}

protocols 定义允许在哪些协议下运行,这里只允许 http 协议
config 定义配置项,用户可以通过配置该 plugin 时提供一些参数
这里我们定义了一个配置参数 test_params

安装插件:

可以通过 LuaRocks 打包安装,生产环境可以通过这个方式统一对插件进行管理,具体实现参照 官方说明
这里为了开发方便,介绍如何通过源文件手动安装:

  1. 让插件能被 kong 找到

方法1:
在配置文件中加入
lua_package_path = /<path-to-plugin-location>/?.lua;;

方法2:
修改 KONG_LUA_PACKAGE_PATH 环境变量
export KONG_LUA_PACKAGE_PATH=/Users/xxx/Downloads/lua_modules/?.lua

  1. 修改配置文件,让 kong 知道需要加载哪些插件,bundled 代表 kong 的系统插件,不需要的话可以去掉
    plugins = bundled,leotest

  2. 关闭 kong 服务
    kong stop

  3. 通过指定配置文件开启 kong
    kong start -c ~/Kong/kong.conf

没有报错信息的情况下,一个自定义插件就安装好了,下面测试一下:

  1. 给指定服务的指定路由加载 leotest 插件

    $ curl -i -X POST http://127.0.0.1:8001/plugins \
    > --data "name=leotest" \
    > --data "service.id=2c47f3bc-36fe-454d-acb6-b87c6ce3bdcb" \
    > --data "route.id=fb10d312-5d78-4dc3-b694-7fb3d7fa827b" \
    > --data "config.test_params=hello"
    HTTP/1.1 201 Created
    Date: Wed, 20 May 2020 07:55:38 GMT
    Content-Type: application/json; charset=utf-8
    Connection: keep-alive
    Access-Control-Allow-Origin: *
    Server: kong/2.0.4
    Content-Length: 316
    X-Kong-Admin-Latency: 371
    {"created_at":1589961338,"config":{"test_params":"hello"},"id":"a577bb61-e6b3-4934-a1ae-d427410b4bc6","service":{"id":"2c47f3bc-36fe-454d-acb6-b87c6ce3bdcb"},"enabled":true,"protocols":["grpc","grpcs","http","https"],"name":"leotest","consumer":null,"route":{"id":"fb10d312-5d78-4dc3-b694-7fb3d7fa827b"},"tags":null}
    
  2. 访问 http://kong.localstudy.com/

{
    "status": 600,
    "msg": "Service is not allowed"
}
  1. 我们在在插件中定义了每次收到访问会将配置项 test_params 写入错误日志,查看错误日志
$ tail /usr/local/opt/kong/logs/error.log    
...
2020/05/20 15:56:03 [error] 23208#0: *713 [lua] handler.lua:11: debug:LeotestHandlerhello, client: 127.0.0.1, server: kong, request: "GET / HTTP/1.0", host: "kong.localstudy.com"

Consumer

Consumer 代表 kong 中的用户角色,可以针对性的对一个或者一组 Consumer 进行放行或者限行

添加用户

$ curl -i -X POST http://127.0.0.1:8001/consumers \
> --data "username=lx001@g.email" \
> --data "custom_id=100100" \
> --data "tags[]=sys-user" \
> --data "tags[]=auto-reg"
HTTP/1.1 201 Created
Date: Tue, 19 May 2020 07:49:49 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/2.0.4
Content-Length: 148
X-Kong-Admin-Latency: 92

{"custom_id":"100100","created_at":1589874589,"id":"1dfc5306-3c85-433f-8b28-05a17da8396b","tags":["sys-user","auto-reg"],"username":"lx001@g.email"}
$ 

username 具有唯一性的用户名
custom_id 具有唯一性的用户ID,username 和 custom_id 仅提供一项即可
tags 标签,可以通过标签对数据进行分组,方便查询过滤

列出用户

访问 http://127.0.0.1:8001/consumers 即可查看全部用户

{
    "next": null,
    "data": [
        {
            "custom_id": "100100",
            "created_at": 1589874589,
            "id": "1dfc5306-3c85-433f-8b28-05a17da8396b",
            "tags": [
                "sys-user",
                "auto-reg"
            ],
            "username": "lx001@g.email"
        }
    ]
}

阅读:26
搜索
  • Linux 高性能网络编程库 Libevent 简介和示例 1899
  • Mac系统编译PHP7【20190929更新】 1765
  • Windows 安装Swoole 1546
  • Hadoop 高可用集群搭建 (Hadoop HA) 1438
  • Hadoop 高可用YARN 配置 1362
  • 小白鼠问题 1290
  • Hadoop Map Reduce 案例:好友推荐 1241
  • 自动化测试工具 Selenium 1103
  • GIT 分支管理 1022
  • Golang 使用 Grpc 968
简介
不定期分享软件开发经验,生活经验