一、安装
说明:
1)由于不想用PostgreSQL和Cassandra数据库,所以我选择的是无DB模式(DB-less mode)
2)选择Docker模式安装,避免环境配置问题。
Docker安装步骤如下:
docker pull kong:2.3.3 docker network create kong-net mkdir -p /hot_data/kong1 docker run -d --name kong1 \ --network=kong-net \ -v /hot_data/kong1:/usr/local/kong/declarative \ -e "KONG_DATABASE=off" \ -e "KONG_DECLARATIVE_CONFIG=/usr/local/kong/declarative/kong.yml" \ -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_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \ -p 8000:8000 \ -p 8443:8443 \ -p 8001:8001 \ -p 8444:8444 \ kong:2.3.3 # 查看启动日志 docker logs kong1 # 启动成功后验证 curl -i http://localhost:8001/
具体参见官方文档:https://docs.konghq.com/install/docker/
3)选择一个kong admin API的图形界面,由于KongA已经停更,我选择了pocketdigi/kong-admin-ui
安装方法如下:
docker run -d --name kong-admin-ui -p 8899:80 pocketdigi/kong-admin-ui:0.5.2
然后访问http://localhost:8899即可。
二、配置
在当前目录下创建kong.yml文件,内容如下:
_format_version: "2.1" _transform: true upstreams: - name: talos targets: - target: 192.168.66.11:6600 weight: 100 services: - name: talos-service host: talos routes: - name: talos-route service: talos-service hosts: ["hello.talos.com"]
然后执行admin api可以让配置生效(实时生效、无需重启):
curl -X POST -F "config=@kong.yml" --url http://192.168.66.11:8001/config
其中@kong.yml是指该文件路径为当前目录,后面http url为kong admin的地址。
配置说明:
四个概念:Upstream、Target、Service、Route
Target:是最终处理请求的Backend服务。
Upstream:Target集合的负载均衡策略。
Services:是多个Upstream的集合,根据Route转发。
Route:是请求的转发规则,按照Hostname和PATH,将请求转发给Service。
下面是一个完整配置例子:
(注意,下面是例子是基于DB模式的,对于DB-less模式,只能通过kong.yml文件来配置,然后post提交kong.yml即可)
# 创建一个upstream $ curl -X POST http://kong:8001/upstreams \ --data "name=address.v1.service" # 给upstream添加两个target $ curl -X POST http://kong:8001/upstreams/address.v1.service/targets \ --data "target=192.168.34.15:80" \ --data "weight=100" $ curl -X POST http://kong:8001/upstreams/address.v1.service/targets \ --data "target=192.168.34.16:80" \ --data "weight=50" # 创建一个把Blue上游作为目标的Service $ curl -X POST http://kong:8001/services/ \ --data "name=address-service" \ --data "host=address.v1.service" \ --data "path=/address" # 最后,为Service添加Route $ curl -X POST http://kong:8001/services/address-service/routes/ \ --data "hosts[]=address.mydomain.com"
然后在操作系统的hosts路由里面绑定:
192.168.66.11(kong地址) address.mydomain.com
然后访问:http://address.mydomain.com:8000/,即可达到Target,(8000为Kong的路由端口)
如果要做“蓝绿发布”的话,上面的配置为“蓝”,下面再添加一套“绿”配置如下:
# 为地址服务v2,创建一个新的Green upstream $ curl -X POST http://kong:8001/upstreams \ --data "name=address.v2.service" # 给upstream添加两个目标 $ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \ --data "target=192.168.34.17:80" --data "weight=100" $ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \ --data "target=192.168.34.18:80" \ --data "weight=100"
然后把Service的Upstream切换为“绿”配置,流量就“全绿”了。
# 将服务从Blue环境转换为Green环境, v1 -> v2 $ curl -X PATCH http://kong:8001/services/address-service \ --data "host=address.v2.service"
类似地,“金丝雀”发布,只要改变Target的权重即可,比如最开始为100:0,然后改成95:5,然后改成80:20,就可以逐步控制流量的进入,如下所示。
# 第一个目标权重 800 $ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \ --data "target=192.168.34.17:80" \ --data "weight=900" # 第二个目标权重 200 $ curl -X POST http://kong:8001/upstreams/address.v2.service/targets \ --data "target=192.168.34.18:80" \ --data "weight=200"
实际上Upstream和Service的配置,类似于下面的Nginx配置:
upstream address.v1.service { server 192.168.34.15:80; server 192.168.34.16:80; } server { listen 8000; location / { proxy_pass http://address.v1.service; } }
在网关集成登录身份验证:
由于是微服务应用,所以后端不使用Session,最常用的方案就是JWT Token。
Kong对 JWT身份验证 支持较好。
首先,Kong支持多种身份验证方式(Basic Auth、JWT、Key Auth等),通用认证流程如下:
向一个API或全局添加AUTH插件(此插件不作用于consumers);
创建一个consumer对象;
为consumer提供指定的验证插件方案的身份验证凭据;
现在,只要有请求进入Kong,都将检查其提供的身份验证凭据(通常在header或者url参数中,取决于auth类型),如果该请求无法被验证或者验证失败,则请求会被锁定,不执行向上有服务转发的操作。
但是,上述的一般流程并不是总是有效的。譬如,当使用了外部验证方案(比如LDAP)时,KONG就不会(不需要)对consumer进行身份验证。
什么是Consumers?
最简单的理解和配置consumer的方式是,将其于用户进行一一映射,即一个consumer代表一个用户(或应用)。但是对于KONG而言,这些都无所谓。consumer的核心原则是你可以为其添加插件,从而自定义他的请求行为。所以,或许你会有一个手机APP应用,并为他的每个版本都定义一个consumer,又或者你又一个应用或几个应用,并为这些应用定义统一个consumer,这些都无所谓。这是一个模糊的概念,他叫做consumer,而不是user!万万要区分开来,且不可混淆。
具体JWT验证方式就不讲了,直接看官方文档吧。值得说明的是,Kong的JWT验证是标准的验证方法,而且还支持对过期时间进行检验。如果需要防重放等特殊验证方法,则标准组件不适合,只能自己写插件。
插件开发:
基于Lua语言,有相关的Demo工程和文档,以及很多现成的插件代码可以参考。
容易实现的功能有:内存缓存,连接Redis,发送HTTP请求。但暂时没找到连接MySQL的例子。
另外,也可以使用Golang写插件,官方曾经弄了一个方案及Demo,但案例不多,还处于非常原始阶段。