共计 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…;