Traefik 路由规则及中间件 Traefik Middlewares 的配置

系统环境:

  • Traefik 版本:v2.2.0
  • Kubernetes 版本:1.18.2
  • 操作系统版本:CentOS 7.8

参考地址:

一、什么是 Traefik

Traefik 是一款开源的边缘路由器,现在本人主要要作用于 kubernetes 中对外的网关,即 Ingress 路由器,可以很轻松的配置其路由规则,让 Kubernetes 外部流量涌入。并且,还支持如 Zipkin、Jaeger 等链路追踪功能,简单好用。

二、什么是 Traefik 路由规则

首先,当部署完后启动 Traefik 时,定义了入口点(端口号和对应的端口名称),然后 Kubernetes 集群外部就可以通过访问 Traefik 服务器地址和配置的入口点对 Traefik 服务进行访问,在访问时一般会带上 “域名” + “入口点端口”,然后 Traefik 会根据域名和入口点端口在 Traefik 路由规则表中进行匹配,如果匹配成功,则将流量发送到 Kubernetes 内部应用中与外界进行交互。这里面的域名与入口点与对应后台服务关联的规则,即是 Traefik 路由规则。

 

 

三、什么是 Traefik Middlewares 中间件

Traefik Middlewares 是一个处于路由和后端服务之前的中间件,在外部流量进入 Traefik,且路由规则匹配成功后,将流量发送到对应的后端服务前,先将其发给中间件进行一些列处理(类似于过滤器链 Filter,进行一系列处理),例如,添加 Header 头信息、鉴权、流量转发、处理访问路径前缀、IP 白名单等等,经过一个或者多个中间件处理完成后,再发送给后端服务,这个就是中间件的作用。

了解什么是 Traefik Middlewares 之前,最好先了解上面提到的 Traefik Ingress 路由规则。

四、如何配置 Traefik 路由规则

在 Kubernetes 中 Traefik 支持 CRD 和 Ingress 两种方式进行路由规则配置,这里配置 Http 和 Https 两种方式为例进行演示。

  • (1)、配置 Traefik Dashboard 的 HTTP 路由规则为例,使用域名 traefik.ziji.work 与其后端服务关联。
  • (2)、配置 Kubernetes Dashboard 的 HTTPS 路由规则为例,使用域名 cloud.ziji.work 与其后端服务关联。

注意:本人部署 Traefik 时候指定了 80 端口的进入点名称是 “web”,而 443 端口的进入点名称为 “websecure”,部署 traefik 时可能这个进入点名称不同,下面的路由规则中设置进入点也不一样,这点需要注意下。

1、方式一:使用 Traefik CRD 配置路由规则

基于 HTTP 路由路由规则:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: traefik-dashboard-route
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`traefik.ziji.work`)
    kind: Rule
    services:
      - name: traefik
        port: 8080

基于 HTTPS 路由路由规则

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: kubernetes-dashboard-route
spec:
  entryPoints:
  - websecure
  tls:
    secretName: cloud-mydlq-tls
  routes:
  - match: Host(`cloud.ziji.work`) 
    kind: Rule
    services:
      - name: kubernetes-dashboard
        port: 443

2、方式二:使用 Kubernetes Ingress 配置路由规则

注意:使用该方式需要 Traefik 版本 ≥ 2.2

基于 HTTP 路由路由规则

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: traefik-dashboard-ingress
  namespace: kube-system
  annotations:
    kubernetes.io/ingress.class: traefik            
    traefik.ingress.kubernetes.io/router.entrypoints: web         ##指定 Traefik 中进入点
spec:
  rules:
  - host: traefik.ziji.work                                 
    http:
      paths:
      - path: /              
        backend:
          serviceName: traefik
          servicePort: 8080

基于 HTTPS 路由路由规则

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kubernetes-dashboard-ingress
  namespace: kube-system
  annotations:
    kubernetes.io/ingress.class: traefik                  
    traefik.ingress.kubernetes.io/router.tls: "true"              ##指定使用 tls 证书方式
    traefik.ingress.kubernetes.io/router.entrypoints: websecure   ##指定 Traefik 中进入点
spec:
  tls:
  - secretName: cloud-mydlq-tls
  rules:
  - host: cloud.ziji.work                               
    http:
      paths:
      - path: /                                     
        backend:
          serviceName: kubernetes-dashboard
          servicePort: 443

五、如何配置 Traefik Middlewares

Traefik Middlewares 中间件是用于流量进入 Traefik 且通过定义的路由规则后,转发到对应后端服务前,在这期间对该流量进行加工的操作,它支持:

  • 重试、压缩、缓冲、断路器
  • header 管理、错误页、中间件链
  • 服务限流、同一主机并发请求限制
  • 基本认证、IP 白名单、摘要认证、转发鉴权验证
  • regex 请求重定向、scheme 请求重定向、请求 URL 替换、regex 请求 URL 替换、删除 URL 前缀、regex 删除 URL 前缀、添加 URL 前缀

这里使用常用 Middleware 来进行演示配置中间件,示例如下:

1、去除请求路径前缀中间件

例如,有一个路由规则中配置的域名路径为 “{host}/one”,traefik 进行路由规则进行流量转发时,也会带上这个前缀作为相对路径发送到后端服务中,而对后端服务来说,一般都是以 “/” 根路径作为相对路径的,如果带上这个路径到后端服务中,那么后端服务则变成以 “/one” 作为相对路径,显然,这样会导致状态码 404 错误。所以,很多时候我们需要去掉这个前缀。

使用去除前缀中间件去除前缀,方便配置一个域名多个二级路径这种需求,中间件写法如下:

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: test-stripprefix
spec:
  stripPrefix:
    prefixes:
      - /one
  • prefixes:设置去除的 url 前缀。

2、正则表达式匹配去除请求路径前缀中间件

上面说了为什么去除前缀,也写了个去除前缀中间件,不过很多时候我们有这样一个需求,就是通过一个域名访问多个服务,这样易于统一服务的入口,而 traefik 中也提供了这种批量匹配去除前缀的功能,就是通过正则表达式方式批量匹配对应路径的前缀,然后去除,即 stripPrefixRegex 中间件。

使用正则表达式,只要正则表达式匹配成功就能将前缀去除,这样的好处就是可以多个路由规则使用该中间件进行去除前缀,方便配置通用的一个域名多个的二级路径这种需求,中间件写法如下:

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: test-stripprefixregex
spec:
  stripPrefixRegex:
    regex:
      - "/foo/[a-z0-9]+/[0-9]+/"
  • prefixes:使用正则表达式匹配需要去除的 url 前缀。

3、转发鉴权验证中间件

在 traefik 中支持简单的第三方鉴权,当访问某个服务路由规则匹配后,则可以使用该转发鉴权验证中间件将请求转发到第三方服务进行鉴权。当第三方鉴权服务返回 Http 200 状态码 traeifk 则认为有权限访问后续服务,不拦截。如果鉴权服务返回非 200 状态码 traefik 认为无权访问,进行拦截。这种中间件的写法如下:

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: test-auth
spec:
  forwardAuth:
    address: https://example.com/auth
    trustForwardHeader: true
  • address:将权限鉴定转发到第三方进行验证,设置转发的地址。
  • trustForwardHeader:信任全部 X-Forwarded-* headers 信息。

更多中间件的使用方法可也查看 Traefik 官方文档 Middlewares 部分:https://docs.traefik.io/middlewares/overview/

六、Traefik 路由规则中如何使用 Traefik Middleware

上面演示了如何简单的配置 Traefik Middlewares,这里我们在路由规则中使用这些中间件,同样也是基于 CRD 和 Ingress 两种路由规则进行演示。

1、使用去除前缀中间件

(1)、创建去除前缀中间件

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: stripprefix-middleware               ##设置中间件名称,要和路由规则中的名称一致 
  namespace: mydlqcloud                      ##指定 Namespace
spec:
  stripPrefix:
    prefixes:
      - /foo                                 ##设置要去除的前缀

(2)、创建路由规则并使用中间件

CRD 方式:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: test-route
  namespace: mydlqcloud                      ##指定 Namespace
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`www.ziji.work`) && PathPrefix(`/foo`)
      kind: Rule
      services:
        - name: test-service
          port: 80
      middlewares:
        - name: stripprefix-middleware       ##指定使用的中间件

Ingress 方式:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  namespace: mydlqcloud                      ##指定 Namespace
  annotations:
    kubernetes.io/ingress.class: traefik
    traefik.ingress.kubernetes.io/router.entrypoints: web
    ##指定使用的 Middleware,规则是 {namespace名称}-{middleware名称}@{资源类型}
    traefik.ingress.kubernetes.io/router.middlewares: mydlqcloud-stripprefix-middleware@kubernetescrd
spec:
  rules:
  - host: www.ziji.work                                 
    http:
      paths:
      - path: /foo            
        backend:
          serviceName: test-service
          servicePort: 80

2、正则表达式去除前缀中间件

(1)、创建正则表达式去除中间件

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: regex-stripprefix-middleware
  namespace: mydlqcloud
spec:
  stripPrefixRegex:
    regex:
      - ^/[a-zA-Z0-9-]+                       ##设置正则表达式

(2)、创建路由规则并使用中间件

CRD 方式:

## IngressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: test-route1
  namespace: mydlqcloud
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`www.ziji.work`) && PathPrefix(`/one`)   ##路由规则1
      kind: Rule
      services:
        - name: test-service1
          port: 80
      middlewares:
        - name: regex-stripprefix-middleware
    - match: Host(`www.ziji.work`) && PathPrefix(`/two`)   ##路由规则2
      kind: Rule
      services:
        - name: test-service2
          port: 80
      middlewares:
        - name: regex-stripprefix-middleware

Ingress 方式:

## Ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress1
  namespace: mydlqcloud
  annotations:
    kubernetes.io/ingress.class: traefik
    traefik.ingress.kubernetes.io/router.entrypoints: web
    traefik.ingress.kubernetes.io/router.middlewares: mydlqcloud-regex-stripprefix-middleware@kubernetescrd
spec:
  rules:
  - host: www.ziji.work                                 
    http:
      paths:
      - path: /one              ##路由规则1  
        backend:
          serviceName: test-service1
          servicePort: 80
      - path: /two              ##路由规则2
        backend:
          serviceName: test-service2
          servicePort: 80

3、转发鉴权验证中间件

(1)、创建转发鉴权中间件

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: authentication-middleware            ##设置中间件名称
  namespace: mydlqcloud                      ##指定 Namespace
spec:
  forwardAuth:
    address: "http://auth-service/auth"
    trustForwardHeader: true

(2)、创建路由规则并使用中间件

CRD 方式:

## IngressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: test-route
  namespace: mydlqcloud
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`www.ziji.work`) && PathPrefix(`/foo`)
      kind: Rule
      services:
        - name: test-service
          port: 80
      middlewares:
        - name: authentication-middleware

Ingress 方式:

## IngressRoute
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  namespace: mydlqcloud
  annotations:
    kubernetes.io/ingress.class: traefik
    traefik.ingress.kubernetes.io/router.entrypoints: web
    traefik.ingress.kubernetes.io/router.middlewares: mydlqcloud-authentication-middleware@kubernetescrd
spec:
  rules:
  - host: www.ziji.work                                 
    http:
      paths:
      - path: /foo            
        backend:
          serviceName: test-service
          servicePort: 80

七、Traefik 路由规则中使用多个 Traefik Middlewares

这里再演示一下使用一个路由中如何使用两个中间件,使用去除路径前缀与鉴权配合:

1、创建转发鉴权与去除前缀中间件

## Middleware1
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: authentication-middleware            ##设置中间件名称
  namespace: mydlqcloud                      ##指定 Namespace
spec:
  forwardAuth:
    address: "http://auth-service/auth"
    trustForwardHeader: true
---
## Middleware2
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: regex-stripprefix-middleware
  namespace: mydlqcloud
spec:
  stripPrefixRegex:
    regex:
      - ^/[a-zA-Z0-9-]+                       ##设置正则表达式

2、创建路由规则并使用中间件

CRD 方式:

## IngressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: test-route
  namespace: mydlqcloud                      ##指定 Namespace
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`www.ziji.work`) && PathPrefix(`/foo`)
      kind: Rule
      services:
        - name: test-service
          port: 80
      middlewares:
        - name: authentication-middleware    ##指定使用的中间件1
        - name: regex-stripprefix-middleware ##指定使用的中间件2

Ingress 方式:

## IngressRoute
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  namespace: mydlqcloud                      ##指定 Namespace
  annotations:
    kubernetes.io/ingress.class: traefik
    traefik.ingress.kubernetes.io/router.entrypoints: web
    ##指定使用的 Middleware,规则是 {namespace名称}-{middleware名称}@{资源类型},如果使用多个中间件,则逗号隔开
    traefik.ingress.kubernetes.io/router.middlewares: mydlqcloud-authentication-middleware@kubernetescrd,mydlqcloud-regex-stripprefix-middleware@kubernetescrd
spec:
  rules:
  - host: www.ziji.work                                 
    http:
      paths:
      - path: /foo            
        backend:
          serviceName: test-service
          servicePort: 80

 

Traefik 官方文档

 

发表评论