基于云原生的微服务网关-Kong


Kong是基于OpenResty的云原生开源网关,其将API相关信息配置到Postgresql或者是Cassandra;通过lua扩展模块,扩展网关平台的功能。可扩展、快速且开源的微服务 API 网关,用于管理、保护与连接混合及云原生架构。采用ApacheV2协议授权。

Kong or Kong API Gateway is a cloud-native, platform-agnostic, scalable API Gateway distinguished for its high performance and extensibility via plugins. By providing functionality for proxying, routing, load balancing, health checking, authentication (and more), Kong serves as the central layer for orchestrating microservices or conventional API traffic with ease.
部署Nginx
# 配置https
upstream kong_cluster{
# 最简单的轮询方式
server 172.17.23.17:8000;
server 172.17.23.14:8000;
# 配置三方模块主动检查健康状态,检查TCP,只要确保Kong服务没有断掉即可,实际的服务健康检查使用Kong插件检查
# 其他配置参考 http://tengine.taobao.org/document_cn/http_upstream_check_cn.html
check interval=3000 rise=2 fall=3 timeout=1000 type=tcp;
}
server {
listen 443 ssl;
server_name example.com; # 更换自己的域名信息
ssl_certificate cert/freeoa.pem; # 更换成自己的证书信息
ssl_certificate_key cert/freeoa.key; # 更换成自己的证书信息
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
# https 因为安全原因,需要禁用 gzip
# 但是在一些场景下,不需要禁用
gzip on;
# 设置允许压缩的页面最小字节数
gzip_min_length 1000;
gzip_buffers 4 16k;
gzip_http_version 1.1;
# 1~9,默认为1,数值越大,压缩率越高,CPU占用越多,时间越久
gzip_comp_level 3;
gzip_vary on;
# 禁用对 IE 6 使用 gzip 压缩
gzip_disable "MSIE [1-6]\.";
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/javascript "application/javascript; charset=utf-8" application/xml application/xml+rss application/json "application/json; charset=utf-8" font/ttf font/otf image/svg+xml;
# 设置最大允许的POST数据量,如果提交的文件超过这个值,会出现413错误
client_max_body_size 32m;
keepalive_timeout 15;
# 隐藏 nginx 的版本号
server_tokens off;
# 设置请求头的长度大小
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
## Individual nginx logs
access_log /var/log/nginx/kong_access.log;
error_log /var/log/nginx/kong_error.log;
location ^~ /robots.txt {
expires 30d;
# add_header Content-Type text/plain;
return 200 "User-Agent: *\nDisallow: /";
}
location ~ /(\w+) {
# websocket 支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 真实地址传递,IP限制插件使用
proxy_pass http://kong_cluster;
expires -1;
}
# 主页返回 404
location = / {
return 404;
}
}
server {
listen 80;
server_name example.com; # 更换自己的域名信息
#告诉浏览器有效期内只准用 https 访问
add_header Strict-Transport-Security max-age=15768000;
#永久重定向到 https 站点
return 301 https://$server_name$request_uri;
}
重启Nginx后生效。
将API配置到Kong
Kong常用组件说明
Service
Service是定义的服务,通过Kong转发后根据请求的协议,host,method,path匹配到实际的服务地址。
Service可以与Route进行关联,一个Service可以有很多Route, Route匹配后就会转发到Service,处理过程中也会通过Plugin的处理,增加或者减少一些相应的Header或者其他信息
Service可以是一个实际的地址,也可以是Kong内部提供的Upstream组件关联,由Upstream将请求转发到实际的服务。
Route
Route就是路由,实际就是我们通过定义一些规则来匹配客户端的请求,每个路由都会关联一个Service,并且Service可以关联多个Route,当匹配到客户端的请求时,每个请求都会被代理到其配置的Service中
Route作为客户端的入口,通过将Route和Service的松耦合,可以通过hosts path等规则的配置,最终让请求转发到不同的Service。
例如,我们规定 api.example.com和 api.service.com的登录请求都能够代理到12.34.56.78:8000端口上,那我们可以通过hosts和path来路由
首先,创建一个Service s1,其相应的host和port以及协议为http://12.34.56.7:8000
然后,创建一个Route,关联的Service为s1,其hosts为[api.service.com, api.example.com],path为login
最后,将域名http://api.example.com和http://api.service.com的请求转到到我们的Kong集群上,也就是我们上面一节中通过Nginx配置的请求地址
那么,当我们请求api.example.com/login和api.service.com/login时,其通过Route匹配,然后转发到Service,最终将会请求我们自己的服务。
Upstream
这是指您自己的API /服务位于Kong后面,客户端请求被转发到该服务器。
相当于Kong提供了一个负载的功能,基于Nginx的虚拟主机的方式做的负载功能。当我们部署集群时,一个单独的地址不足以满足我们的时候,我们可以使用Kong的upstream来进行设置。
首先在service中指定host的时候,可以指定为我们的upstream定义的hostname
在创建upstream时指定名字,然后指定solts(暂时不确定具体作用),upstream可以进行健康检查等系列操作。这里先不开启
然后我们可以再创建target类型,将target绑定到upstream上,那么基本上我们部署集群时,也可以使用
Target
target 就是在upstream进行负载均衡的终端,当我们部署集群时,需要将每个节点作为一个target,并设置负载的权重,当然也可以通过upstream的设置对target进行健康检查。当我们使用upstream时,整个路线是 Route >> Service >> Upstream >> Target
Consumer
Consumer 可以代表一个服务,可以代表一个用户,也可以代表消费者,可以根据我们自己的需求来定义;可以将一个Consumer对应到实际应用中的一个用户,也可以只是作为一个Service的请求消费者
Consumer具体可以在Plugin使用时再做深入了解
Plugin
在请求被代理到上游API之前或之后执行Kong内的动作的插件。例如,请求之前的Authentication或者是请求限流插件的使用 Plugin可以和Service绑定,也可以和Route以及Consumer进行关联,也可以是全局的插件。常用的限流插件,IP限制插件等。

Kong使用
主要使用4个组件Service,Route,Upstream和Target;
Target配置的就是服务节点,不过要将其关联到到Upstream;
Upstream可以对Target做负载均衡和健康检查等,通过设置name于Service关联,Service匹配到请求时转发到相应的Upstream;
Service根据业务设置不同的服务,Service和Route绑定获取实际请求,通过protocol,host,port和path匹配请求,并将匹配到的请求转发到Upstream;
Route是Kong中实际的入口点。主要根据protocols,hosts,methods,paths设置,匹配请求,将请求转发到相应的服务上;
按照这个顺序,依次创建Service,Route,Upstream和Target。
Kong插件使用
插件的作用范围,从小到大可以是 Route,Service,Consumer,Global。
可以根据需求使用一些插件,比如做一些限流操作,IP白名单和IP黑名单等;下面是Kong官方就提供的开源版可用的插件。
Rate Limiting
限流插件,限制在指定时间内可以访问的次数,可以是几秒内,几分钟内,几小时,几天等。 插件可以设置在Service,Route或者全局,如果启用Consumer,则根据Consumer来计算限制时间,否则根据客户端IP地址。
IP Restriction
IP Restriction就是通过设置IP白名单和黑名单,根据客户端IP来对一些请求进行拦截和防护,通过插件的源码可以看到其工作原理是,通过NGINX的变量binary_remote_addr以及设置的黑名单和白名单来进行限制,先看黑名单再看白名单,就是说白名单优先级更高一些,如果同时设置一个IP即在黑名单又在白名单列表,那么这个IP是可以进行访问。
IP Restriction插件可以作用于Service, Route, Consumer, 也可以作用于全局。
HMAC Authentication
HMAC签名身份验证,Kong网关签名验证通过后,才可以向后请求,实际应用场景听多,具体流程如下:
创建消费者Consumer给消费Consumer创建插件HMAC对应的username和secret,客户端使用其签名在Service或者Route中启用HMAC插件客户端在请求时,根据前面返回的username和secret签名,Kong网关匹配后进行签名验证。
服务器端准备
enforce_headers: Header中必须要有的参数,后续用于签名验证
algorithms:用户想要支持的HMAC摘要算法列表。允许的值是hmac-sha1,hmac-sha256,hmac-sha384,和hmac-sha512客户端请求时,从中选择一个即可
validate_request_body:启用验证请求体,设置为true之后,客户端请求头中若是有Digest,Kong则会使用HMAC算法验证请求体body。
客户端请求测试
重要请求头信息
1. Authorization 或者 Proxy-Authorization
这个头的组成是
credentials 签名算法 使用HMAC插件,固定值就是hmac
params 具体的参数,参数用","分割。
algorithm: 签名算法
headers: 签名计算包括的key
signature: 生成的签名,生成规则
2. Digest:启用validate_request_body,需要生成
3. Date:必须是GMT时间格式
与Apache APISIX对比

最新版本:3.0
2022年9月中旬 Kong 发布了 3.0.0 版本,这个主要版本添加了一个用 Rust 编写的新路由器,和一个与 OpenTelemetry API 规范兼容的跟踪 API。此外还进行了各种内部更改以提高 Kong 的性能和内存消耗。由于它是主要版本,建议用户查看更改列表,以确定升级时是否需要更改配置。
不支持从 2.1.0 之前的 Kong 进行蓝绿部署,升级到 2.1.0 或更高版本再升级到 3.0.0 进行蓝绿部署。
弃用/停止生产 Amazon Linux (1) 容器和软件包(2020 年 12 月 31 日停产
弃用/停止生产 Debian 8 “Jessie” 容器和软件包(2020 年 6 月停产)
当给定上下文为 “选择” 时,Kong 模式库的 process_auto_fields 函数将不再制作传递给它的数据的深层副本。
Kong Plugin 或 DAO 模式中已弃用的简写字段已被删除,取而代之的是或键入的 shorthand_fields。
从 Kong 模式和 Kong 字段模式中删除了对 legacy = true/false 属性的支持。
Kong.serve_admin_api 已弃用的别名已被删除。如果自定义 Nginx 模板仍然使用它,请将其更改为 Kong.admin_content。
删除了 dataplane 配置缓存,配置持久性现在使用 LMDB 自动完成。
官方主页
https://konghq.com/
https://github.com/Kong/kong

Kong or Kong API Gateway is a cloud-native, platform-agnostic, scalable API Gateway distinguished for its high performance and extensibility via plugins. By providing functionality for proxying, routing, load balancing, health checking, authentication (and more), Kong serves as the central layer for orchestrating microservices or conventional API traffic with ease.
部署Nginx
# 配置https
upstream kong_cluster{
# 最简单的轮询方式
server 172.17.23.17:8000;
server 172.17.23.14:8000;
# 配置三方模块主动检查健康状态,检查TCP,只要确保Kong服务没有断掉即可,实际的服务健康检查使用Kong插件检查
# 其他配置参考 http://tengine.taobao.org/document_cn/http_upstream_check_cn.html
check interval=3000 rise=2 fall=3 timeout=1000 type=tcp;
}
server {
listen 443 ssl;
server_name example.com; # 更换自己的域名信息
ssl_certificate cert/freeoa.pem; # 更换成自己的证书信息
ssl_certificate_key cert/freeoa.key; # 更换成自己的证书信息
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
# https 因为安全原因,需要禁用 gzip
# 但是在一些场景下,不需要禁用
gzip on;
# 设置允许压缩的页面最小字节数
gzip_min_length 1000;
gzip_buffers 4 16k;
gzip_http_version 1.1;
# 1~9,默认为1,数值越大,压缩率越高,CPU占用越多,时间越久
gzip_comp_level 3;
gzip_vary on;
# 禁用对 IE 6 使用 gzip 压缩
gzip_disable "MSIE [1-6]\.";
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/javascript "application/javascript; charset=utf-8" application/xml application/xml+rss application/json "application/json; charset=utf-8" font/ttf font/otf image/svg+xml;
# 设置最大允许的POST数据量,如果提交的文件超过这个值,会出现413错误
client_max_body_size 32m;
keepalive_timeout 15;
# 隐藏 nginx 的版本号
server_tokens off;
# 设置请求头的长度大小
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
## Individual nginx logs
access_log /var/log/nginx/kong_access.log;
error_log /var/log/nginx/kong_error.log;
location ^~ /robots.txt {
expires 30d;
# add_header Content-Type text/plain;
return 200 "User-Agent: *\nDisallow: /";
}
location ~ /(\w+) {
# websocket 支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 真实地址传递,IP限制插件使用
proxy_pass http://kong_cluster;
expires -1;
}
# 主页返回 404
location = / {
return 404;
}
}
server {
listen 80;
server_name example.com; # 更换自己的域名信息
#告诉浏览器有效期内只准用 https 访问
add_header Strict-Transport-Security max-age=15768000;
#永久重定向到 https 站点
return 301 https://$server_name$request_uri;
}
重启Nginx后生效。
将API配置到Kong
Kong常用组件说明
Service
Service是定义的服务,通过Kong转发后根据请求的协议,host,method,path匹配到实际的服务地址。
Service可以与Route进行关联,一个Service可以有很多Route, Route匹配后就会转发到Service,处理过程中也会通过Plugin的处理,增加或者减少一些相应的Header或者其他信息
Service可以是一个实际的地址,也可以是Kong内部提供的Upstream组件关联,由Upstream将请求转发到实际的服务。
Route
Route就是路由,实际就是我们通过定义一些规则来匹配客户端的请求,每个路由都会关联一个Service,并且Service可以关联多个Route,当匹配到客户端的请求时,每个请求都会被代理到其配置的Service中
Route作为客户端的入口,通过将Route和Service的松耦合,可以通过hosts path等规则的配置,最终让请求转发到不同的Service。
例如,我们规定 api.example.com和 api.service.com的登录请求都能够代理到12.34.56.78:8000端口上,那我们可以通过hosts和path来路由
首先,创建一个Service s1,其相应的host和port以及协议为http://12.34.56.7:8000
然后,创建一个Route,关联的Service为s1,其hosts为[api.service.com, api.example.com],path为login
最后,将域名http://api.example.com和http://api.service.com的请求转到到我们的Kong集群上,也就是我们上面一节中通过Nginx配置的请求地址
那么,当我们请求api.example.com/login和api.service.com/login时,其通过Route匹配,然后转发到Service,最终将会请求我们自己的服务。
Upstream
这是指您自己的API /服务位于Kong后面,客户端请求被转发到该服务器。
相当于Kong提供了一个负载的功能,基于Nginx的虚拟主机的方式做的负载功能。当我们部署集群时,一个单独的地址不足以满足我们的时候,我们可以使用Kong的upstream来进行设置。
首先在service中指定host的时候,可以指定为我们的upstream定义的hostname
在创建upstream时指定名字,然后指定solts(暂时不确定具体作用),upstream可以进行健康检查等系列操作。这里先不开启
然后我们可以再创建target类型,将target绑定到upstream上,那么基本上我们部署集群时,也可以使用
Target
target 就是在upstream进行负载均衡的终端,当我们部署集群时,需要将每个节点作为一个target,并设置负载的权重,当然也可以通过upstream的设置对target进行健康检查。当我们使用upstream时,整个路线是 Route >> Service >> Upstream >> Target
Consumer
Consumer 可以代表一个服务,可以代表一个用户,也可以代表消费者,可以根据我们自己的需求来定义;可以将一个Consumer对应到实际应用中的一个用户,也可以只是作为一个Service的请求消费者
Consumer具体可以在Plugin使用时再做深入了解
Plugin
在请求被代理到上游API之前或之后执行Kong内的动作的插件。例如,请求之前的Authentication或者是请求限流插件的使用 Plugin可以和Service绑定,也可以和Route以及Consumer进行关联,也可以是全局的插件。常用的限流插件,IP限制插件等。

Kong使用
主要使用4个组件Service,Route,Upstream和Target;
Target配置的就是服务节点,不过要将其关联到到Upstream;
Upstream可以对Target做负载均衡和健康检查等,通过设置name于Service关联,Service匹配到请求时转发到相应的Upstream;
Service根据业务设置不同的服务,Service和Route绑定获取实际请求,通过protocol,host,port和path匹配请求,并将匹配到的请求转发到Upstream;
Route是Kong中实际的入口点。主要根据protocols,hosts,methods,paths设置,匹配请求,将请求转发到相应的服务上;
按照这个顺序,依次创建Service,Route,Upstream和Target。
Kong插件使用
插件的作用范围,从小到大可以是 Route,Service,Consumer,Global。
可以根据需求使用一些插件,比如做一些限流操作,IP白名单和IP黑名单等;下面是Kong官方就提供的开源版可用的插件。
Rate Limiting
限流插件,限制在指定时间内可以访问的次数,可以是几秒内,几分钟内,几小时,几天等。 插件可以设置在Service,Route或者全局,如果启用Consumer,则根据Consumer来计算限制时间,否则根据客户端IP地址。
IP Restriction
IP Restriction就是通过设置IP白名单和黑名单,根据客户端IP来对一些请求进行拦截和防护,通过插件的源码可以看到其工作原理是,通过NGINX的变量binary_remote_addr以及设置的黑名单和白名单来进行限制,先看黑名单再看白名单,就是说白名单优先级更高一些,如果同时设置一个IP即在黑名单又在白名单列表,那么这个IP是可以进行访问。
IP Restriction插件可以作用于Service, Route, Consumer, 也可以作用于全局。
HMAC Authentication
HMAC签名身份验证,Kong网关签名验证通过后,才可以向后请求,实际应用场景听多,具体流程如下:
创建消费者Consumer给消费Consumer创建插件HMAC对应的username和secret,客户端使用其签名在Service或者Route中启用HMAC插件客户端在请求时,根据前面返回的username和secret签名,Kong网关匹配后进行签名验证。
服务器端准备
enforce_headers: Header中必须要有的参数,后续用于签名验证
algorithms:用户想要支持的HMAC摘要算法列表。允许的值是hmac-sha1,hmac-sha256,hmac-sha384,和hmac-sha512客户端请求时,从中选择一个即可
validate_request_body:启用验证请求体,设置为true之后,客户端请求头中若是有Digest,Kong则会使用HMAC算法验证请求体body。
客户端请求测试
重要请求头信息
1. Authorization 或者 Proxy-Authorization
这个头的组成是
credentials 签名算法 使用HMAC插件,固定值就是hmac
params 具体的参数,参数用","分割。
algorithm: 签名算法
headers: 签名计算包括的key
signature: 生成的签名,生成规则
2. Digest:启用validate_request_body,需要生成
3. Date:必须是GMT时间格式
与Apache APISIX对比

最新版本:3.0
2022年9月中旬 Kong 发布了 3.0.0 版本,这个主要版本添加了一个用 Rust 编写的新路由器,和一个与 OpenTelemetry API 规范兼容的跟踪 API。此外还进行了各种内部更改以提高 Kong 的性能和内存消耗。由于它是主要版本,建议用户查看更改列表,以确定升级时是否需要更改配置。
不支持从 2.1.0 之前的 Kong 进行蓝绿部署,升级到 2.1.0 或更高版本再升级到 3.0.0 进行蓝绿部署。
弃用/停止生产 Amazon Linux (1) 容器和软件包(2020 年 12 月 31 日停产
弃用/停止生产 Debian 8 “Jessie” 容器和软件包(2020 年 6 月停产)
当给定上下文为 “选择” 时,Kong 模式库的 process_auto_fields 函数将不再制作传递给它的数据的深层副本。
Kong Plugin 或 DAO 模式中已弃用的简写字段已被删除,取而代之的是或键入的 shorthand_fields。
从 Kong 模式和 Kong 字段模式中删除了对 legacy = true/false 属性的支持。
Kong.serve_admin_api 已弃用的别名已被删除。如果自定义 Nginx 模板仍然使用它,请将其更改为 Kong.admin_content。
删除了 dataplane 配置缓存,配置持久性现在使用 LMDB 自动完成。
官方主页
https://konghq.com/
https://github.com/Kong/kong