traefik初探——route部分的高级用法

半日闲 2020年11月18日 35次浏览

traefik支持多种匹配器,
本次来探究一下traefikroute部分的匹配器
如下

image-20201118172406327

测试环境

准备kubernetes集群

部署好traefik

准备2个后端服务以及对应的svc

环境准备可参考前一个traefik系列文档,链接如下

  1. traefik初探——ingressroute用法

  2. traefik初探——灰度发布

高级用法

基于Host的匹配

ingressrouteyaml文件如下

[root@a file-yaml]$ cat busybox-ingressroute-host.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: busybox-httpd-ingressroute
  namespace: default
spec:
  entryPoints:
    - web
  routes:
  - match: Host("httpd-v1.a.b", "test.a.b")
### Host匹配器支持多个域名同时匹配
    kind: Rule
    services:
    - name: busybox-httpd-v1
      port: 80
  - match: HostRegexp("v2.a.b", "{subdomain:[xyz]}.a.b")
### HostRegexp匹配器同样支持多个域名匹配,但是更加强大,同时支持正则表达式域名的匹配
    kind: Rule
    services:
    - name: busybox-httpd-v2
      port: 80

增加/etc/hosts/文件中域名解析

[root@a file-yaml]$ cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost6 localhost6.localdomain6 localhost6.localdomain

192.168.1.8 httpd-v1.a.b
192.168.1.8 v2.a.b
192.168.1.8 test.a.b
192.168.1.8 x.a.b
192.168.1.8 y.a.b
192.168.1.8 z.a.b

使用kubectl apply -f busybox-ingressroute-host.yaml创建后,

使用curl访问后端服务

如下

image-20201118184802335

可以看到基于不同的域名,可访问到不同的后端

基于Headers的匹配

ingressrouteyaml文件如下

[root@a file-yaml]$ cat busybox-ingressroute-headers.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: busybox-httpd-ingressroute
  namespace: default
spec:
  entryPoints:
    - web
  routes:
  - match: Host("httpd.a.b") && PathPrefix("/") && Headers("version", "v1")
    kind: Rule
    services:
    - name: busybox-httpd-v1
      port: 80
  - match: Host("httpd.a.b") && PathPrefix("/") && Headers("version", "v2")
    kind: Rule
    services:
    - name: busybox-httpd-v2
      port: 80

注意go中使用的双引号包裹字符串,而不是单引号

使用kubectl apply -f busybox-ingressroute-headers.yaml创建后,

使用curl -H "Version: v1" -v http://httpd.a.b/30080访问后端服务

其中-H为添加访问时的Headers

如下

image-20201118173157462

可以看到使用不同的Headers时,访问了不同的后端服务

基于Method的匹配

ingressrouteyaml文件如下

[root@a file-yaml]$ cat busybox-ingressroute-method.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: busybox-httpd-ingressroute
  namespace: default
spec:
  entryPoints:
    - web
  routes:
  - match: Host("httpd.a.b") && Method("GET")
    kind: Rule
    services:
    - name: busybox-httpd-v1
      port: 80
  - match: Host("httpd.a.b")
    kind: Rule
    services:
    - name: busybox-httpd-v2
      port: 80

由于后端服务使用的是busybox中的httpd,其中仅仅只有1个index.html,没有设置其他的接口,因此PUTDELETEPOSTPATCH均无法完成,提示501 Not Implemented,仅仅只能测试GET的方法

使用kubectl apply -f busybox-ingressroute-method.yaml创建后,

使用curl -X GET http://httpd.a.b:20080/访问,

如下

image-20201118182158145

显示访问到busybox-httpd-v1的服务,与配置中的ingressroute一致

匹配符号与(&&)和或(||

ingressrouteyaml文件如下

[root@a file-yaml]$ cat busybox-ingressroute-and-or.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: busybox-httpd-ingressroute
  namespace: default
spec:
  entryPoints:
    - web
  routes:
  - match: (Host("httpd.a.b") && Headers("version", "is_v1")) || (Host("httpd.a.b") && Headers("version", "not_v2"))
### host匹配httpd.a.b并且headers中有version=is_v1的请求或者host匹配http.a.b并且headers中有version=not_v2的请求,转发到服务busybox-httpd-v1上
    kind: Rule
    services:
    - name: busybox-httpd-v1
      port: 80
  - match: Host("httpd.a.b")
### host匹配httpd.a.b的请求转发到服务busybox-httpd-v2上
    kind: Rule
    services:
    - name: busybox-httpd-v2
      port: 80

使用kubectl apply -f busybox-ingressroute-and-or.yaml创建后,

使用curl访问后端服务

如下

image-20201118183500443

可以看到访问到了不同的结果,测试正常

使用 AND(&&)和 OR(||)运算符来结合多个匹配器,也可以使用括号

报错记录

yaml文件中使用了'(单引号),导致traefik出现日志,提示非法字符

time="2020-11-18T09:20:52Z" level=error msg="error while parsing rule Host(`httpd.a.b`) && PathPrefix(`/`) && Head('version'): 1:46: illegal rune literal" entryPointName=web routerName=default-busybox-httpd-ingressroute-47ba86a6b9f4755ff5fd@kubernetescrd

关于我

工作:运维工程师

方向:目前专注于微服务,容器技术 以及Devops方面!

个人微信公众号:

gongzhonghaopic

ps:哈哈哈,希望有需求的大佬带上我一起进步啊!!!