1、Kong的概述
Kong是一个clould-native、快速的、可扩展的、分布式的微服务抽象层(也称为API网关、API中间件或在某些情况下称为服务网格)框架。Kong作为开源项目在2015年推出,它的核心价值是高性能和可扩展性。Kong被广泛用于从初创企业到全球5000家公司以及政府组织的生产环境中。
如果构建Web、移动或IoT(物联网)应用,可能最终需要使用通用的功能来实现这些应用。Kong充当微服务请求的网关(或侧车),通过插件能够提供负载平衡、日志记录、身份验证、速率限制、转换等能力。
2、功能特性
- 云本土化(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添加功能。
3、Kong依赖的技术
Kong部署在Nginx和Apache Cassandra或PostgreSQL等可靠技术之上,并提供了易于使用的RESTful API来操作和配置系统。下面是Kong的技术逻辑图。基于这些技术,Kong提供相关的特性支持:
- Nginx:
- 经过验证的高性能基础;
- HTTP和反向代理服务器;
- 处理低层级的操作。
- OpenRestry:
- 支持Lua脚本;
- 拦截请求/响应生命周期;
- 基于Nginx进行扩展。
- Clustering&Datastore:
- 支持Cassandra或PostgreSQL数据库;
- 内存级的缓存;
- 支持水平扩展。
- Plugins:
- 使用Lua创建插件;
- 功能强大的定制能力;
- 与第三方服务实现集成。
- Restful Administration API:
- 通过Restful API管理Kong;
- 支持CI/CD&DevOps;
- 基于插件的可扩展。
4、使用Helm在Kubernetes上部署Kong
4.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)。
4.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 | [] |
4.3 安装Chart
通过执行如下的命令,在Kubernetes中部署Kong:
$ helm install --name my-release stable/kong
4.4 验证Kong(命令行)
通过执行下面的命令,进入Kong的容器:
kubectl exec -it my-release-kong-d448dc869-fblbk sh
并在kong中执行如下的命令:
curl http://localhost:8001
如果kong正常运行的话,应该会返回一些内容。
4.5 验证Kong(客户端)
另外,也可以安装一个Kong的客户端来验证。在安装有Docker引擎的操作系统上执行如下的命令:
docker run -d -p 8080:8080 pgbi/kong-dashboard start --kong-url http://10.0.32.172:31177
通过docker安装一个Kong-Dashboard,安装完成后,通过浏览器访问:
5、使用
5.1 注册服务
在此部分将会向kong添加一个API,为了做到这一点,首先需要往Kong中添加一个服务。我们将创建一个指向Mockbin API的服务,Mockbin是一个“echo”类型的公共网站,它将返回的请求作为响应返回给请求者。通过此示例有助于了解Kong是如何代理API请求。在开始对服务进行请求之前,需要为服务添加一个路由。路由指定在到达Kong之后如何向服务发送请求,单个服务可以有多个路由。在配置了服务和路由之后,就能够通过Kong对服务进行请求。Kong公开了RESTful Admin API:8001,Kong的配置(包括添加服务和路由)是通过对该API的请求进行的。
5.1.1 注册服务
服务实体是上游服务中的每一个抽象。服务的示例将是数据转换微服务、计费API等。服务的主要属性是它的URL(其中Kong应该代理流量),它可以被设置为单个字符串或单独指定它的协议、主机、端口和路径。
通过执行下面的命令,将名称为example-servic,地址为url=http://mockbin.org的服务注册到Kong上。
$ curl -i -X POST --url http://localhost:8001/services/ --data 'name=example-service' --data 'url=http://mockbin.org'
执行命令后,返回的结果类似下面的内容:
HTTP/1.1 201 Created Content-Type: application/json Connection: keep-alive { "host":"mockbin.org", "created_at":1519130509, "connect_timeout":60000, "id":"92956672-f5ea-4e9a-b096-667bf55bc40c", "protocol":"http", "name":"example-service", "read_timeout":60000, "port":80, "path":null, "updated_at":1519130509, "retries":5, "write_timeout":60000 }
5.1.2 创建路由
路由实体定义用来匹配客户端请求的规则。每个路由都与一个服务相关联,并且一个服务可能具有与其相关的多个路由。匹配给定路由的每个请求都将被代理到其关联的服务。通过路由和服务的组合(以及它们之间的关注点分离)提供了强大的路由机制,通过这种机制,可以在Kong中定义细粒度入口点,从而实现基础设施的不同上游服务。
$ curl -i -X POST --url http://localhost:8001/services/example-service/routes --data 'hosts[]=example.com'
返回结果如下所示:
HTTP/1.1 201 Created Content-Type: application/json Connection: keep-alive { "created_at":1519131139, "strip_path":true, "hosts":[ "example.com" ], "preserve_host":false, "regex_priority":0, "updated_at":1519131139, "paths":null, "service":{ "id":"79d7ee6e-9fc7-4b95-aa3b-61d2e17e7516" }, "methods":null, "protocols":[ "http", "https" ], "id":"f9ce2ed7-c06e-4e16-bd5d-3a82daef3f9d" }
在为服务创建好路由后,Kong就做好对外提供了此服务的准备。
5.1.3 通过Kong转达对于服务的请求
发出以下curl请求,以验证Kong是否正确地将请求转发给服务。注意,缺省情况下,Kong处理端口上的代理请求:8000:
$ curl -i -X GET --url http://localhost:8000/ --header 'Host: example.com'
成功的响应意味着Kong将http://localhost:8000发出的请求转发到在步骤#1中配置的url(https://mockbin.org),并将返回响应结果。通过在curl请求中定义的头,Kong知道如何做的这一点:
- Host:
5.2 注册API
在此部分将把API添加到Kong层,以让Kong管理API。
5.2.1 使用Admin API注册
通过下面的命令将API (Mockbin) 注册到Kong中:
$ curl -i -X POST --url http://localhost:8001/apis/ --data 'name=example-api' --data 'hosts=example.com' --data 'upstream_url=http://mockbin.org'
5.2.2 验证API
注册后返回的信息应该如下所示:
HTTP/1.1 201 Created Content-Type: application/json Connection: keep-alive { "created_at": 1488830759000, "hosts": [ "example.com" ], "http_if_terminated": false, "https_only": false, "id": "6378122c-a0a1-438d-a5c6-efabae9fb969", "name": "example-api", "preserve_host": false, "retries": 5, "strip_uri": true, "upstream_connect_timeout": 60000, "upstream_read_timeout": 60000, "upstream_send_timeout": 60000, "upstream_url": "http://mockbin.org" }
5.1.3 通过Kong转发请求
发出以下curl请求,以验证Kong是否正确地将请求转发给服务。注意,缺省情况下,Kong处理端口上的代理请求:8000:
$ curl -i -X GET --url http://localhost:8000/ --header 'Host: example.com'
成功的响应意味着Kong将http://localhost:8000发出的请求转发到在步骤#1中配置的url(https://mockbin.org),并将返回响应结果。通过在curl请求中定义的头,Kong知道如何做的这一点:
- Host:
6、Admin API
6.1 API Object
API对象描述了一个由Kong公开的API。当使用者从代理端口(Proxy port)调用它时,Kong需要知道如何获取此API。每个API对象必须指定主机(hosts)、uris和方法(method)的一些组合。Kong将把所有对API的请求委托给指定的upstream URL。
{ "created_at": 1488830759000, "hosts": [ "example.org" ], "http_if_terminated": false, "https_only": false, "id": "6378122c-a0a1-438d-a5c6-efabae9fb969", "name": "example-api", "preserve_host": false, "retries": 5, "strip_uri": true, "upstream_connect_timeout": 60000, "upstream_read_timeout": 60000, "upstream_send_timeout": 60000, "upstream_url": "http://httpbin.org" }
6.1.1 注册API
请求地址:/apis/
请求方法:POST
属性 | 描述 |
---|---|
name |
API的名称 |
hosts semi-optional |
以逗号分隔,指向API的域名列表。例如:example.com。至少应该指定主机、uri或方法中的一个。 |
uris semi-optional |
以逗号分隔,指向API的uri前缀列表。例如: /my-path。至少应该指定主机、uri或方法中的一个。 |
methods semi-optional |
以逗号分隔,指向API的HTTP方法列表。例如: GET,POST。至少应该指定主机、uri或方法中的一个。 |
upstream_url |
指向API服务器的基本目标URL,这个URL将被用于代理请求。例如: https://example.com. |
strip_uri optional |
当通过一个uris前缀匹配一个API时,要从upstream URI中去掉匹配的前缀。默认值:true。 |
preserve_host optional |
当通过一个主机域名匹配一个API时,请确保请求主机头被转发到upstream服务。默认值:false,upstream主机头将从配置的upstream_url中提取出来。 |
retries optional |
在代理失败的情况下执行的重试次数。默认值是5。 |
upstream_connect_timeout optional |
建立连接到upstream服务的连接超时时间。默认为60000。 |
upstream_send_timeout optional |
The timeout in milliseconds between two successive write operations for transmitting a request to your upstream service Defaults to 60000 . |
upstream_read_timeout optional |
The timeout in milliseconds between two successive read operations for transmitting a request to your upstream service Defaults to 60000 . |
https_only optional |
如果希望仅使用HTTPS提供API(默认情况下是8443),那么就可以启用该参数。默认值:false。 |
http_if_terminated optional |
在执行HTTPS通信时,考虑一下X-Forwarded-Proto header。默认值: false |
6.1.2 检索API
请求地址:/apis/{name or id}
请求方法:GET
属性 | 描述 |
---|---|
name or id(必填) | 要检索的API的唯一标识符或名称。 |
6.1.3 API列表
请求地址:/apis/
请求方法:GET
属性 | 描述 |
---|---|
id(可选) | 基于api id字段的过滤器。 |
name(可选) | 基于api name字段的过滤器。 |
upstream_url(可选) | 基于api upstream_url字段的过滤器。 |
retries(可选) | 基于api retries字段的过滤器。 |
offset(可选) | 用于分页的游标。偏移量是定义列表中的位置的对象标识符。 |
size(可选,默认是100) | 每个页面返回的对象数量的限制。 |
6.1.4 更新API
请求地址:/apis/{name or id}
请求方法:GET
属性 | 描述 |
---|---|
name or id required |
The unique identifier or the name of the API to delete |
6.1.5 删除API
请求地址:/apis/{name or id}
请求方法:DELETE
PATH参数:
属性 | 描述 |
---|---|
name or id
required |
删除API的名称或唯一的标识符。 |
6.2 插件对象(Plugin Object)
插件实体表示将在HTTP请求/响应生命周期期间执行的插件配置。通过插件,可以为服务添加功能,例如身份验证或速率限制。可以通过访问Kong Hub找到需要的插件,以及有关如何安装和值的更多信息。当添加一个插件配置到服务后,客户端向该服务发出的每个请求都将会运行添加的插件。如果需要为特定消费者将插件调整为不同的值,可以通过指定 consumer_id值来实现:
{ "id": "4d924084-1adb-40a5-c042-63b19db421d1", "service_id": "5fd1z584-1adb-40a5-c042-63b19db49x21", "consumer_id": "a3dX2dh2-1adb-40a5-c042-63b19dbx83hF4", "name": "rate-limiting", "config": { "minute": 20, "hour": 500 }, "enabled": true, "created_at": 1422386534 }
6.2.1 优先级
插件将始终只被运行一次,即每次请求只运行一次。但是它所运行的配置取决于它所配置的实体。当插件应用于具有不同配置的不同实体时,存在一个优先顺序来运行插件。经验法则是:插件越具体,所配置的实体数量越多,优先级越高。
当一个插件被多次配置时,完整优先纪顺序是:
示例:如果rate-limiting插件应用了两次(具有不同的配置):对于服务(插件配置A)和对于消费者(插件配置B),则对此消费者进行身份验证的请求将运行插件配置B并忽略A.但是,请求不认证此消费者将回退到运行插件配置A.请注意,如果禁用配置B(其enabled
标志设置为false
),配置A将应用于否则将匹配配置B的请求。
6.2.2 添加插件
可以通过下面的几种方式添加插件:
- 对于每个服务/路由和消费者。不要设置consumer_id,而是设置service_id或route_id。
- 适用于每个服务/路由和特定消费者。只有设定consumer_id。
- 适用于每个消费者和特定服务。仅设置service_id(警告:某些插件只允许设置route_id)
- 对于每个消费者和特定的路由。仅设置route_id(警告:某些插件只允许设置service_id)
- 对于特定的服务/路由和消费者。设置service_id/route_id和consumer_id。
请注意,并非所有插件都允许指定consumer_id。
6.2.2.1 Request Body
属性 | 描述 |
---|---|
name | 要添加的插件的名称。目前,插件必须分别安装在每个Kong实例中。 |
consumer_id 可选的 |
使用者的唯一标识符,用于覆盖传入请求中此特定使用者的现有设置。 |
config.{property} | 插件的配置属性,可以在Kong Hub的插件文档页面找到。 |
enabled | 是否应用插件。默认值:true。 |
Response
HTTP 201 Created
{ "id": "4d924084-1adb-40a5-c042-63b19db421d1", "service_id": "5fd1z584-1adb-40a5-c042-63b19db49x21", "consumer_id": "a3dX2dh2-1adb-40a5-c042-63b19dbx83hF4", "name": "rate-limiting", "config": { "minute": 20, "hour": 500 }, "enabled": true, "created_at": 1422386534 }
参考资料
1.《Route Object》地址:https://docs.konghq.com/0.13.x/admin-api/#route-object;
2.《Configuring a Service》地址:https://docs.konghq.com/0.14.x/getting-started/configuring-a-service/
3.《Kong and Kong Enterprise on Kubernetes》地址:https://docs.konghq.com/install/kubernetes/?_ga=2.256537099.1475189429.1544400620-1563374863.1537379250
作者简介:
季向远,北京神舟航天软件技术有限公司。本文版权归原作者所有。