浙江汉农建设有限公司网站,扬州门户网站开发公司,网站建设项目管理论文,设计之窗Kong Gateway 是一个轻量、快速、灵活的云原生API网关#xff0c;其本质是一个运行在 Nginx中的Lua应用程序。
概述
Kong是Mashape开源的高性能高可用的API网关#xff0c;可以水平扩展。它通过前置的负载均衡配置把请求分发到各个server#xff0c;来应对大批量的网络请求…Kong Gateway 是一个轻量、快速、灵活的云原生API网关其本质是一个运行在 Nginx中的Lua应用程序。
概述
Kong是Mashape开源的高性能高可用的API网关可以水平扩展。它通过前置的负载均衡配置把请求分发到各个server来应对大批量的网络请求。 由于Kong 的成功Mashape 于 2017 年重组并更名为 Kong Inc.将业务重点全面转移到 API 网关及相关技术上。如今已成为 API 网关和服务网格的领先提供商。 主要功能
Kong提供了诸如HTTP基本认证、密钥认证、CORS、TCP、UDP、日志记录、请求限流、请求转发以及NGINX监控等基本功能。除此之外它还可以通过插件(lua编写)来扩展已有的功能。其示意图如下 Kong的核心功能如下
API路由与反向代理
Kong Gateway作为API请求的入口将请求从客户端路由到相应的服务。支持动态路由可以根据URL、请求头、参数等条件来决定将请求转发到哪个服务端点。
认证与授权
提供多种认证方式如OAuth 2.0、JWT、Basic Auth、Key Auth等确保API只能被经过认证的客户端访问。支持对用户进行授权控制确保不同的用户只能访问他们被授权使用的API服务。
安全保护
Kong Gateway可以保护API免受常见攻击如DDos、SQL注入、跨站请求伪造等。通过API限流IP白名单/黑明单机制防止恶意访问。
负载均衡
Kong可以在多个服务之间分配流量确保负载均衡分布并具备健康检查功能可以动态监测服务节点的健康状况。支持协议的转换比如从HTTP转换为HTTPS、从HTTP2转换为HTTP1.1。
限流与速度限制
Kong提供了高级的速率限制功能你可以为每个API路由配置速率限制策略限制客户端在一定时间内发送的请求数量防止资源滥用。
监控与日志记录
Kong集成了多种监控工具支持Prometheus、Datalog、Grafana等监控系统。提供了详细的日志记录功能记录API的访问日志包括响应时间请求来源等信息。
插件架构
支持通过插件来扩展功能官方和社区提供了丰富的插件生态系统覆盖认证、限流、缓存、日志记录等多方面。开发者还可以自定义插件来满足特定的业务需求。
多协议支持
支持多种协议如HTTP、HTTPS、gRPC、WebSocket等允许在API层支持不同类型的服务通信。
服务网格集成
Kong Gateway与Kong Mesh无缝集成支持在更复杂的微服务架构中管理服务间的通信、提供服务发现、负载均衡以及自动化的安全策略。 Kong gateway是与OpenResty一起分发的而OpenRestry是一个扩展于lua-nginx-module的模块。OpenRestry主要解决Nginx无法动态扩展功能的问题它将Lua JIT内嵌到了 Nginx 的内部以支持通过 lua 语言对 Nginx 的能力进行方便地扩展开发。 版本和模式
Kong Gateway的部署方式有两种使用Kong Konnect进行托管和自主管理。
Konnect提供了实用Kong Gateway的最简单的方法。全局控制平面由Kong托管在云上你只需要管理各个数据平面节点即可 但Konnect是收费方案。另一种部署方式就是自管理。
自管理
Kong gateway有两个不同的版本开源版和企业版。开源版包括基本的API网关功能和开源插件企业版附加了一些额外功能包括RBAC和企业插件。企业版是收费的。
开源版和企业版的功能比较
功能描述开源版企业版API基础设施现代化API网关✅✅端对端自动化✅✅Kong Ingress Controller✅✅网关Mocking❌✅admin界面管理器✅✅流量管理和转换基础流量管控插件✅✅简单数据转换✅✅gRPC转换✅✅GraphQL❌✅请求验证❌✅jq转换❌✅高级缓存❌✅高级qps限制❌✅安全管控认证和基本授权(Bot检测CORSACLs)✅✅高级认证❌✅基于角色的访问控制(RBAC)❌✅高级授权(OPA)❌✅证书管理❌✅FIPS 140-2 支持❌✅Signed Kong镜像❌✅AI网关多种大语言模型支持✅✅AI流量控制✅✅AI prompt安全✅✅AI 可观测性✅✅企业支持与服务❌✅
Kong Admin API 和 Kong Manager
Kong 网关的所有实体包括服务路由插件消费者等等都可以通过admin api来访问和配置。
Kong Manager是Kong 网关的图形化管理界面实际上还是通过Admin API来调用接口进行管理。
Kubernetes
前文说过Kong Gateway是云原生网关主要体现为它可以通过其ingress controller运行在k8s中。
工作原理
本节将从路由负载均衡方面来介绍Kong Gateway的工作原理。
路由规则
Kong Gateway对外暴露多个接口体现在如下的配置属性中
proxy_listen这个属性定义了一系列地址/端口通过这些地址和端口来接受公开的HTTP, gRPC, WebSocket等请求随后将这些请求代理到服务(默认8000端口)。admin_listen: 这个属性也定义了一系列地址和端口但这个属性指定的是Admin API 的地址提供给管理员来对Kong进行配置(默认8001端口)。stream_listen: 这个属性与proxy_listen作用类似只不过它是适用于4层的代理(如TCP、TLS)。默认情况下是关闭的。
从顶层来看Kong Gateway既可以监听7层的HTTP请求也可以监听4层的请求分别通过proxy_listen和stream_listen指定。然后根据配置的路由将匹配的请求代理到对应的服务。路由条件是根据子系统(HTTP/HTTPS, gRPC/gRPCS, TCP/TLS)来区分的主要有下列条件
http: methods, hosts, headers, paths (对于https请求还有snis)tcp: sources, destinations对于tls还有snisgrpc: hosts, headers, paths对于grpcs还有snis
假设现在我们创建了一个路由如下
curl -i -X POST http://localhost:8001/routes/ \-d hosts[]test.com \-d hosts[]foo-service.com \-d headers.regionnorth该路由规定了hosts和header参数只有满足条件的请求才能被路由接受。
域名通配符
设置路由属性时既可以指定完整的域名也可以使用域名通配符。
路径正则表达式
设置路由属性时既可以指定完整的路径也可以使用正则表达式来表示路径。当路径是正则表达式时需要用~作为前缀如
paths: [~/foo/bar$]没有~前缀会被当成纯文本如
paths: [/users/\d/profile, /following]如果一个请求的路径同时满足两个路径条件那应该如何路由呢这时候就需要考虑路径优先级了。优先级是根据regex_priority 来判断的。该值越大则优先级越高。如果没有设置regex_priority , 则要根据其他规则来判断优先级具体路径 前缀匹配 正则匹配。
捕获组
在Kong中捕获组是正则表达式的一种功能用于在路由中提取特定部分的请求路径。假设有一个正则表达式路由配置如下
routes:- name: user-routepaths:- ~^/users/(\d)/details$service:id: user-service这里的(\d)就是一个捕获组。请求/users/123/details可以匹配到该路径其中的123就是捕获组参数。后端服务可以通过动态路径来接受该参数如Springboot中的GetMapping(/users/{id}/details) 。
除此之外还可以通过插件来对捕获组参数进行其他处理。例如request-transformer插件可以将参数作为请求头放进去
plugins:- name: request-transformerservice: user-serviceconfig:add:headers:- X-User-ID: $1preserve_host
Kong Gateway在代理请求时会默认将Kong中配置的服务域名作为Host发送给服务。如果将preserve_host 设为true则会将原始客户端请求的host发送给服务。
举个例子假设原始客户端请求的域名为service.com, 该请求将被路由到域名为api.internal.service的服务。如果不设置preserve_host , 则服务收到的请求的Host将是api.internal.service。如果将preserve_host 设为true则服务收到的请求的Host为原始的service.com。
负载均衡
Kong gateway提供了多种负载均衡方式默认的是基于DNS的方式。
默认情况下DNS负载均衡器是开启的并且仅限于轮询的负载均衡的算法中。换句话说默认使用DNS负载均衡器时Kong不提供其他负载均衡算法如最少连接随机等。因此尽管支持多种负载均衡策略但是DNS负载均衡的上下文中轮询是唯一可用的选择。
开启Kong Gateway之旅
安装方式有多种既可以下载安装包也可以通过docker来安装。本文以docker安装为例进行介绍。
安装kong gateway
首先创建一个docker网络
docker network create kong-net然后启动一个postgresql容器: docker run -d --name kong-database \--networkkong-net \-p 5432:5432 \-e POSTGRES_USERkong \-e POSTGRES_DBkong \-e POSTGRES_PASSWORDkongpass \postgres:12用户名和数据库名设置为kong是Kong gateway的默认值。密码则无要求。 接下来准备初始化数据
docker run --rm --networkkong-net \
-e KONG_DATABASEpostgres \
-e KONG_PG_HOSTkong-database \
-e KONG_PG_PASSWORDkongpass \
kong:3.8.0 kong miigrations bootstrap如果docker的镜像仓库访问不了可以用docker pull public.ecr.aws/docker/library/kong:3.8.0从aws的免费仓库拉取, 然后重新打标签: docker tag public.ecr.aws/docker/library/kong:3.8.0 kong:3.8.0 这里KONG_DATABASE指定数据库类型KONG_PG_HOST就是上一步创建的postgres容器密码也是上一步的密码。kong migrations bootstrap 是数据初始化命令。--rm参数表示这是一个一次性任务完成之后即删除容器。
启动容器
docker run -d --name kong-gateway \--networkkong-net \-e KONG_DATABASEpostgres \-e KONG_PG_HOSTkong-database \-e KONG_PG_USERkong \-e KONG_PG_PASSWORDkongpass \-e KONG_PROXY_ACCESS_LOG/dev/stdout \-e KONG_ADMIN_ACCESS_LOG/dev/stdout \-e KONG_PROXY_ERROR_LOG/dev/stderr \-e KONG_ADMIN_ERROR_LOG/dev/stderr \-e KONG_ADMIN_LISTEN0.0.0.0:8001, 0.0.0.0:8444 ssl \-e KONG_ADMIN_GUI_URLhttp://localhost:8002 \-p 8000:8000 \-p 8443:8443 \-p 127.0.0.1:8001:8001 \-p 127.0.0.1:8002:8002 \-p 127.0.0.1:8444:8444 \kong:3.8.0KONG_ADMIN_LISTEN指定admin api监听的端口 验证是否安装成功 curl -i -X GET --url http://localhost:8001/services如果成功安装你可以看到返回200状态码。通过http://localhost:8002查看管理界面。 Kong gateway还可以以无数据库模式启动此时通过配置文件来加载配置。这种方式虽然更简单但只适合独立的网关实例或小规模环境。这里就不介绍了。 服务与路由
服务和路由是Kong的流量管理策略中的两个重要组件。
服务管理
创建服务
先通过Admin API创建一个服务该服务将映射到https://httpbin.konghq.com。
curl -i -s -X POST http://localhost:8001/services \--data nameexample_service \--data urlhttps://httpbin.konghq.com查看服务
查看服务配置
curl -X GET http://localhost:8001/services/example_service输出如下
{host: httpbin.konghq.com,name: example_service,enabled: true,...
}更新服务
将retries参数从5改成6:
curl --request PATCH --url localhost:8001/services/example_service --data retries6列出服务
curl -X GET http://localhost:8001/services路由管理
创建路由
创建关联服务的路由请求该路由地址的流量将被转发到关联的服务
curl -i -X POST http://localhost:8001/services/example_service/routes --data paths[]/mock --data nameexample_route查看路由配置
路由查看地址
/services/{service name or id}/routes/{route name or id}
/routes/{route name or id}以前者为例
curl -X GET http://localhost:8001/services/example_service/routes/example_route更新路由
curl --request PATCH --url localhost:8001/services/example_service/routes/example_route --data tagstutorial列出路由
curl http://localhost:8001/routes除了Admin API之外也可以通过Manager查看和管理。 请求代理
根据上面创建的路由可知当向/mock发送请求时将会被路由到example_service。
发送请求如下
curl -X GET http://localhost:8000/mock/anything可以看到服务返回的响应结果。
请求速率限制
Rps限制可以针对全局可以针对服务和路由还可以针对消费者。速率限制插件是默认安装的。
全局限制
curl -i -X POST http://localhost:8001/plugins --data namerate-limiting --data config.minute5 --data config.policylocallocal表示当个kong节点计数cluster表示多节点部署时计数共享。 我们执行一个命令来发送6条请求看看是否会触发rate limit
for _ in {1..6}; do curl -s -i localhost:8000/mock/anything; echo; sleep 1; done前面5次请求正常输出最后一条请求输出
{message:API rate limit exceeded,request_id:c9e6a941e6217c3011b8b86146081a72
}说明触发了速率限制。
服务限制
服务级别的rate limiting需要请求具体服务的plugins
curl -X POST http://localhost:8001/services/example_service/plugins --data namerate-limiting --data config.minute5 --data config.policylocal路由限制
curl -X POST http://localhost:8001/routes/example_route/plugins --data namerate-limiting --data config.minute5 --data config.policylocal消费者限制
所谓消费者即服务的调用方。
先创建一个消费者
curl -X POST http://localhost:8001/consumers/ --data usernamejsmith再开启消费速率限制
curl -X POST http://localhost:8001/plugins --data namerate-limiting --data consumer.usernamejsmith --data config.second5在生产环境中消费者通常是基于API密钥或者JWT等方式来识别的。
速率限制只是Kong Gateway的其中一个功能其他的如缓存、认证、负载均衡等都是以类似的方式来进行配置的并且这些基础功能都可以通过Manger来操作。这里就不一一列举了具体可以参见网上资料。
生产实践
部署方式
Kong Gateway一共有四种部署方式分别是
Konnect(托管控制平面)HybridTraditional(database)DB-less and declarative
不通的模式都有各自的特点需要在生产环境中需要根据具体情况来考虑。
Konnect
Konnect是一种混合模式的部署它提供了使用Kong Gateway的最简单方法。全局控制平面由Kong托管在云上而你可以在自己的网络环境中管理各个数据平面节点。
Hybrid
在混合模式中Kong Gateway节点分成两种角色一种是控制平面(CP)一种是数据平面(DP)。控制平面负责管理配置信息并提供Admin API接口。数据平面负责请求路由。控制平面访问数据库数据平面连接到控制平面节点获取最新的配置信息。如下图所示 Traditional (database)
传统模式中Kong Gateway在数据库中存储配置信息。所有的kong gateway节点均连接到数据库每个节点自己管理配置信息。示意图如下
与混合模式相比传统模式没有控制平面。因此每个节点既有控制平面的作用也有数据平面的作用。这意味着如果您的任何节点被泄露则整个运行中的网关配置也会被泄露。相比之下混合模式具有不同的CP和DP节点减小了被攻击的暴露面。
DB-less and declarative mode
无数据库模式通过配置文件来读取配置信息并将配置信息保存在节点的内存中。
此种模式下Kong Gateway不能完全发挥所有功能。
Admin API 安全保护
通过Admin API 可以对Kong Gateway进行完全的控制所以对Admin API 的访问控制就尤为显得重要。
网络层的访问限制
默认情况下Kong只能通过本地接口访问其admin_listen的设置如下
admin_listen 127.0.0.1:8001这个值是可以修改的但不要扩大暴露面比如0.0.0.0:8081是不行的。
L3/4 的访问控制
如果必须将Admin API 的接口暴露给非本地接口那也要从网络层面上做尽可能多的访问限制。假设现在有这样一个场景Admin API 暴露在某个私有网络中但只能给某个IP范围段的部分地址访问。在这种情况下就必须配置基于主机的防火墙(例如 iptables)。
grep admin_listen /etc/kong/kong.conf
admin_listen 10.10.10.3:8001# 显示设置只允许来自自身8001端口的TCP包
iptables -A INPUT -s 10.10.10.3 -m tcp -p tcp --dport 8001 -j ACCEPT# 显示设置只允许来自以下地址的8001端口的TCP包
iptables -A INPUT -s 10.10.10.4 -m tcp -p tcp --dport 8001 -j ACCEPT
iptables -A INPUT -s 10.10.10.5 -m tcp -p tcp --dport 8001 -j ACCEPT# 其他地址发送过来的包全部丢弃
iptables -A INPUT -m tcp -p tcp --dport 8001 -j DROP灰度部署
蓝绿部署
“Blue” Environment
先创建upstream
curl -X POST http://localhost:8001/upstreams --data nameaddress.v1.service添加两个目标地址
curl -X POST http://localhost:8001/upstreams/address.v1.service/targets --data target192.168.34.15:80 --data weight100
curl -X POST http://localhost:8001/upstreams/address.v1.service/targets --data target192.168.34.16:80 --data weight50创建一个服务将其关联到上面的upstream:
curl -X POST http://localhost:8001/services/ --data nameaddress-service --data hostaddress.v1.service --data path/address添加服务路由
curl -X POST http://localhost:8001/services/address-service/routes/ --data hosts[]address.mydomain.com当请求的域名符合路由规则时该请求将被转发到service对应的upstream上并根据服务器实例的权重值进行负载均衡。三分之二的请求被转发到http://192.168.34.15:80/address三分之一的请求转发到另一台机器。
“Green” Environment
同样地再创建一个Green环境。
# 创建upstream
curl -X POST http://localhost:8001/upstreams --data nameaddress.v2.service# 添加targets
curl -X POST http://localhost:8001/upstreams/address.v2.service/targets --data target192.168.34.17:80 --data weight100
curl -X POST http://localhost:8001/upstreams/address.v2.service/targets --data target192.168.34.18:80 --data weight100服务和路由已经有了接下来只需要修改一下服务的域名:
curl -X PATCH http://localhost:8001/services/address-service --data hostaddress.v2.service此时再次发送请求curl http://address.mydomain.com/address时请求将被转发到服务对应的域名address.v2.service关联的upstream上并根据每台服务器的权重来做负载均衡。
通过Admin API 更改的Kong Gateway 配置实时生效无需重载或者重启当前正在处理中的请求也不会受到影响。
金丝雀部署
在上文的基础上我们更新域名address.v2.service关联的targets的权重值。假设192.168.34.17:80为原机器192.168.34.18:80为新机器。
# 获取upstreams
curl http://localhost:8001/upstreams/# 获取指定upstream关联的targets
curl http://localhost:8001/upstreams/{upstream_id}/targets# 修改target原机器ip的权重
curl -X PATCH http://localhost:8001/upstreams/{upstream_id}/targets/{target_id} --data weight1000
# 修改target新机器ip权重
curl -X PATCH http://localhost:8001/upstreams/{upstream_id}/targets/{target_id} --data weight0所有admin api的操作均可在manager console上操作 修改完权重后因为新服务实例的权重为0因此所有请求将被全部转发原服务实例上。接下来修改两个服务实例的权重值其中一个降低为900另一个增长为100。修改完成后10%的请求将被转发到新服务实例上。以此类推直到所有请求全部被转发到新机器上。
区别
蓝绿部署和金丝雀部署都是用于发布和部署更新的策略但两者的方式和目标有所不同。
蓝绿部署是一种发布策略将应用的两个完整版本蓝色和绿色分别部署在独立的环境中。通常“蓝色”表示旧版本“绿色”表示新版本。其流程是蓝色环境承载生产流量新版本在绿色环境中完全准备好后流量从蓝色环境切换到绿色环境使所有用户瞬间访问到新版本如果需要回滚可以快速切换回蓝色环境。
金丝雀部署是一种渐进式发布策略将新版本逐步推送给一小部分用户进行验证后再逐步增加流量直到全部用户使用新版本。其流程是新版本部署到少量节点并分配一部分流量根据监控的指标和反馈验证新版本的稳定性逐渐增加流量。如果发生问题可以快速将流量恢复到旧版本节点。
可以看到蓝绿部署需要两套完整的生产环境适用于发布较大更新的场景。而金丝雀部署需要复杂的流量控制和监控机制适合频繁的小版本更新。
K8S中金丝雀部署
在k8s环境中我们无法直接指定具体的服务实例因此不能将流量控制到服务器级别但可以控制到service级别。
假设现在有两个服务如下
apiVersion: v1
kind: Service
metadata:name: app-v1
spec:selector:app: your-appversion: v1ports:- port: 80targetPort: 80
---
apiVersion: v1
kind: Service
metadata:name: app-v2
spec:selector:app: your-appversion: v2ports:- port: 80targetPort: 80创建一个ingress用来进行流量路由:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: app-ingressannotations:konghq.com/ingress.class: kongkonghq.com/plugins: traffic-split
spec:rules:- host: your-hosthttp:paths:- path: /pathType: Prefixbackend:service:name: app-v1port:number: 80再创建一个KongIngress来分配流量
apiVersion: configuration.konghq.com/v1
kind: KongIngress
metadata:name: app-ingress-confignamespace: your-namespace
proxy:protocols:- http- httpsroute:splits:- weight: 90service:name: app-v1port: 80- weight: 10service:name: app-v2port: 80此时10%的流量将被转发到app-v2服务继续更新KongIngress配置逐步将流量导入到v2版本的服务直至全部切到v2为止。这个过程即k8s下的canary部署。
参考资料
[1]. https://docs.konghq.com/gateway/latest/ [2]. https://zhuanlan.zhihu.com/p/698162981