在K8S中使用Kong插件来扩展网关功能

插件介绍

kong内部使用openrestry作为反向代理,其可通过lua扩展nginx功能,官方已编写了大量的插件,如用于限流处理的Rate Limiting插件,用于IP黑白名单限制的IP Restriction插件,更多插件详见Kong Hub插件中心。

测试用例

测试用例1

echo测试用例可以返回服务器与客户端访问信息,便于我们调试并观察。

% kubectl create namespace demo
% kubectl run echo --image=googlecontainer/echoserver:1.10
% kubectl expose deploy echo --port=8080 --target-port=8080

% kubectl create -f - <

访问测试:

% kubectl get ing echo
NAME      HOSTS     ADDRESS         PORTS     AGE
echo      *         134.194.18.11   80        1m

% curl 134.194.18.11:30569/echo
...
Request Information:
        client_address=10.128.2.246
        method=GET
        real path=/
        query=
        request_version=1.1
        request_scheme=http
        request_uri=http://134.194.18.11:8080/

Request Headers:
        accept=*/*
        connection=keep-alive
        host=134.194.18.11:30569
        user-agent=curl/7.29.0
        x-forwarded-for=10.131.2.1
        x-forwarded-host=134.194.18.11
        x-forwarded-port=8000
        x-forwarded-proto=http
        x-real-ip=10.131.2.1
...

测试用例2

httpbin测试用例主要用于观察http header头部响应信息,使用如下命令创建:

% kubectl run httpbin --image=kennethreitz/httpbin
% kubectl expose deploy httpbin --port=80

% kubectl apply -f - <

访问测试:

% kubectl get ing httpbin
NAME      HOSTS     ADDRESS         PORTS     AGE
httpbin   *         134.194.18.11   80        1m

% curl -I 134.194.18.11:30569/bar/status/200
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
Server: gunicorn/19.9.0
Date: Mon, 23 Sep 2019 09:50:56 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
X-Kong-Upstream-Latency: 3
X-Kong-Proxy-Latency: 1
Via: kong/1.3.0

使用插件

注意:Kong插件可设置在Service、Ingress(Route)、Global(全局)上。

在Service处设置插件

注意:本节使用rate-limiting插件来做访问限流处理,如示例限制每IP每分钟只能进行5次访问。

通过CRD:KongPlugin创建一个rate-limiting的插件。注意:因示例以db-less模式安装kong,故policy需设置为local。

% kubectl apply -f - <

更新Service添加plugins.konghq.com注释:

% kubectl patch svc httpbin \
  -p '{"metadata":{"annotations":{"plugins.konghq.com": "rl-by-ip\n"}}}'
% kubectl get svc echo -o yaml|more
...
apiVersion: v1
kind: Service
metadata:
  annotations:
    plugins.konghq.com: |
      rl-by-ip
...

访问测试:

## 通过ingress访问:
# 连续访问5次:
% curl -I 134.194.18.11:30569/bar/status/200
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
Server: gunicorn/19.9.0
Date: Tue, 24 Sep 2019 02:26:11 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
X-RateLimit-Limit-minute: 5                        # 每分钟允许访问5次
X-RateLimit-Remaining-minute: 0                    # 剩余可访问次数为0
X-Kong-Upstream-Latency: 2
X-Kong-Proxy-Latency: 0
Via: kong/1.3.0

# 后续访问失败
% curl -I 134.194.18.11:30569/bar/status/200
HTTP/1.1 429 Too Many Requests                     # 访问失败
Date: Tue, 24 Sep 2019 02:26:12 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Content-Length: 37
X-RateLimit-Limit-minute: 5
X-RateLimit-Remaining-minute: 0
Server: kong/1.3.0

## 通过svc访问:
# 不经过ingress,通过svc访问无限流:
% curl -I httpbin.demo.svc.cluster.local/status/200
HTTP/1.1 200 OK
Server: gunicorn/19.9.0
Date: Tue, 24 Sep 2019 02:28:55 GMT
Connection: keep-alive
Content-Type: text/html; charset=utf-8
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Content-Length: 0

注意

  • 在service上添加plugins.konghq.com注释后,kong ingress control会动态更新kong网关,而后kong插件在ingress处得以实施,其不影响service访问;
  • 对于rate-limiting插件,以db-less模式部署时其计数信息存储在内存中,故若部署多个kong实例的话,每实例对于计数信息是独占的,故对于限流处理是不严格的,详情参考官方手册;
  • 本例是通过NodePort方式暴露kong网关供集群外访问,故kong网关所面对的真实客户端IP可能是非我们所预期的。如使用OKD的redhat/openshift-ovs-networkpolicy网络插件,kong网关所见的是真实客户端IP为节点上tun0的IP地址,此时不论从哪个客户端访问服务,其共享限流处理,一个解决方法是通过HostNetwork方式将kong暴露到集群外部;
# 使用echo应用来验证以上所述,如从任何客户端访问此地址可发现真实IP均为主机上的tun0网卡IP
% curl 134.194.18.11:30569/echo
...
Request Headers:
        accept=*/*
        connection=keep-alive
        host=134.194.18.11:30569
        user-agent=curl/7.29.0
        x-forwarded-for=10.131.2.1            # 应用所见到的真实客户端IP地址
        x-forwarded-host=134.194.18.11
        x-forwarded-port=8000
        x-forwarded-proto=http
        x-real-ip=10.131.2.1                  # 应用所见到的真实客户端IP地址
...

% ip a|grep 10.131.2.1
    inet 10.131.2.1/23 brd 10.131.3.255 scope global tun0

在Ingress处设置插件

本节使用IP Restriction对客户端做IP白名单访问限制。

如上所见,通过NodePort暴露的kong网关,其面对的客户端IP地址为每K8S节点上的tun0网卡地址,故此时对IP做黑白名单访问限制并非如我们预期的那样,但对于本文来说,重点不在此插件用途上。

如下限制仅可通过134.194.18.11这台主机访问httpdbin服务,创建插件如下所示。注意:此处白名单IP地址为tun0网卡上的地址。

% kubectl apply -f - <

上节在Service处添加了插件注释,此处将在Ingress处添加插件注释:

% kubectl patch ing httpbin \
  -p '{"metadata":{"annotations":{"plugins.konghq.com": "ip-restriction\n"}}}'

最后,通过不同的节点访问可发现仅能从134.194.18.11访问:

# 可访问
% curl -I 134.194.18.11:30569/bar/status/200
HTTP/1.1 200 OK
...

# 被墙,无法访问
% curl -I 134.194.18.9:30569/bar/status/200
HTTP/1.1 403 Forbidden

配置Global全局插件

全局插件影响kong网关上的所有服务,如下配置全局插件对所有API做限流处理。

% kubectl apply -f - <

上面已在httpbin的service做了每分钟5次限流处理,而echo并为做任何限流处理,此时访问观察可有如下发现:

# 全局策略在echo ingress上生效:
% curl -I 134.194.18.11:30569/echo
...
X-RateLimit-Limit-minute: 150
X-RateLimit-Remaining-minute: 149
...

# 全局策略优先级较低,故在ingress、service上设置的同类型插件优先级高。
% curl -I 134.194.18.11:30569/bar/status/200
...
X-RateLimit-Limit-minute: 5
X-RateLimit-Remaining-minute: 4
...

参考文档

你可能感兴趣的:(kong,kubernetes)