微服务 API 网关 -Kong 详解
一 概述
Kong是一个clould-native、快速的、可扩展的、分布式的微服务抽象层(也称为API网关、API中间件或在某些情况下称为服务网格)框架。更确切地说,Kong是一个在Nginx中运行的Lua应用程序,并且可以通过lua-nginx模块实现。Kong不是用这个模块编译Nginx,而是与[OpenResty](https://openresty.org/)一起发布,[OpenResty](https://openresty.org/)已经包含了lua-nginx-module。OpenResty 不是 Nginx的分支,而是一组扩展其功能的模块。
这为可插拔架构奠定了基础,可以在运行时启用和执行Lua脚本(称为“插件”)。因此,我们认为Kong是微服务架构的典范:它的核心是实现数据库抽象,路由和插件管理。插件可以存在于单独的代码库中,并且可以在几行代码中注入到请求生命周期的任何位置。Kong作为开源项目在2015年推出,它的核心价值是高性能和可扩展性。
Kong被广泛用于从初创企业到全球5000家公司以及政府组织的生产环境中。
如果构建Web、移动或IoT(物联网)应用,可能最终需要使用通用的功能来实现这些应用。Kong充当微服务请求的网关(或侧车),通过插件能够提供负载平衡、*日志记录、身份验证、速率限制、转换*等能力。
一个service可以创建多个routes,routes就相当于前端配置,可以隐藏业务真正的接口地址,service指定后端真实的转发接口地址,在kong上进行认证/鉴权/日志/分析/监控等控制。
二 特性
云原生(Cloud-Native):Kong可以在Kubernetes或物理环境上运行;
动态负载平衡(*Dynamic Load Balancing*):跨多个上游服务的负载平衡业务。
基于哈希的负载平衡(Hash-based Load Balancing):一致的散列/粘性会话的负载平衡。
断路器(Circuit-Breaker):智能跟踪不健康的上游服务。
健康检查(Health Checks):主动和被动监控您的上游服务。
服务发现(*Service Discovery*):解决如Consul等第三方DNS解析器的SRV记录。
无服务器(Serverless):从Kong中直接调用和保证AWS或OpenWhisk函数安全。
WebSockets:通过WebSockets与上游服务进行通信。
OAuth2.0:轻松的向API中添加OAuth2.0认证。
日志记录(*Logging*):通过HTTP、TCP、UDP记录请求或者相应的日志,存储在磁盘中。
安全(*Security*):ACL,Bot检测,IPs白名单/黑名单等。
系统日志(Syslog):记录信息到系统日志。
SSL:为基础服务或API设置特定的SSL证书。
监视(*Monitoring)*:能够实时对关键负载和性能指标进行监控。
转发代理(Forward Proxy):使端口连接到中间透明的HTTP代理。
认证(*Authentications*):支持HMAC,JWT和BASIC方式进行认证等等。
速率限制(*Rate-limiting*):基于多个变量的阻塞和节流请求。
转换(Transformations):添加、删除或操作HTTP请求和响应。
缓存(*Caching*):在代理层进行缓存和服务响应。
命令行工具(CLI):能够通过命令行控制Kong的集群。
REST API:可以通过REST API灵活的操作Kong。
GEO复制:在不同的区域,配置总是最新的。
故障检测与恢复(*Failure Detection & Recovery*):如果Cassandra节点失效,Kong并不会受影响。
群集(Clustering):所有的Kong节点会自动加入群集,并更新各个节点上的配置。
可扩展性(Scalability):通过添加节点,实现水平缩放。
性能(Performance):通过缩放和使用Nigix,Kong能够轻松处理负载。
插件(Plugins):基于插件的可扩展体系结构,能够方便的向Kong和API添加功能。
三 依赖组件
Kong部署在Nginx和Apache Cassandra或PostgreSQL等可靠技术之上,并提供了易于使用的RESTful API来操作和配置系统。下面是Kong的技术逻辑图。基于这些技术,Kong提供相关的特性支持:
3.1 Nginx
经过验证的高性能基础;
HTTP和反向代理服务器;
处理低层级的操作。
3.2 OpenRestry
支持Lua脚本;
拦截请求/响应生命周期;
基于Nginx进行扩展。
3.3 Clustering&Datastore
支持Cassandra或PostgreSQL数据库;
内存级的缓存;
支持水平扩展。
3.4 Plugins
使用Lua创建插件;
功能强大的定制能力;
与第三方服务实现集成。
3.5 Restful Administration API
通过Restful API管理Kong;
支持CI/CD&DevOps;
基于插件的可扩展。
四 架构图
五 部署
5.1 物理服务器部署
5.1.1 配置yum源
5.1.2 数据库安装
Kong支持PostgreSQL v9.5+和Cassandra 3.x.x作为数据存储。
按照文档安装PostgreSQL v11: https://www.postgresql.org/download/linux/redhat/
5.1.2 启动kong
在无数据库模式配置Kong,一旦Kong启动,访问Admin API的/
根端点已验证它是否在没有数据库的情况下运行。
5.1.3 安装konga
konga为目前最先版本的kong的dashboard,由于kong-dashboard目前为更新适应新版本的kong,推荐使用konga
konga带来的一个最大的便利就是可以很好地通过UI观察到现在kong的所有的配置,并且可以对于管理kong节点情况进行查看、监控和预警,konga主要特性如下:
多用户管理
管理多个Kong节点
电子邮件异常信息通知
管理所有Kong Admin API
使用快照备份,还原和迁移Kong节点
使用运行状况检查监控节点和API状态
轻松的数据库集成(MySQL,postgresSQL,MongoDB)
node安装
安装konga
配置
访问
IP:1338,默认用户:admin,密码:adminadminadmin
配置链接kong, http://localhost:8001
5.2 docker中运行
5.2.1 Docker中部署
5.2.2 docker-compose部署
创建虚拟网络
后续的应用及数据库都使用这个虚拟网络。
编写docker-compose.yaml
使用docker-compose up 命令启动服务。会发现启动时报数据库错误,这是因为kong 使用的postgres 数据还需要进行初始化才能使用。
初始化数据库
一定要在创建数据库容器之后,并且保持数据库的Docker容器在运行状态,再执行初始化数据库,数据库初始化成功后,再次使用docker-compose up -d 启动服务就可以了。
验证
dashboard
另外,也可以安装一个Kong的客户端来验证。在安装有Docker引擎的操作系统上执行如下的命令:
1.0之后的kong-dashboard就已经不兼容了,建议使用konga
5.2.3 安装kong-dashboard
Kong Dashboard 3.3.0 is only partially compatible with Kong 0.13. It does not support the new Service and Route objects introduced in Kong 0.13.
通过docker安装一个Kong-Dashboard,安装完成后,通过浏览器访问:
5.3 kubernetes部署
5.3.1 前置条件
已有Kubernetes 1.6+环境;
已部署helm客户端和tiller服务端(请参考:https://docs.helm.sh/using_helm/#installing-helm)
- 在Kubernetes中创建了具备足够权限访问权限的service account;
- 并通过此service account在Kubernetes部署了tiller服务端(请参考:https://docs.helm.sh/using_helm/#role-based-access-control)。
5.3.2 helm char配置
下表列示了Kong chart的配置参数和默认值:
| 参数 | 说明 | 默认值 |
| :----------------------------: | :----------------------------------------------------------: | :------------: |
| image.repository | Kong image | kong
|
| image.tag | Kong image version | 0.14.1
|
| image.pullPolicy | Image pull policy | IfNotPresent
|
| image.pullSecrets | Image pull secrets | null
|
| replicaCount | Kong instance count | 1
|
| admin.useTLS | Secure Admin traffic | true
|
| admin.servicePort | TCP port on which the Kong admin service is exposed | 8444
|
| admin.containerPort | TCP port on which Kong app listens for admin traffic | 8444
|
| admin.nodePort | Node port when service type is NodePort
| |
| admin.type | k8s service type, Options: NodePort, ClusterIP, LoadBalancer | NodePort
|
| admin.loadBalancerIP | Will reuse an existing ingress static IP for the admin service | null
|
| admin.loadBalancerSourceRanges | Limit admin access to CIDRs if set and service type is LoadBalancer
| []
|
| admin.ingress.enabled | Enable ingress resource creation (works with proxy.type=ClusterIP) | false
|
| admin.ingress.tls | Name of secret resource, containing TLS secret | |
| admin.ingress.hosts | List of ingress hosts. | []
|
| admin.ingress.path | Ingress path. | /
|
| admin.ingress.annotations | Ingress annotations. See documentation for your ingress controller for details | {}
|
| proxy.useTLS | Secure Proxy traffic | true
|
| proxy.servicePort | TCP port on which the Kong Proxy Service is exposed | 8443
|
| proxy.containerPort | TCP port on which the Kong app listens for Proxy traffic | 8443
|
| proxy.nodePort | Node port when service type is NodePort
| |
| proxy.type | k8s service type. Options: NodePort, ClusterIP, LoadBalancer | NodePort
|
| proxy.loadBalancerSourceRanges | Limit proxy access to CIDRs if set and service type is LoadBalancer
| []
|
| proxy.loadBalancerIP | To reuse an existing ingress static IP for the admin service | |
| proxy.ingress.enabled | Enable ingress resource creation (works with proxy.type=ClusterIP) | false
|
| proxy.ingress.tls | Name of secret resource, containing TLS secret | |
| proxy.ingress.hosts | List of ingress hosts. | []
|
| proxy.ingress.path | Ingress path. | /
|
| proxy.ingress.annotations | Ingress annotations. See documentation for your ingress controller for details | {}
|
| env | Additional Kong configurations | |
| runMigrations | Run Kong migrations job | true
|
| readinessProbe | Kong readiness probe | |
| livenessProbe | Kong liveness probe | |
| affinity | Node/pod affinities | |
| nodeSelector | Node labels for pod assignment | {}
|
| podAnnotations | Annotations to add to each pod | {}
|
| resources | Pod resource requests & limits | {}
|
| tolerations | List of node taints to tolerate | []
|
5.3.3 安装chart
启用数据库需要先安装pvc
5.3.4 验证Kong(命令行)
通过执行下面的命令,进入Kong的容器:
并在kong中执行如下的命令:
如果kong正常运行的话,应该会返回一些内容。
通过浏览器查看
curl 创建一个service
创建一个routes
curl测试
六 使用
6.1 CLI使用
提供的CLI(命令行界面Command Line Interface)允许启动,停止和管理Kong实例。CLI可以管理本地节点(如在当前计算机上)。
通用参数
命令
更详细的CLI参数可参考:CLI Reference
6.1 配置一个实例
配置一个访问 www.baidu.com/ 的接口API,实际使用时会对接后端的业务数据接口地址。
路由定义了匹配客户端请求的规则,每一个路由关联一个 Service,每一个 Service 有可能被多个路由关联,每一个匹配到指定的路由请求将被代理到它关联的 Service 上,参见Kong Admin Api Route Object。
kong admin接口
6.1.1 创建服务
服务是上游服务的抽象,可以是一个应用,或者具体某个接口。
命令行方式创建服务:
postman创建
6.1.2 创建路由
在刚才创建的baidu-service的服务上创建路由
Curl 创建
postman创建
6.1.3 测试
curl测试
这时候访问kong的proxy地址
时,如果host为baidu.com,请求被转发到
http://baidu.com
postman测试
测试post
利用konga web界面操作更为方便。
6.2 插件使用
插件是用来扩展API的,例如为API添加认证、设置ACL、限制速率等、集成oauth、ldap等。
6.2.1 认证-JWT
上面的配置,只要知道Router的地址,就可以访问获取数据,我们要把API加入身份认证。如果API面对不是具体用户,而是其他的系统,可以使用JWT来进行系统间身份认证,使用Kong JWT插件就可能完成这功能。JWT 插件要在对应的Router上进行启用。
fee36521-e549-410f-8986-9fbba02219c1 是创建的service的ID。
这时再通过Postman 访问上面的接口就会提示:
创建用户
用户生成JWT凭证
返回凭证信息,也可以通过 get 方法查询凭证信息
使用key和secret在 jwt.io/ 可以生成jwt 凭证信息.
再通过postman 访问,就可以看到数据了。
6.2.2 安全-ACL
JWT插件可以保护API能够被受信用户访问,但不能区别哪个用户能够访问哪个API,即接口权限问题,我们使用ACL 插件解决这个问题.
在上面定义好的路由上启用acl 插件,指定白名单,
此时再访问api,会提示不能访问这个服务。
只需将kongauser1这个用户关联到白名单内的go2cloud-api-group组里即可。
再次访问接口,能正常返回数据。
现在就可以对网关暴露的接口进行身份认证和权限控制了。
6.2.3 认证-key-auth
为服务或者路由创建key-auth,插件即可以应用在service上,也可以应用在route上
获取到的结果为:
创建用户,在用户中配置apk-key
postman测试,认证方式为apikey
6.2.4 认证-basic auth
在service或route上创建basic auth
在consumers中创建basic credentials
利用postman测试
6.2.5 安全-ip-restriction
顾名思义,用来设置接口IP的黑白名单
在service或routes上创建basic auth,配置黑白名单
postman测试
将调用方的IP地址加入到白名单中,可以正常访问。
6.2.6 安全-bot-detection
为routes或service 创建bot-detection,'User-Agent: PostmanRuntime/7.15.2',将postman客户端加入到黑名单进行测试,默认规则详见:https://github.com/Kong/kong/blob/master/kong/plugins/bot-detection/rules.lua
6.2.7 流控-rate-limiting
在service或route配置流量控制
定义每秒/分钟/小时/天/月/年可以发送的请求数量
限制可以根据服务或路由/ip地址/证书
策略可以利用本地,集群或redis
例如配置限制每天只能调用10次
postman测试
6.2.8 流控-request/size-limiting/termination
request-size-limiting 请求payload size限制
request-termination 这允许(暂时)阻止API或消费者
此处只简单列举几个插件,更详细的插件请查看,
测试在k8s中目前还没有将konga做成helm部署,后期可以自己将起做成charts方便在k8s中图形化管理。
参考链接
https://docs.konghq.com/0.13.x/admin-api/#route-object
https://www.kubernetes.org.cn/4952.html
https://www.lijiaocn.com/tags/all.html#kong
https://github.com/Kong/kong
https://docs.konghq.com/install/kubernetes/
https://github.com/PGBI/kong-dashboard
版权声明: 本文为 InfoQ 作者【雪雷】的原创文章。
原文链接:【http://xie.infoq.cn/article/ba0f7503c73b86126017c0d32】。文章转载请联系作者。
评论 (1 条评论)