欢迎访问我的博客,你的支持,是我最大的动力!

KONG-基于lua(OpenResty)的高性能API网关

Linux 小马奔腾 951℃ 评论
目录:
[显示]

Kong介绍

Kong是OpenResty的一个应用程序,依靠lua和nginx的极高性能,具有高效、可配置、可扩展、分布式的API网关
Kong项目完全开源,代码托管于Github,目前已获得超过2.1万的Star和超过2.5千次的fork
Kong除了能用于微服务,也可作为nginx、openresty或者haproxy的替代,同时,kong的插件机制,可为业务提供认证、限流、日志等额外功能

Kong可运行元数据库模式和数据库模式
其中数据库仅支持postgresql 9.5+cassandra 3.x.x (java)

Kong的主要特性:
-> 云原生,可运行于Kubernetes
-> 动态负载均衡,基于哈希的负载均衡
-> 断路器,自动跟踪不健康的上游服务
-> 健康检查,有主动和被动两种检查方式
-> 服务发现,解析第三方DNS的srv记录
-> 支持websockets
-> 支持多种验证方式,OAuth2.0,HMAC,JWT,Basic等
-> 日志功能,支持HTTP/TCP/UDP或直接保存到磁盘
-> 安全,ACL,黑/白名单
-> 支持SSL证书
-> 监控
-> 支持正向/反向代理
-> 限速
-> 添加、删除和操作HTTP请求和响应
-> 支持代理层缓存
-> 支持kong集群
-> 插件机制,支持通过插件添加功能

项目地址:https://github.com/Kong/kong
官方网站:https://konghq.com/kong/
RPM包下载:https://kong.bintray.com/kong-rpm/centos/7/

Kong部署

当前最新版本为 1.1.1
Docker方式:https://hub.docker.com/_/kong/
RPM包地址:https://kong.bintray.com/kong-rpm/centos/7/kong-1.1.1.el7.noarch.rpm

操作系统为CentOS 7.5
采用 RPM + Postgre(Docker) 方式部署

部署 postgre 11.2 (docker方式)

# apache cassandra 是java程序,需要java环境,且通常部署为集群方式

# 拉取镜像
docker pull postgres:11.2               【大小:312MB】
docker pull postgres:11.2-alpine    【大小:70.8MB】
# 启动postgre容器
docker run --name mypostgres -d \
-p 5432:5432 \
-e POSTGRES_PASSWORD=123456 \
-e POSTGRES_USER=admin \
-e PGDATA=/data/ \
-e POSTGRES_DB=kong \
postgres:11.2-alpine
# 容器内操作数据库(测试)
docker exec -it mypostgres bash
psql --host=127.0.0.1 --username=admin --password --dbname=kong
命令:
select 1;
\l  显示数据库
\d 显示表
\d acls 显示表acls结构定义
# CREATE USER kong; CREATE DATABASE kong OWNER kong;
部署 kong 1.1.1

kong 1.1.1 对应的openresty版本为 1.13.6.2

nginx -V
nginx version: openresty/1.13.6.2
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)
built with OpenSSL 1.1.1b 26 Feb 2019
TLS SNI support enabled
configure arguments:
--prefix=/usr/local/openresty/nginx
--with-cc-opt='-O2 -I/tmp/openssl/include'
--add-module=../ngx_devel_kit-0.3.0
--add-module=../echo-nginx-module-0.61
--add-module=../xss-nginx-module-0.06
--add-module=../ngx_coolkit-0.2rc3
--add-module=../set-misc-nginx-module-0.32
--add-module=../form-input-nginx-module-0.12
--add-module=../encrypted-session-nginx-module-0.08
--add-module=../srcache-nginx-module-0.31
--add-module=../ngx_lua-0.10.13
--add-module=../ngx_lua_upstream-0.07
--add-module=../headers-more-nginx-module-0.33
--add-module=../array-var-nginx-module-0.05
--add-module=../memc-nginx-module-0.19
--add-module=../redis2-nginx-module-0.15
--add-module=../redis-nginx-module-0.3.7
--add-module=../rds-json-nginx-module-0.15
--add-module=../rds-csv-nginx-module-0.09
--add-module=../ngx_stream_lua-0.0.5
--with-ld-opt='-Wl,-rpath,/usr/local/openresty/luajit/lib -L/tmp/openssl -Wl,-rpath,/usr/local/kong/lib'
--with-pcre=/tmp/pcre-8.41
--with-pcre-jit  ++
--with-http_realip_module
--with-http_ssl_module
--with-http_stub_status_module
--with-http_v2_module
--with-stream_ssl_preread_module
--with-stream_realip_module   ++
--with-stream
--with-stream_ssl_module

安装kong

yum install https://kong.bintray.com/kong-rpm/centos/7/kong-1.1.1.el7.noarch.rpm
## 没有依赖
部署到系统后的文件:
/etc/kong/kong.conf.default 默认配置文件
/usr/local/bin/{json2lua,kong,lapis,lua2json,luarocks,luarocks-5.1,luarocks-admin,luarocks-admin-5.1}  命令
/usr/local/etc/luarocks/config-5.1.lua
/usr/local/kong/ 工作目录,初始状态仅bin,include,lib目录,初始化后会创建openresty的相关目录
/usr/local/lib/{lua,luarocks}/ 目录
/usr/local/openresty/ Openresty目录
/usr/local/share/lua/ 目录

编辑配置文件

cp /etc/kong/kong.conf.default /etc/kong/kong.conf

监听配置:
100行 anonymous_reports = off   # 不上报错误跟踪信息
107行 proxy_listen = 0.0.0.0:8000, 0.0.0.0:8443 ssl  # 代理监听端口
177行 admin_listen = 0.0.0.0:8001, 0.0.0.0:8444 ssl  # 管理监听端口
数据库配置:
412行 database = postgres
417行 pg_host = 192.168.1.130
418行 pg_port = 5432
422行 pg_user = admin
423行 pg_password = 123456
424行 pg_database = kong

初始化数据库

kong migrations bootstrap

启动kong

kong start

验证

curl -i http://localhost:8001/  或访问 http://192.168.1.50:8001/

当前kong工作目录为:/usr/local/kong
启动命令实际为:/usr/local/openresty/nginx/sbin/nginx -p /usr/local/kong -c nginx.conf
其中 nginx.conf在http块include了文件 nginx-kong.conf
nginx-kong.conf 文件是openresty引入kong的配置文件
日志目录:/usr/local/kong/logs

端口说明:
0 0.0.0.0:8000  代理端口
0 0.0.0.0:8443  代理端口,HTTPS方式
0 0.0.0.0:8001  管理端口
0 0.0.0.0:8444  管理端口,HTTPS方式

kong 基本命令

kong start     # 启动kong
kong stop     # 停止kong
kong restart  # 重启kong
kong reload  # 重载kong
kong check   # 检查配置文件  注意,检查的是 /etc/kong/kong.conf 文件
kong health  # 健康检查
kong quit      # 优雅退出
kong version # 查看版本
kong prepare # 根据kong.conf生成nginx配置文件nginx-kong.conf并验证语法是否正确

Kong使用

一个完整的流程

1、创建服务 service
服务定义一个后端,通过url定义,可以是ip地址、url也可以是upsteam。upsteam提供负载均衡和健康检查能力
curl -i -X POST --url http://127.0.0.1:8001/services/ --data 'name=example-service' --data 'url=http://www.baidu.com'
# 服务名为example-service 访问到http://www.baidu.com

2、为服务添加路由 route
一个服务可以有多个路由,路由即用户访问API网关的url
curl -i -X POST --url http://127.0.0.1:8001/services/example-service/routes --data 'hosts[]=example.com'
# 定义了Host头为example.com的请求会映射到example-service服务

测试:
curl -i -X GET --url http://127.0.0.1:8000 --header 'Host: example.com'
# 返回百度首页

3、为服务添加插件 plugin
添加 key-auth 插件,请求头中必须带有apikey键且值匹配时,才允许访问
curl -i -X POST --url http://127.0.0.1:8001/services/example-service/plugins/ --data 'name=key-auth'
# 为服务example-service启用key-auth插件

验证:
curl -i -X GET --url http://127.0.0.1:8000/ --header 'Host: example.com'
# 因为启用了插件,访问返回401未授权

4、创建用户 consumer
认证是绑定到用户上的
curl -i -X POST --url http://127.0.0.1:8001/consumers/ --data "username=Jason"
# 创建了名为Jason的用户

5、为用户Jason配置key验证
curl -i -X POST --url http://127.0.0.1:8001/consumers/Jason/key-auth/ --data 'key=mykey'
# 键apikey的值为mykey

验证:
curl -i -X GET --url http://127.0.0.1:8000 --header "Host: example.com" --header "apikey: mykey"
# 因为header中有认证的apikey且存在值mykey 允许访问

kong.conf 文件

kong.conf 文件位于 /etc/kong/kong.conf ,它是kong的配置文件,安装提供的kong.conf.default为配置文件模板,注释中的值为默认值,后面还提供了详细的配置说明
配置文件在 kong start 命令或 kong prepare 命令执行时被读取,并最终生成nginx配置文件

配置的提供顺序: 环境变量 > kong.conf > 默认值
其中环境变量全部使用大写字符,且前缀为 KONG_ ,如 log_level -> KONG_LOG_LEVEL

值得注意的配置内容:
anonymous_reports = on  建议设置为 off 不发送报告
headers = server_tokens, latency_tokens  建议设置为off 默认值会在响应头中携带 Server Via X-Kong-Proxy-Latency X-Kong-Upstream-Latency
这会暴露额外的信息
数据库配置通常是必设的内容
数据缓存方面:
db_update_frequency = 5  读取数据库的频率,主要是针对kong集群
db_cache_ttl = 0  数据缓存在内存中的过期时间,0表示永不过期,设置为0可防止因数据库连接出现问题而导致的配置失效问题

注入Nginx指令:
nginx_http_ 前缀,会注入到 http 块
nginx_proxy_ 前缀,会注入到 server 块,业务部分
nginx_admin_ 前缀,会注入到 server 块 AdminApi部分
nginx_http_include 注入nginx配置文件,位于 http 块

kong admin-api

GET /  #获取节点信息,含当前配置信息
GET /status  #获取节点状态,连接、请求数

service

查询服务:
GET /services  #列出服务
GET /services/{service name or id}  #返回指定服务
GET /routes/{route name or id}/service  #返回与特定路由关联的服务
GET /plugins/{plugin id}/service  #返回与特定插件关联的服务

创建服务:
POST /services

参数 属性/默认值 说明
name 可选 服务名称
retries 可选,5 连接失败的重试次数
protocol http 协议,http/https
host   host或upstream的名称
port 80 端口
path 可选 路径
connect_timeout 可选,60000 连接超时,毫秒
write_timeout 可选,60000 写超时,毫秒
read_timeout 可选,60000 读超时,毫秒
tags 可选 标签
url   protocol+host+port+path

示例:
curl -i -X POST --url http://127.0.0.1:8001/services/  \
--data 'name=example-service' \
--data 'url=http://www.baidu.com'
curl -i -X POST --url http://127.0.0.1:8001/services/  \
-H "Content-Type:application/json" \
--data '{"name":"test_service","url":"http://www.baidu.com"}'

更新服务:
PATCH /service/{service name or id}
PATCH /routes/{route name or id}/service
PATCH /plugins/{plugin id}/service
创建或更新服务:
PUT /service/{service name or id}
PUT /routes/{route name or id}/service
PUT /plugins/{plugin id}/service
删除服务:
DELETE /service/{service name or id}
DELETE /routes/{route name or id}/service

route

查询路由:
GET /routes
GET /services/{service name or id}/routes
GET /routes/{route name or id}
GET /plugins/{plugin id}/route
创建路由:
POST /routes
POST /services//{service name or id}/routes

参数 属性/默认值 说明
name 可选 路由名称
protocols 列表,["http","https"] 协议,仅设置["https"]时http请求会跳转到https
methods 半可选,列表 使用http/https时,hosts/paths/methods必须设置一个
hosts 半可选,列表 使用http/https时,hosts/paths/methods必须设置一个
paths 半可选,列表 使用http/https时,hosts/paths/methods必须设置一个
regex_priority 可选,0 正则优先级,多个正则路由同时匹配时使用,优先级相同时取最早创建的
 strip_path 可选,true 为true时,发往后端的请求会删除路由前缀
preserve_host 可选,false 为true时,发往后端的host会是路由的host
为false时,发往后端的host会是service的host
snis 半可选,列表 使用tcp/tls时,snis/sources/destinations必须设置一个
sources 半可选,列表 源IP,使用tcp/tls时,snis/sources/destinations必须设置一个
destinations 半可选,列表 目的IP,使用tcp/tls时,snis/sources/destinations必须设置一个
tags 可选 标签
service 可选,对象 与路由关联的服务,仅支持service id

示例:
curl -i -X POST --url http://127.0.0.1:8001/routes/  \
--data 'name=test-route' \
--data 'hosts[]=example.com' \
--data 'hosts[]=t.example.com' \
--data 'service.id=1597b251-8a60-44cf-90b7-6891057ada27'
curl -i -X POST --url http://127.0.0.1:8001/routes/  \
-H "Content-Type:application/json" \
--data '{"name":"test2-route","hosts":["example.com","t.example.com"],"service":{"id":"1597b251-8a60-44cf-90b7-6891057ada27"}}'

更新路由:
PATCH /route/{route name or id}
PATCH /plugins/{plugin id}/route
更新或创建路由:
PUT /routes/{route name or id}
PUT /plugins/{plugin id}/route
删除路由:
DELETE /routes/{route name or id}

consumer

#查询用户
GET /consumers
GET /consumers/{username or id}
GET /plugins/{plugin id}/consumer
#创建用户
POST /consumers

参数 属性/默认值 说明
username 半可选 用户名,username/custom_id至少设置一个
custom_id 半可选 用户id,username/custom_id至少设置一个
tags 可选,列表 标签

示例:
curl -i -X POST --url http://127.0.0.1:8001/consumers/  \
--data 'username=my-username' \
--data 'custom_id=my-customid' \
--data 'tags[]=usertag'
curl -i -X POST --url http://127.0.0.1:8001/consumers/  \
-H "Content-Type:application/json" \
--data '{"username":"test-user","tags":["test-tag"]}'

更新用户:
PATCH /consumers/{username or id}
PATCH /plugins/{plugin id}/consumer
更新或创建用户:
PUT /consumers/{username or id}
PUT /plugins/{plugin id}/consumer
删除用户:
DELETE /consumers/{username or id}

plugin

插件在每次请求只运行一次
插件文档: https://docs.konghq.com/hub/ 

可为各种实体、实体组合甚至全局设置插件
插件优先级:
路由、服务、用户组合上配置的插件 -> 路由、用户组合上配置的插件 -> 服务、用户组合上配置的插件
-> 路由、服务组合上配置的插件 -> 用户的插件 -> 路由的插件 -> 服务的插件 -> 全局插件

# 查询所有可用插件
GET /plugins/enabled
# 查询插件config参数类型
GET /plugins/schema/{plugin name}

查询插件:
GET /plugins
GET /routes/{route id}/plugins
GET /services/{service id}/plugins
GET /consumers/{consumer id}/plugins
GET /plugins/{plugin id}
启用插件:
POST /plugins
POST /routes/{route id}/plugins
POST /service/{service id}/plugins
POST /consumers/{consumer id}/plugins

参数 属性/默认值 说明
name   插件名称
route 可选,null route.id 绑定到路由
service 可选,null service.id 绑定到服务
consumer 可选,null cosumer.id 绑定到用户
config 可选 插件的属性
run_on first 适用于服务网格场景
first 在请求遇到的第一个kong节点上运行
second 在请求遇到的第二个kong节点上运行
all 在所有节点上运行
protocols 列表,["http","https"] http/https/tcp/tls
enabled 可选,true 是否启用插件
tags 可选 标签

示例:
curl -i -X POST --url http://127.0.0.1:8001/plugins/  \
--data 'name=key-auth' \
--data 'service.id=1597b251-8a60-44cf-90b7-6891057ada27' \
--data 'tags[]=mytag'
curl -i -X POST --url http://127.0.0.1:8001/plugins/  \
-H "Content-Type:application/json" \
--data '{"name":"key-auth","service":{"id":"1597b251-8a60-44cf-90b7-6891057ada27"},"tags":["mytag"]}'

更新插件:
PATCH /plugins/{plugin id}
更新或启用插件:
PUT /plugins/{plugin id}
删除插件:
DELETE /plugins/{plugin id}

certificate

查询证书:
GET /certificates
GET /certificates/{certificate id}
创建证书:
POST /certificates

参数 属性/默认值 说明
cert   PEM编码的证书
key   PEM编码的私钥
tags 可选 标签
snis 可选,列表 与此证书关联的0个或多个主机名的数组
将创建SNI对象并将其与此证书相关联

更新证书:
PATCH /certificates/{certificate id}
更新或创建证书:
PUT /certificates/{certificate id}
删除证书:
DELETE /certificates/{certificate id}

sni

主机名与证书的多对一映射

查询SNI:
GET /snis
GET /certificates/{certificate name or id}/snis
GET /snis/{snis name or id}
添加SNI:
POST /snis
POST /certificates/{certificate name or id}/snis

参数 属性/默认值 说明
name   SNI名称,host名
tags 可选,列表 标签
certificate   certificate.id 证书的UUID

更新SNI:
PATCH /snis/{snis name or id}
更新或添加SNI:
PUT /snis/{sni name or id}
删除SNI:
DELETE /snis/{sni name or id}

upstream

上游对象,虚拟主机名,能实现负载均衡能力,并提供健康检查功能
被动健康检查若失败,不会自动恢复目标,需要管理员手动设置为健康
healthchecks.active.healthy.interval 为0时 不执行健康目标活动探测
healthchecks.active.unhealthy.interval 为0时 不执行非健康目标活动探测
禁用健康检查:
healthchecks.active.healthy.interval=0
healthchecks.active.unhealthy.interval=0
healthchecks.passive下的所有计数器阈值设置为零
默认即为禁用健康检查

查询upstream:
GET /upstreams
GET /upstreams/{name or id}
GET /targets/{target host:port or id}/upstream
添加upstream:
POST /upstreams

参数 属性/默认值 说明
name   host名称,匹配于service对象的host值
hash_on 可选,none 散列的输入,consumer/ip/header/cookie
hash_fallback 可选,none hash_on失败时,备用散列输入,consumer/ip/header/cookie
若hash_on为cookie 该项无效
hash_on_header 半可选 当hash_on为header时,选择要使用的header键名
hash_fallback_header 半可选 当hash_fallback为header时,选择要使用的header键名
hash_on_cookie 半可选 当hash_on或hash_fallback为cookie时,使用的cookie值
若指定的cookie不存在,会生成一个值并在响应中设置cookie
hash_on_cookie_path 半可选,/ 要在响应标头中设置的cookie路径
slots 可选,10000 负载均衡算法中的插槽数,10-65536
healthchecks.active.
https_verify_certificate
可选,true https健康检查时是否检查远程主机ssl证书有效性
healthchecks.active.
unhealthy.http_statuses
可选,[429,404,500,
501,502,503,504,505]
http状态,被认为不健康
healthchecks.active.
unhealthy.tcp_failure
可选,0 被认为不健康的tcp故障数
healthchecks.active.
unhealthy.timeouts
可选,0 被认为不健康的超时次数
healthchecks.active.
unhealthy.http_failures
可选,0 http故障数,即前面定义的不健康的http状态码出现的次数
healthchecks.active.
unhealthy.interval
可选,0 检查间隔,秒
0表示不进行健康检查
healthchecks.active.
http_path
可选,/ GET请求使用的路径
healthchecks.active.
timeout
可选,1 检查的超时时间,秒
healthchecks.active.
healthy.http_statuses
可选,[200,302] http状态,被认为是健康的
healthchecks.active.
healthy.interval
可选,0 健康检查的间隔时间,秒
0表示不进行健康检查
healthchecks.active.
healthy.successes
可选,0 http成功计数,即前面定义为健康的http状态码出现的次数
healthchecks.active.
https_sni
可选 使用https检查时传递的SNI
当使用IP配置目标时,可传递配置的主机名,以验证目标主机证书
healthchecks.active.
concurrency
可选,10 同时检查的目标数
healthchecks.active.
type
可选,http 检查方式,tcp/http/https
healthchecks.passive.
unhealthy.http_failures
可选,0 http故障数,不健康的http状态码的计数
healthchecks.passive.
unhealthy.http_statuses
可选,[429,500,503] 不健康的http状态码
healthchecks.passive.
unhealthy.tcp_failures
可选,0 不健康的tcp故障数
healthchecks.passive.
unhealthy.timeouts
可选,0 不健康的超时次数
healthchecks.passive.
type
可选,http 被动检查方式,tcp/http/https
healthchecks.passive.
healthy.successes
可选,0 成功次数,以认为目标是健康的
healthchecks.passive.
healthy.http_statuses
可选,[200,201,202,203,204,
205,206,207,208,226,300,301,
302,303,304,305,306,307,308]
被认为健康的http状态码
tags 可选 标签

更新upstream:
PATCH /upstreams/{name or id}
PATCH /targets/{target host:port or id}/upstream
更新或添加upstream:
PUT /upstreams/{name or id}
PUT /targets/{target host:port or id}/upstream
删除upstream:
DELETE /upstreams/{name or id}
DELETE /targets/{target host:port or id}/upstream

查看健康状态:
GET /upstreams/{name or id}/health/

target

target是IP/主机名加端口
不能删除或侯target,要禁用某target,设置其weight=0 (可通过DELETE方法快捷实现)
target是和upstream相关联的,不能单独创建

查询target:
GET /upstreams/{upstream host:port or id}/targets
列出所有target:
GET /upstreams/{name or id}/targets/all/
添加target:

POST /upstreams/{upstream host:port or id}/targets

参数 属性/默认值 说明
target   ip/主机名:端口号
若主机名解析为srv记录,port值会被覆盖
weight 可选,100 权重,若主机名解析为srv记录,weight值会被覆盖
tags 可选 标签

禁用target:
DELETE /upstreams/{upstream name or id}/targets/{host:port or id}
注,并非真正删除,而是设置weight为0
设置target为健康:
POST /upstreams/{upstream name or id}/targets/{target or id}/healthy
设置target为不健康:
POST /upstreams/{upstream name or id}/targets/{target or id}/unhealthy

无数据库模式

无数据库模式使用声明式配置
将 kong.conf 中 database 设置为 off
启动kong
检查database是否为off
http :8001/
http :8001/routes # 应为空

# 创建声明性配置文件
kong config -c kong.conf init # 在当前目录创建框架文件 kong.yml

# 检查配置文件
kong config -c kong.conf parse kong.yml

# 加载声明性配置文件
方式1、kong.conf 中 declarative_config=kong.yml
方式2、http :8001/config config=@kong.yml

无DB模式的注意事项:
内存缓存要求 mem_cache_size
节点完全相互独立
只读admin API
插件兼容性,部分插件需要数据库协调或动态创建实体
# oauth2不兼容

kong WebUI

项目地址:https://github.com/pantsel/konga
项目地址:https://github.com/PGBI/kong-dashboard  [不推荐,不好用]

# 拉取镜像
docker pull pantsel/konga
# 初始化数据库
docker run --rm pantsel/konga:latest -c prepare -a postgres -u postgresql://admin:123456@192.168.1.130:5432/konga_database
# 启动容器
docker run -d -p 1337:1337 \
-e "TOKEN_SECRET=aaabbbcccddd" \
-e "DB_ADAPTER=postgres" \
-e "DB_URI=postgresql://admin:123456@192.168.1.130:5432/konga_database" \
-e "NODE_ENV=production" \
--name konga \
pantsel/konga:latest
# 访问
http://192.168.1.50:1337
第一次访问会要求创建一个帐号
然后添加到kong admin的连接

kong 官方文档

https://docs.konghq.com/1.1.x/configuration  # kong.conf参数说明
https://docs.konghq.com/1.1.x/cli  # kong 命令
https://docs.konghq.com/1.1.x/proxy
https://docs.konghq.com/1.1.x/admin-api  # 管理接口
https://docs.konghq.com/1.1.x/clustering  # 集群
https://docs.konghq.com/1.1.x/db-less-and-declarative-config/  # 无数据库模式
https://docs.konghq.com/1.1.x/streams-and-service-mesh/
https://docs.konghq.com/1.1.x/loadbalancing/    # 负载均衡
https://docs.konghq.com/1.1.x/health-checks-circuit-breakers/  # 健康检查
https://docs.konghq.com/1.1.x/plugin-development/
https://docs.konghq.com/hub/  # 插件文档

 

转载请注明:轻风博客 » KONG-基于lua(OpenResty)的高性能API网关

喜欢 (1)or分享 (0)