Kong Api网关简介(一) 安装运行

Kong 是 Mashape 开源的高性能高可用 API 网关和 API 管理服务层。它基于 OpenResty 进行 API 管理,并提供了插件实现 API 的 AOP。最近因工作的需要研究了 Kong 的相关应用实现。

准备

kong 的官方文档提供了基于不同平台的安装方式,为了方便,这里使用 docker-compose 进行。

$ mkdir kong-gateway && cd kong-gateway
$ touch docker-compose.yml
$ mkdir config plugins postgresql

上述创建名为 kong-gateway 的目录并且进入,然后在 kong-gateway 目录中创建 docker-compose.yml 文件,并且创建了 config、 plugins、 postgresql 三个文件夹。其中, config 文件夹用于存放 kong 网关配置, plugins 文件夹用于存放自定义插件, postgresql 文件夹用于存放 postgresql 数据文件,这三个文件夹将被挂载到 docker 容器中。 docker-compose.yml 文件定义如下:

version: '3'

services:
  postgres:
    image: postgres:9.6
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_USER=kong
      - POSTGRES_DB=kong
      - POSTGRES_PASSWORD=kong
      - PGDATA=/var/lib/postgresql/data
    container_name: kong-database
    volumes:
      - ./postgresql/data:/var/lib/postgresql/data
  kong:
    image: kong:latest
    container_name: kong
    environment:
      - KONG_DATABASE=postgres
      - KONG_PG_HOST=kong-database
      - KONG_PG_USER=kong
      - KONG_PG_PASSWORD=kong
      - KONG_CASSANDRA_CONTACT_POINTS=kong-database
      - KONG_PROXY_ACCESS_LOG=/dev/stdout
      - KONG_ADMIN_ACCESS_LOG=/dev/stdout
      - KONG_PROXY_ERROR_LOG=/dev/stderr
      - KONG_ADMIN_ERROR_LOG=/dev/stderr
    ports:
      - "8000:8000"
      - "8001:8001"
      - "8443:8443"
      - "7946:7946"
      - "7946:7946/udp"
    volumes:
      - ./config:/etc/kong
      - ./plugins:/etc/kong/plugins
    depends_on:
      - postgres

config 文件夹下放置 kong 的配置文件 kong.conf,简单定义如下:

prefix = /etc/kong/

log_level = debug

proxy_listen = 0.0.0.0:8000, 0.0.0.0:8443 ssl
admin_listen = 0.0.0.0:8001, 0.0.0.0:8444 ssl

database = postgres
pg_host = 127.0.0.1
pg_port = 5432
pg_user = kong
pg_password = kong
pg_database = kong
pg_ssl = off
pg_ssl_verify = off

上述准备好后的 kong-gateway文件夹目录如下:

kong-gateway
| -- config
	| -- kong.conf
| -- plugins
| -- postgresql
| -- docker-compose.yml

启动

首先准备数据库,执行下面命令:

$ docker-compose run kong kong migrations up

执行过程中将拉取 docker-compose.yml 中定义的 postgres:9.6 镜像和 kong:latest镜像,并执行数据库迁移操作。

迁移完成后,执行下面命令,启动 kong 网关:

$ docker-compose up --no-recreate -d
Starting kong-database ... done
Creating kong          ... done

$ docker-compose ps
    Name                   Command               State                                                                Ports
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
kong            /docker-entrypoint.sh kong ...   Up      0.0.0.0:7946->7946/tcp, 0.0.0.0:7946->7946/udp, 0.0.0.0:8000->8000/tcp, 0.0.0.0:8001->8001/tcp, 0.0.0.0:8443->8443/tcp, 8444/tcp
kong-database   docker-entrypoint.sh postgres    Up      0.0.0.0:5432->5432/tcp

这时候控制台执行 curl http://127.0.0.1:8001/status可以看到管理端口输出的状态json。

运行

Servie Object

Kong 中的 Service 对象代表了上游服务的一个抽象,主要由协议、主机名、端口、路径等组成。Service 和路由关联(一个Service可能会被关联至多个路由)。更多参见Kong Admin Api Service Object

我们首先执行命令创建一个 Service, 这个 Service 名称为 baidu-service,对应的 url 地址为 http://www.baidu.com:

$ curl -i -X POST \
>   --url http://127.0.0.1:8001/services/ \
>   --data 'name=baidu-service' \
>   --data 'url=http://www.baidu.com'
HTTP/1.1 201 Created
Date: Mon, 09 Jul 2018 05:53:13 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/0.14.0
Content-Length: 259

{"host":"www.baidu.com","created_at":1531115593,"connect_timeout":60000,"id":"edbe2f0f-f11e-493b-9b59-5997e50c3de1","protocol":"http","name":"baidu-service","read_timeout":60000,"port":80,"path":null,"updated_at":1531115593,"retries":5,"write_timeout":60000}

可以通过以下命令查看所有已创建的 Service:

$ curl -i -X GET --url http://127.0.0.1:8001/services/
HTTP/1.1 200 OK
Date: Mon, 09 Jul 2018 05:55:44 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/0.14.0
Content-Length: 282

{"next":null,"data":[{"host":"www.baidu.com","created_at":1531115593,"connect_timeout":60000,"id":"edbe2f0f-f11e-493b-9b59-5997e50c3de1","protocol":"http","name":"baidu-service","read_timeout":60000,"port":80,"path":null,"updated_at":1531115593,"retries":5,"write_timeout":60000}]}

也可以根据 serviceId 查看某个具体的 Service:

$ curl -i -X GET --url http://127.0.0.1:8001/services/edbe2f0f-f11e-493b-9b59-5997e50c3de1
HTTP/1.1 200 OK
Date: Mon, 09 Jul 2018 05:57:30 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/0.14.0
Content-Length: 259

{"host":"www.baidu.com","created_at":1531115593,"connect_timeout":60000,"id":"edbe2f0f-f11e-493b-9b59-5997e50c3de1","protocol":"http","name":"baidu-service","read_timeout":60000,"port":80,"path":null,"updated_at":1531115593,"retries":5,"write_timeout":60000}

Route Object

路由定义了匹配客户端请求的规则,每一个路由关联一个 Service,每一个 Service 有可能被多个路由关联,每一个匹配到指定的路由请求将被代理到它关联的 Service 上。 更多参见Kong Admin Api Route Object

首先创建一个Route:

$ curl -i -X POST \
>   --url http://localhost:8001/services/baidu-service/routes \
>   --data 'hosts[]=baidu.com'
HTTP/1.1 201 Created
Date: Mon, 09 Jul 2018 06:24:11 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/0.14.0
Content-Length: 288

{"created_at":1531117451,"strip_path":true,"hosts":["baidu.com"],"preserve_host":false,"regex_priority":0,"updated_at":1531117451,"paths":null,"service":{"id":"edbe2f0f-f11e-493b-9b59-5997e50c3de1"},"methods":null,"protocols":["http","https"],"id":"92b5b7b7-49a9-4cb5-a595-2544e86ee519"}

可以通过以下命令查看所有已创建的 Routes:

$ curl -i -X GET --url http://localhost:8001/routes
HTTP/1.1 200 OK
Date: Mon, 09 Jul 2018 06:25:58 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/0.14.0
Content-Length: 311

{"next":null,"data":[{"created_at":1531117451,"strip_path":true,"hosts":["baidu.com"],"preserve_host":false,"regex_priority":0,"updated_at":1531117451,"paths":null,"service":{"id":"edbe2f0f-f11e-493b-9b59-5997e50c3de1"},"methods":null,"protocols":["http","https"],"id":"92b5b7b7-49a9-4cb5-a595-2544e86ee519"}]}

也可以根据 routeId 查看某个具体的 Route:

$ curl -i -X GET --url http://127.0.0.1:8001/routes/92b5b7b7-49a9-4cb5-a595-2544e86ee519
HTTP/1.1 200 OK
Date: Mon, 09 Jul 2018 06:27:32 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/0.14.0
Content-Length: 288

{"created_at":1531117451,"strip_path":true,"hosts":["baidu.com"],"preserve_host":false,"regex_priority":0,"updated_at":1531117451,"paths":null,"service":{"id":"edbe2f0f-f11e-493b-9b59-5997e50c3de1"},"methods":null,"protocols":["http","https"],"id":"92b5b7b7-49a9-4cb5-a595-2544e86ee519"}

运行

先执行如下命令执行:

$ curl -i -X GET --url http://127.0.0.1:8000/
HTTP/1.1 404 Not Found
Date: Mon, 09 Jul 2018 06:33:31 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Server: kong/0.14.0
Content-Length: 58

{"message":"no route and no API found with those values"}

发现返回的是404 Not Found,因为我们在 route 中定义了 host,所以需要在 header 中指定 host。 根据 Kong Admin Api 要求,添加 Route 时,methods、hosts、path三者至少选择一个。修改请求如下:

[xueyufish@izbp13cqwumhn3wzp2j5mqz kong-gateway]$ curl -i -X GET \
>   --url http://127.0.0.1:8000/ \
>   --header 'Host: baidu.com'
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 2381
Connection: keep-alive
Accept-Ranges: bytes
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Date: Mon, 09 Jul 2018 06:38:22 GMT
Etag: "588604c8-94d"
Last-Modified: Mon, 23 Jan 2017 13:27:36 GMT
Pragma: no-cache
Server: bfe/1.0.8.18
Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
X-Kong-Upstream-Latency: 63
X-Kong-Proxy-Latency: 34
Via: kong/0.14.0

<!DOCTYPE html>
<!--STATUS OK--><html>... 省略html内容 ...</html>

至此,一个简单的 kong 网关运行成功。但是正如 kong 官网所描述,它具备很多其他特性,后续将对重要的继续介绍。