kong 学习随记

模式

  • db
  • dbless

install

1
2
3
4
5
6
7
8
9
10
11
12
13
14
docker run -d --name kong \
-v "kong.yaml:/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:latest
  • plugins –> module
  • comsumer –> 消费者目前只看到用作auth认证用
  • services –> upstream
  • routes –> server

debug 模式

1
curl -H "X-Kong-Debug: 1" http://localhost:8000

注入环境变量

从配置文件中加载属性时,Kong还将寻找同名的环境变量。声明前缀KONG_并大写可以覆盖默认配置。
example:

1
2
$ export KONG_DATABASE=off
使用dbless 模式启动kong

注入nginx变量

前缀为的条目nginx_http_将注入到整体http 块指令中。

前缀为的条目nginx_proxy_将注入到server处理Kong代理端口的block指令中。

前缀为的条目nginx_admin_将注入到server处理Kong的Admin API端口的block指令中。

example:

1
2
3
4
$ export KONG_NGINX_HTTP_OUTPUT_BUFFERS="4 64k"

将会在nginx的http 代码段中加入一条
output_buffers="4 64k"

HOST传递

preserve_host: true 将会传递request原始的host,相当于proxy_set_header host $host

expamle:

1
2
3
4
5
services:
- name: test
preserve_host: true
url: http://mockbin.org


request header区分路由

注意:headers键是逻辑键AND,其值是逻辑键OR。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
routes:
- name: test
service: test
hosts: ["x.t.xiemx.com"]
headers: { "version": ["v1","v2"]}


Documents curl localhost:8000 -H version:v1 -H host:x.t.xiemx.com -I
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, 03 Jan 2020 03:19:08 GMT
Via: kong/1.4.2
X-Kong-Upstream-Status: 200
X-Kong-Upstream-Latency: 517
X-Kong-Proxy-Latency: 34
Kong-Cloud-Request-ID: eeb277b4d0df3eb242e92dc0c669f8bc

Documents curl localhost:8000 -H version:v2 -H host:x.t.xiemx.com -I
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, 03 Jan 2020 03:19:17 GMT
Via: kong/1.4.2
X-Kong-Upstream-Status: 200
X-Kong-Upstream-Latency: 566
X-Kong-Proxy-Latency: 2
Kong-Cloud-Request-ID: f3eaf8e27f3d3f9510f1c0c4619df035

Documents curl localhost:8000 -H version:v3 -H host:x.t.xiemx.com -I
HTTP/1.1 404 Not Found
Date: Fri, 03 Jan 2020 03:19:23 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Content-Length: 48
X-Kong-Response-Latency: 0
Server: kong/1.4.2


path优先级

  • 用路径前缀代理时,最长的路径将首先被评估
  • regex_priority 优先级

src/dest ip白名单

sources/destinations路由属性仅适用于TCP和TLS路线。它允许通过传入连接IP、网段或端口源的列表来匹配路由

1
2
3
4
5
6
7
8
9
10
service: TCPService
protocols:
- tls
- tcp
sources:
- { ip: 1.1.1.1/32, port: 1234 }
- ip: 127.0.0.0/8
destinations:
- { ip: 2.2.2.2/32, port: 1234 }
- ip: 10.0.0.0/8

strip_path 转发时删除路径

1
2
3
4
5
6
7
{
"paths": ["/service"],
"strip_path": true,
}

request_url -> /service/1/
proxy_url -> /1/

Kong proxy时默认处理的HEADER

  • Host:
  • Connection: keep-alive,以允许重用上游连接。
  • X-Real-IP: ,其中$remote_addr变量的名称与ngx_http_core_module提供的名称相同。$remote_addr可能被ngx_http_realip_module覆盖。
  • X-Forwarded-For: , 访问路径。
  • X-Forwarded-Proto: ,客户端使用的协议。使用ngx_http_core_module $scheme提供的变量的值。
  • X-Forwarded-Host: ,客户端发送的主机名。
  • X-Forwarded-Port: ,服务器的端口。使用ngx_http_core_module $server_port变量的值。

Kong Response headers

nginx 接收到upstream 的响应只会执行header-filter阶段将下面的header封装进header,后续会在执行body—filter阶段

  • Via: kong/x.x.x,x.x.x使用的Kong版本在哪里
  • X-Kong-Proxy-Latency: ,Kong从客户端接收请求到将请求发送到上游服务之间的时间(以毫秒为单位)。
  • X-Kong-Upstream-Latency: ,Kong等待上游服务响应的第一个字节的时间(以毫秒为单位)。

负载均衡

  • DNS负载均衡(ttl=0)

    • SRV record
    • A record
    • CNAME record

    优先级:

    • LAST(最后一次成功的类型) -> SRV -> A -> CNAME
    • 可以在Kong的配置文件中修改,默认dns_order:LAST,SRV,A,CNAME

    问题:

    • DNS可能不会返回所有的记录,导致下游服务器负载不均衡
  • Ring-balancer

    • upstream

      • service中host=”upstream_name”使用的名字,使用方法同nginx类似
      • upstream 需要预先分配一个slots,target会根据weight分配到slots上,默认upstream的slots=10000,范围(1 - 65536)。
      • 插槽数越多,随机分布越好,但是更改的开销就越大(添加/删除目标)
      • 当插槽数量更改时,将需要重建
      • which can be overwritten before proxying, using upstream’s property host_header
    • target

      • 实际upstream中使用的主机地址,等同于nginx upstream中的server指令,支持定义weight
      • 当target使用域名时,会将域名进行解析,然后将每条记录都设置到slots上,切遵循DNS TTL过期时间,去重复查询
      • 如果存在SRV记录,会优先使用SRV 记录的weight/port
  • 负载均衡算法

    • HASH(如下hash key)

      • none 不使用哈希,而采用weighted-round-robin(默认值)。
      • cookie
      • ip
      • header
      • consumer
    • WRR(weighted-round-robin)

    PS: upstream 中的target 如未指定port则使用requst 请求中的port 不会使用,service中定义的port


健康检测

  • active
    主动发出http/https request轮询target

  • passive
    分析backend response的状态码,不需要指定URL等参数

    PS: interval=0时禁止,healthcheck可以同时开启被动检测,已实现断路功能,并开启主动检测中的unhealthcheck实现target故障自愈后自动加入


kong cluster

  • 集群之间的节点流量不会自动负载均衡,需要在node前面有一个负载均衡器

  • 由于性能的原因,node不会在proxy流量时去链接PG,而是将数据cache在内存中,多node集群中需要保证节点的数据同步更新

    • db_update_frequency: 5 #node节点去db中同步数据的间隔,数据刷新间隔
    • db_update_propagation: 0 #如果后端是分布式数据库的话,则需要配置这个值。此值应该等于分布式数据库内部传播数据最终达到数据一致的时间。如果设置这个值,数据库更新时间将会为db_update_frequency + db_update_propagation,并且设置的节点也会等待一个propagation时间再去update cache
    • db_cache_ttl: 0 #防止invalid event事件node没有接收到而错过更新,可以设置一个主动过期时间