KONG 网关简介及简单使用

Kong 网关简介及简单使用

1、kong 网关简介

Kong是在客户端和微服务端转发 API 通信的 API 网关,可以通过插件扩展功能。Kong 主要有两个重要的的组件:

  • Kong Server:基于 nginx 的服务器,用来接收 API 请求
  • Apache Cassandra:用于存储操作数据

我们可以通过增加更多的 Kong Server服务器对 Kong 服务进行水平扩展,通过前置的负载均衡器向这些机器发送分发请求。根据文档描述,两个 Cassandra 节点就足以支撑绝大多数情况,但如果网络非常拥挤,可以适当考虑增加更多的节点。

对于我们来说,Kong 中最为重要的一个特性就是可以通过插件扩展已有功能,这些插件在 API 请求响应循环的生命周期内被执行。插件使用 Lua 编写,而且 Kong 还有如下几个基础功能:

HTTP 基本认证,密匙认证,CORS(Cross-origin Resource Sharing,跨域资源共享),TCP,UDP,文件日志,API请求限流,请求转发及 Nginx 监控等等

2、docker 部署 kong

官方文档:https://hub.docker.com/_/kong/

设置网络

1
docker network create kong-net

安装数据库, PostgreSQL and Cassandra,推荐使用 postgres(版本号可自由选择)

1
2
3
4
5
6
docker run -d --name kong-database \
--network=kong-net \
-p 5432:5432 \
-e "POSTGRES_USER=kong" \
-e "POSTGRES_DB=kong" \
postgres:11.1-alpine

准备 kong 数据

1
2
3
4
5
6
docker run --rm \
--network=kong-net \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-database" \
-e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
kong:latest kong migrations bootstrap

启动kong,设置postgres 数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker run -d --name kong \
--network=kong-net \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-database" \
-e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
-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:latest

:8000 Kong 在该端口上侦听来自客户端的传入 HTTP 流量,并将其转发到上游服务

:8443 Kong 在其上侦听传入的 HTTPS 流量。此端口具有与端口 8000 类似的行为,不过他仅支持 HTTPS通信,可以通过配置文件禁用此端口

:8001 用于配置 Kong 侦听的 admin api

:8444 admin api 在其上侦听 HTTPS 流量

检查 kong 是否正常运行

1
curl -i http://localhost:8001/

安装图形化界面

1
2
3
4
5
docker run -d --name kong-dashboard \
--network=kong-net \
--link kong:kong \
-p 8081:8080 \
pgbi/kong-dashboard:v2 migrations up

3、配置服务

向 kong添加 API,我们需要先添加一个 service,即使用 kong 用来指代其管理的上游 API 和微服务的名称

我们将创建一个指向Mockbin API的服务。Mockbin是一个“回声”类型的公共网站,它将返回的请求返回给请求者,作为响应。这有助于了解Kong如何代理您的API请求。

在开始对服务提出请求之前,需要为其添加一条路由。路线指定到达香港后如何(以及是否)将请求发送到其服务。单个服务可以具有多个路由。

配置服务和路线后,您将可以使用它们通过Kong发出请求。

Kong 在port上公开了RESTful Admin API:8001。Kong的配置(包括添加服务和路由)是通过该API上的请求进行的。

1)使用 admin api添加服务

发出以下cURL请求以将您的第一个服务(指向Mockbin API)添加到Kong:

1
2
3
4
curl -i -X POST \
--url http://localhost:8001/services/ \
--data 'name=example-service' \
--data 'url=http://mockbin.org'

内容回复:

1
2
3
4
5
6
7
8
9
10
HTTP/1.1 201 Created
Date: Fri, 07 Feb 2020 09:04:51 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/2.0.1
Content-Length: 296
X-Kong-Admin-Latency: 210

{"host":"mockbin.org","created_at":1581066291,"connect_timeout":60000,"id":"1148d98c-2eeb-4988-af84-d3173080bdd9","protocol":"http","name":"example-service","read_timeout":60000,"port":80,"path":null,"updated_at":1581066291,"retries":5,"write_timeout":60000,"tags":null,"client_certificate":null}%

SERVICES API详解

1、添加 services

请求地址:/service/

请求方法:POST

请求主体:

属性 描述
name(可选) 服务名称.
protocol 该协议用于与upstream通信。它可以是http(默认)或https。
host upstream服务器的主机。
port upstream服务器端口。默认为80
path(可选) 在向upstream服务器请求中使用的路径。默认为空。
retries(可选) 在代理失败的情况下执行的重试次数。默认值是5。
connect_timeout(可选) 建立到upstream服务器的连接的超时时间。默认为60000。
write_timeout(可选) 将请求发送到upstream服务器的两个连续写操作之间的超时时间。默认为60000。
read_timeout(可选) 将请求发送到upstream服务器的两个连续读取操作之间的超时时间。默认为60000。
url(简写属性) 将协议、主机、端口和路径立即设置成简短的属性。这个属性是只写的(管理API从来不“返回”url)。

2、查找 service

请求地址:/services/{name or id}

请求方法:GET

请求主体:

属性 描述
name or id(必填) 检索的唯一标识符或服务名称。

请求地址:/routes/{route id}/service

请求方法:GET

请求主体:

属性 描述
route id(必填) 属于要检索的服务的路由的唯一标识符。

3、查找 service 列表

请求地址:/services/

请求方法:GET

请求主体:

属性 描述
offset(可选) 用于分页的游标。偏移量是定义列表中的位置的对象标识符。
size(可选,默认是100 max是1000) 每个页面返回的对象数量的限制。

4、更新 service

请求地址:/service/{name or id}

请求方法:PATCH

请求主体:

属性 描述
name or id(必填) 要更新的服务的id或name属性。

请求地址:/routes/{route id}/service

请求方法:PATCH

请求主体:

属性 描述
route id(必填) 要更新服务的路由的id属性。

5、删除 service

请求地址:/services/{name or id}

请求方法:DELETE

请求主体:

属性 描述
name or id(必填) 要删除的服务的id或name属性。

2)添加服务路线

1
2
3
curl -i -X POST \
--url http://localhost:8001/services/example-service/routes \
--data 'hosts[]=example.com'

内容回复:

1
2
3
4
5
6
7
8
9
10
HTTP/1.1 201 Created
Date: Fri, 07 Feb 2020 09:05:40 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/2.0.1
Content-Length: 429
X-Kong-Admin-Latency: 26

{"id":"535592c2-c8b5-4f40-9a37-22f1dae115b8","path_handling":"v0","paths":null,"destinations":null,"headers":null,"protocols":["http","https"],"methods":null,"snis":null,"service":{"id":"1148d98c-2eeb-4988-af84-d3173080bdd9"},"name":null,"strip_path":true,"preserve_host":false,"regex_priority":0,"updated_at":1581066340,"sources":null,"hosts":["example.com"],"https_redirect_status_code":426,"tags":null,"created_at":1581066340}%

kong 现在知道服务名称,并准备代理请求

ROUTE API详解

1、添加 route

请求地址:/routes/

请求方法:POST

请求主体:

属性 描述
protocols 这条路线应该允许的协议列表。默认情况下,它是“http”、“https”,这意味着路由接受这两种方式。当设置为“HTTPS”时,HTTP请求会被请求升级到HTTPS。通过表单编码,符号是协议=http&协议=https。使用JSON,使用数组。
methods(半可选) 与此路由相匹配的HTTP方法列表。例如: [“GET”, “POST”].至少有一个主机、路径或方法必须被设置。用表单编码参数是methods[]=GET&methods[]=OPTIONS。使用JSON,使用数组。
hosts(半可选) 与此路径匹配的域名列表。例如:example.com. 至少有一个主机、路径或方法必须被设置。用表单编码参数是 hosts[]=foo.com&hosts[]=bar.com。使用JSON,使用数组。
paths(半可选) 与此路径相匹配的路径列表。例如: /my-path.至少有一个主机、路径或方法必须被设置。用表单编码参数是 paths[]=/foo&paths[]=/bar. 使用JSON,使用数组。
strip_path(可选) 当通过一条路径匹配一条路径时,从upstream请求URL中剥离匹配的前缀。默认值为true。
preserve_host(可选) 当通过一个主机域名匹配一条路由时,在upstream请求头中使用请求主机头。默认设置为false,upstream主机头将是服务主机的主机头。
service 这条路线的服务是相关的。这是路由代理通信的地方。用表单编码参数是service.id=。如果是JSON,则使用”service”:{“id”:”“}

2、查找 route

请求地址:/routes/{id}

请求方法:GET

请求主体:

属性 描述
id(必填) 检索路由的id属性。

3、查找 route 列表

请求地址:/routes/

请求方法:GET

请求主体:

属性 描述
offset(可选) 用于分页的游标。偏移量是定义列表中的位置的对象标识符。
size(可选,默认是100 max是1000) 每个页面返回的对象数量的限制。

4、更新 route

请求地址:/routes/{id}

请求方法:PATCH

请求主体:

属性 描述
id(必填) 更新路由的id属性。

5、删除 route

请求地址:/route/{ id}

请求方法:DELETE

请求主体:

属性 描述
id(必填) 删除路由的id属性。

6、列出与 service 相关的 route

请求地址:/services/{service name or id}/routes

请求方法:GET

请求主体:

属性 描述
service name or id(必填) 要检索路由的服务的id或name属性。当使用这个API时,只有属于指定服务的路由才会被列出。

3)通过 kong 转发请求

发出以下cURL请求,以验证Kong是否正确地将请求转发到您的服务。请注意,默认情况下, Kong在port上处理代理请求:8000

1
2
3
curl -i -X GET \
--url http://localhost:8000/ \
--header 'Host: example.com'

如果成功响应,表示 kong 已经成功转发我们的请求,转发 url 地址为步骤 1 中的地址

4、启用插件

Kong的核心原则之一是其通过插件的可扩展性。插件使我们可以轻松地向服务中添加新功能或使其更易于管理。

在下面的步骤中,将配置key-auth插件以向服务添加身份验证。在添加此插件之前, 对服务的所有请求都将在上游被代理。添加并配置此插件后,只会代理具有正确密钥的请求-Kong将拒绝所有其他请求,从而保护上游服务免遭未经授权的使用。

1)配置密匙身份验证插件

1
2
3
curl -i -X POST \
--url http://localhost:8001/services/example-service/plugins/ \
--data 'name=key-auth'

注意:此插件还接受一个config.key_names参数,默认为['apikey']。它是应该在请求期间包含apikey的标头和参数名称(均受支持)的列表。

内容回复:

1
2
3
4
5
6
7
8
9
10
HTTP/1.1 201 Created
Date: Fri, 07 Feb 2020 09:15:07 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/2.0.1
Content-Length: 363
X-Kong-Admin-Latency: 52

{"created_at":1581066907,"config":{"key_names":["apikey"],"run_on_preflight":true,"anonymous":null,"hide_credentials":false,"key_in_body":false},"id":"c032c177-dac4-435b-a3b6-b39edd9c11fe","service":{"id":"1148d98c-2eeb-4988-af84-d3173080bdd9"},"enabled":true,"protocols":["grpc","grpcs","http","https"],"name":"key-auth","consumer":null,"route":null,"tags":null}%

2)确认插件配置正确

1
2
3
curl -i -X GET \
--url http://localhost:8000/ \
--header 'Host: example.com'

由于未指定所需的apikey 标题或者参数,因此响应应为 401authorized

内容回复:

1
2
3
4
5
6
7
8
9
10
HTTP/1.1 401 Unauthorized
Date: Fri, 07 Feb 2020 09:15:28 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
WWW-Authenticate: Key realm="kong"
Content-Length: 41
X-Kong-Response-Latency: 14
Server: kong/2.0.1

{"message":"No API key found in request"}%

5、添加消费者

通过 restful api 创建消费者

1
2
3
curl -i -X POST \
--url http://localhost:8001/consumers/ \
--data "username=Jason"

内容回复:

1
2
3
4
5
6
7
8
9
10
HTTP/1.1 201 Created
Date: Fri, 07 Feb 2020 09:22:44 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/2.0.1
Content-Length: 117
X-Kong-Admin-Latency: 46

{"custom_id":null,"created_at":1581067364,"id":"947b5a94-f0d1-4955-9903-d5d489be4015","tags":null,"username":"Jason"}%

注意:custom_id创建使用者以将使用者与现有用户数据库相关联时,Kong还接受参数。

CONSUMER API 详解:

1、创建Consumer

请求地址:*/consumers/*
请求方法:POST
请求主体:

属性 描述
username(半可选) 用户的唯一用户名。usernamecustom_id二选一。
custom_id(半可选) 消费者存储唯一ID - 用于现有数据库中的用户进行映射。usernamecustom_id二选一。

2、检索Consumer

请求地址:*/consumers/{username or id}*
请求方法:GET
请求主体:

属性 描述
username or id(必选) 要检索的消费者的唯一标识符或用户名。

3、Consumer列表

请求地址:*/consumers/*
请求方法:GET
请求主体:

属性 描述
id(可选) 基于消费者id字段的过滤器。
custom_id(可选) 基于消费者custom_id字段的过滤器。
username(可选) 基于消费者username字段的过滤器。
offset(可选) 用于分页的游标。偏移量是定义列表中的位置的对象标识符。
size(可选,默认是100) 每个页面返回的对象数量的限制。

4、更新Consumer

请求地址:*/consumers/{username or id}*
请求方法:PATCH
请求主体:

属性 描述
username or id(必选) 更新的唯一标识符或用户名。

请求主体:同1、添加Consumer

5、更新或创建Consumer

请求地址:*/consumers/*
请求方法:PUT
请求主体:同1、添加Consumer

6、删除Consumer

请求地址:*/consumers/{username or id}*
请求方法:DELETE
请求主体:

属性 描述
username or id(必选) 更新的唯一标识符或用户名。

2)为消费者提供关键凭证

现在,我们可以Jason通过发出以下请求为我们最近创建的使用者创建密钥:

1
2
3
curl -i -X POST \
--url http://localhost:8001/consumers/Jason/key-auth/ \
--data 'key=ENTER_KEY_HERE'

内容回复:

1
2
3
4
5
6
7
8
9
10
HTTP/1.1 201 Created
Date: Fri, 07 Feb 2020 09:27:40 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/2.0.1
Content-Length: 172
X-Kong-Admin-Latency: 56

{"created_at":1581067660,"consumer":{"id":"947b5a94-f0d1-4955-9903-d5d489be4015"},"id":"6b59a5e1-fa04-4d4b-b3b1-2e044b9c0605","tags":null,"ttl":null,"key":"ENTER_KEY_HERE"}%

3)验证消费者凭证有效

现在,我们可以发出以下请求来验证我们的Jason消费者凭证是否有效:

1
2
3
4
curl -i -X GET \
--url http://localhost:8001 \
--header "Host: example.com" \
--header "apikey: ENTER_KEY_HERE"

内容回复:

1
2
3
4
5
6
7
8
9
10
11
12
13
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 10695
Connection: keep-alive
Server: Cowboy
Etag: W/"29c7-XG+PICJmz/J+UYWt5gkKqqAUXjc"
Vary: Accept-Encoding
Date: Fri, 07 Feb 2020 09:28:04 GMT
Via: kong/2.0.1
X-Kong-Upstream-Status: 200
X-Kong-Upstream-Latency: 746
X-Kong-Proxy-Latency: 1523
Kong-Cloud-Request-ID: 3a1112d6c34f47aeb5df4ba2435b0f70

如果正常响应表示该消费者请求被kong成功转发并返回数据


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!