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

19次阅读

共计 5376 个字符,预计需要花费 14 分钟才能阅读完成。

插件介绍

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 - <<EOF
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: echo
spec:
  rules:
  - http:
      paths:
      - path: /echo
        backend:
          serviceName: echo
          servicePort: 8080
EOF

访问测试:

% 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 - <<EOF
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: httpbin
spec:
  rules:
  - http:
      paths:
      - path: /bar
        backend:
          serviceName: httpbin
          servicePort: 80
EOF

访问测试:

% 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 - <<EOF
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: rl-by-ip
config:
  minute: 5
  limit_by: ip
  policy: local
plugin: rate-limiting
EOF
% kubectl get kongplugin
NAME       PLUGIN-TYPE     AGE
rl-by-ip   rate-limiting   16s

更新 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 - <<EOF
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: ip-restriction
config:
  whitelist:
  - 10.131.2.1
plugin: ip-restriction
EOF

上节在 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 - <<EOF
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: global-rate-limit
  labels:
    global: "true"
config:
  minute: 150
  limit_by: ip
  policy: local
plugin: rate-limiting
EOF

上面已在 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插件中心:https://docs.konghq.com/hub/;
  • kubernetes-ingress-controller文档:https://github.com/Kong/kuber…;
  • using-kongplugin-resource.md:https://github.com/Kong/kuber…;
正文完
 0