Traefik是一个开源的可以使服务发布变得轻松有趣的边缘路由器。它负责接收你系统的请求,然后使用合适的组件来对这些请求进行处理。
image.png
除了众多功能之外,Traefik的与众不同之处还在于它会自动发现你服务的配置。当Traefik在检查你的服务时,会找到服务的相关信息并找到合适的服务来满足对应的请求。

Traefik兼容所有主流的集群技术,如k8s、docker、doker swarm、aws、mesos、marathon等等;并且可以同事处理多种方式。

使用Traefik,不需要维护或者同步一个独立的配置文件,因为一切都会自动配置,实时操作的(无需重新启动,不会中断连接)。使用Traefik,可以花更多的时间在系统的开发和新功能上,而不是在配置和维护工作状态上花费时间。

核心概念

Traefik是一个边缘路由器,是整个平台的大门,拦截并路由每个传入的请求:它知道所有的逻辑和规则,这些规则确定哪些服务处理哪些请求;传统的反向代理需要一个配置文件,其中包含路由到你服务的所有可能路由,而Traefik会实时检测服务并自动更新路由规则,可以自动服务发现。
image.png
首先,当启动Traefik时,需要定义entrypoints(入口点),然后根据连接到这些entrypoints的路由来分析传入的请求,查看他们是否与一组规则相匹配,如果匹配,则路由可能会将请求通过一系列中间件转换过后再转发到你的服务上去。在了解Traefik之前有几个核心概念需要了解:

  • Providers:用来自动发现平台上的服务,可以是编排工具、容器引擎或者是key-value存储等,比如docker、k8s、file
  • Entrypoints:监听传入的流量(端口等…),是网络的入口点,它们定义了接收请求的端口(HTTP或者TCP)
  • Routers:分析请求(host、path、headers、SSL….),负责将传入请求连接到可以处理这些请求的服务上去
  • Services:将请求转发给你的应用(Load balancing…),负责配置如何获取最终将处理传入请求的实际服务。
  • Middlewares:中间件,用来修改请求或者根据请求来做出一些判断(authentication,ratelimiting,headers….),中间件被附件到路由上,是一种在请求发送到你的服务之前(或者在服务的响应发送到客户端之前)调整请求的一种方法。

安装

使用Traefik2.3.6版本

在Traefik中的配置可以使用两种不同的方式:

  • 动态配置:完全动态的路由配置
  • 静态配置:启动配置

静态配置中的元素(这些元素不会经常变更)连接到providers并定义Traefik将要监听的entrypoints。

Traefik中有三种方式定义静态配置:在配置文件中、在命令行参数中、通过环境变量传递

动态配置包含定义系统如何处理请求的所有配置内容,这些配置是可以改变的,而且是无缝热更新的,没有任何请求中断或连接损耗。

使用helm来快速安装traefik,首先获取Helm Chart包:

  1. git clone https://github.com/traefik/traefik-helm-chart

创建一个定制的values配置文件:

# values-prod.yaml
# Create an IngressRoute for the dashboard
ingressRoute:
  dashboard:
    enabled: false  # 禁用helm中渲染的dashboard,我们自己手动创建

# Configure ports
ports:
  web:
    port: 8000
    hostPort: 80  # 使用 hostport 模式
    # Use nodeport if set. This is useful if you have configured Traefik in a
    # LoadBalancer
    # nodePort: 32080
    # Port Redirections
    # Added in 2.2, you can make permanent redirects via entrypoints.
    # https://docs.traefik.io/routing/entrypoints/#redirection
    # redirectTo: websecure
  websecure:
    port: 8443
    hostPort: 443  # 使用 hostport 模式

# Options for the main traefik service, where the entrypoints traffic comes
# from.
service:  # 使用 hostport 模式就不需要Service了
  enabled: false

# Logs
# https://docs.traefik.io/observability/logs/
logs:
  general:
    level: DEBUG

tolerations:   # kubeadm 安装的集群默认情况下master是有污点,需要容忍这个污点才可以部署
- key: "node-role.kubernetes.io/master"
  operator: "Equal"
  effect: "NoSchedule"

nodeSelector:   # 固定到master1节点(该节点才可以访问外网)
  kubernetes.io/hostname: "master1"

用 hostport 模式将 Traefik 固定到 master1 节点上,因为只有这个节点有外网 IP,所以这里 master1 是作为流量的入口点。直接使用上面的 values 文件安装 traefik:

➜ helm install --namespace kube-system traefik ./traefik -f ./values-prod.yaml
NAME: traefik
LAST DEPLOYED: Thu Dec 24 11:23:51 2020
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
➜ kubectl get pods -n kube-system -l app.kubernetes.io/name=traefik
NAME                       READY   STATUS    RESTARTS   AGE
traefik-78ff486794-64jbd   1/1     Running   0          3m15s

安装完成后可以通过查看Pod的资源清单来了解Traefik的运行方式:

➜ kubectl get pods traefik-78ff486794-64jbd -n kube-system -o yaml
apiVersion: v1
kind: Pod
metadata:
......
spec:
  containers:
  - args:
    - --global.checknewversion
    - --global.sendanonymoususage
    - --entryPoints.traefik.address=:9000/tcp
    - --entryPoints.web.address=:8000/tcp
    - --entryPoints.websecure.address=:8443/tcp
    - --api.dashboard=true
    - --ping=true
    - --providers.kubernetescrd
    - --providers.kubernetesingress
    - --accesslog=true
    - --accesslog.fields.defaultmode=keep
    - --accesslog.fields.headers.defaultmode=drop
...

其中entryponits属性定义了web和websecure这两个入口点,并开启kubernetesingress和kubernetescrd这两个provider,也就是说明可以使用k8s原本的ingress对象,也可以使用Traefik自己扩展的IngressRoute这样的CRD资源对象。

创建一个用于Dashboard访问的IngressRoute资源清单:

➜ cat <<EOF | kubectl apply -f -
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: traefik-dashboard
  namespace: kube-system
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`traefik.qikqiak.com`)  # 指定域名
    kind: Rule
    services:
    - name: api@internal
      kind: TraefikService  # 引用另外的 Traefik Service
EOF
➜ kubectl get ingressroute -n kube-system
NAME                AGE
traefik-dashboard   19m

其中的TraefikServiceTraefik Service的一个CRD实现,这里使用的api@internal这个TraefikService,表示我们访问的是Traefik内置的应用服务。

部署完成后可以通过在本地/etc/hosts中添加域名的映射即可访问Traefik的Dashboard页面:
image.png

需要注意的是默认情况下Traefik的IngressRoute已经允许跨namespace进行通信了,可以通过设置参数--providers.kubernetescrd.allowCrossNamespace=true(默认已经开启),开启后IngressRoute就可以引用IngressRoute命名空间以外的其他命名空间中的任何资源了

ACME

Traefik通过扩展CRD的方式来扩展Ingress的功能,除了默认的用Secret的方式可以支持应用的HTTPS之外,还支持自动生成HTTPS证书。

示例应用:

apiVersion: v1
kind: Service
metadata:
  name: whoami
spec:
  ports:
    - protocol: TCP
      name: web
      port: 80
  selector:
    app: whoami
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: whoami
  labels:
    app: whoami
spec:
  replicas: 2
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
        - name: whoami
          image: containous/whoami
          ports:
            - name: web
              containerPort: 80

然后定义一个IngressRoute对象:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: simpleingressroute
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`who.qikqiak.com`) && PathPrefix(`/notls`)
    kind: Rule
    services:
    - name: whoami
      port: 80

通过entrypoints指定了应用的入口点是web,也就是通过80端口访问,然后访问的规则就是匹配who.qikqiak.com这个域名,并且具有/notls的路径前缀的请求才会被whoami这个Service所匹配。可以直接创建上面的资源对象,然后对域名做对应的解析后,就可以访问应用了:
image.png在IngressRoute对象中定义了一些匹配规则,这些规则在Traefik中有如下定义方式:
image.png
如果需要用HTTPS来访问应用的话,就需要监听websecure这个入口点,也就是通过443端口来访问,同样用HTTPS访问必然需要证书,这里用openssl来创建一个自签名证书:

➜ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=who.qikqiak.com"

然后通过Secret对象来引用证书文件:

# 要注意证书文件名称必须是 tls.crt 和 tls.key
➜ kubectl create secret tls who-tls --cert=tls.crt --key=tls.key
secret/who-tls created

这时候就可以创建一个HTTPS访问应用的IngressRoute对象:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: ingressroutetls
spec:
  entryPoints:
    - websecure
  routes:
  - match: Host(`who.qikqiak.com`) && PathPrefix(`/tls`)
    kind: Rule
    services:
    - name: whoami
      port: 80
  tls:
    secretName: who-tls

创建完成后就可以通过HTTPS来访问应用了,由于是自签名证书,所以证书不受信任:
image.png
除了手动提供证书的方式外Traefik同样也支持使用let's encrypt自动生成证书,要使用let’s encrypt来进行自动化HTTPS,就需要首先开启ACME,开启ACME需要通过静态配置的方式,也就是说可以通过环境变量、启动参数等方式来提供。

ACME有多种校验方式tlsChallenge、httpChallenge 和 dnsChallenge 三种验证方式,之前常用的是http这种验证方式,关于这几种验证方式的使用可以查看文档:https://www.qikqiak.com/traefik-book/https/acme/了解它们之间的区别。要使用tls校验方式的话需要保证Traefik的443端口可达,dns校验方式可以生成通配符的证书,只需要配置上DNS解析服务商的API访问密钥即可校验。下面是DNS校验的方式

重新修改Helm安装的values配置文件,添加如下的定制参数:

# values-prod.yaml
additionalArguments:
# 使用 dns 验证方式
- --certificatesResolvers.ali.acme.dnsChallenge.provider=alidns
# 先使用staging环境进行验证,验证成功后再使用移除下面一行的配置
# - --certificatesResolvers.ali.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory
# 邮箱配置
- --certificatesResolvers.ali.acme.email=ych_1024@163.com
# 保存 ACME 证书的位置
- --certificatesResolvers.ali.acme.storage=/data/acme.json

envFrom: 
- secretRef:
    name: traefik-alidns-secret
    # ALICLOUD_ACCESS_KEY
    # ALICLOUD_SECRET_KEY
    # ALICLOUD_REGION_ID

persistence:
  enabled: true  # 开启持久化
  accessMode: ReadWriteOnce
  size: 128Mi
  path: /data

# 由于上面持久化了ACME的数据,需要重新配置下面的安全上下文
securityContext:
  readOnlyRootFilesystem: false
  runAsGroup: 0
  runAsUser: 0
  runAsNonRoot: false

通过设置--certificatesresolvers.ali.acme.dnschallenge.provider=alidns参数来指定阿里云的DNS校验,要使用阿里云的DNS校验还需要配置3个环境变量:ALICLOUD_ACCESS_KEYALICLOUD_SECRET_KEYALICLOUD_REGION_ID,分别对应平时开发阿里云应用的时候的密钥,可以登录阿里云后台获取,由于比较私密,所以使用Secret对象来创建:

➜ kubectl create secret generic traefik-alidns-secret --from-literal=ALICLOUD_ACCESS_KEY=<aliyun ak> --from-literal=ALICLOUD_SECRET_KEY=<aliyun sk> --from-literal=ALICLOUD_REGION_ID=cn-beijing -n kube-system

创建完后将这个Secret通过环境变量配置到Traefik的应用中,还有一个值得注意的是验证通过的证书存放在/data/acme.json文件中,一定要将这个文件持久化,否则每次Traefik重建后就需要重新认证,而let’s encrypt本身验证次数是有限制的。所以在values中重新开启了数据持久化,不过开启过后需要提供一个可用的PV存储,由于将Traefik固定到master节点上,所以可以创建一个hostpath类型的pv:

➜ cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolume
metadata:
  name: traefik
spec:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 128Mi
  hostPath:
    path: /data/k8s/traefik
EOF

然后使用如下命令更新Traefik:

➜ helm upgrade --install traefik --namespace=kube-system ./traefik -f ./values-prod.yaml 
Release "traefik" has been upgraded. Happy Helming!
NAME: traefik
LAST DEPLOYED: Thu Dec 24 14:32:04 2020
NAMESPACE: kube-system
STATUS: deployed
REVISION: 2
TEST SUITE: None

更新完成后来修改whoami的资源清单:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: ingressroutetls
spec:
  entryPoints:
    - websecure
  routes:
  - match: Host(`who.qikqiak.com`) && PathPrefix(`/tls`)
    kind: Rule
    services:
    - name: whoami
      port: 80
  tls:
    certResolver: ali
    domains:
    - main: "*.qikqiak.com"

其他的都不变,只需要将 tls 部分改成我们定义的 ali 这个证书解析器,如果我们想要生成一个通配符的域名证书的话可以定义 domains 参数来指定,然后更新 IngressRoute 对象,这个时候我们再去用 HTTPS 访问我们的应用(当然需要将域名在阿里云 DNS 上做解析):
image.png

中间件

中间件是Traefik2.x中一个非常有特色的功能,可以根据自己的各种需求去选择不同的中间件来满足服务,traefik官方已经内置了许多不同功能的中间件,其中一些可以修改请求,头信息,一些负责重定向,一些添加身份验证等等,而且中间件还可以通过链式组合的方式来适用各种情况。
image.png
比如上面定义的whoami这个应用,可以通过https://whoami.qikqiak.com/tls来访问到应用,但是如果用http访问就会404,因为根本没有监听80端口这个入口点,所以要想通过http来访问应用的话就需要监听下web这个入口点:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: ingressroutetls-http
spec:
  entryPoints:
    - web
  routes:
  - match: Host(`who.qikqiak.com`) && PathPrefix(`/tls`)
    kind: Rule
    service:
    - name: whoami
      port: 80

这里创建的IngressRoute的entryPoints是web,然后创建这个对象,就可以通过http访问到这个应用。

但是如果只希望用户通过https,需要让http强制跳转到https服务去,在Traefik中可以配置强制跳转,只是这个功能目前是通过中间件来提供的,如下所示,使用redirectScheme中间件来创建提供强制跳转服务:

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: redirect-https
spec:
  redirectScheme:
    scheme: https

然后将这个中间件附加到http的服务上去:

---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: ingressroutetls-http
spec:
  entryPoints:
    - web
  routes:
  - match: Host(`who.qikqiak.com`) && PathPrefix(`/tls`)
    kind: Rule
    services:
    - name: whoami
      port: 80
    middlewares: 
    - name: redirect-https

这个时候再去访问 http 服务可以发现就会自动跳转到 https 去了。关于更多中间件的用法可以查看文档Traefik Docs

Traefik Pilot

虽然Traefik已经默认实现了很多中间件,可以满足大部分日常需求,但是在实际的工作中,用户仍然还是有自定义中间件的需求,这就是Traefik Pilot的功能了。
image.png
Traefik Pilot是一个SaaS平台,和Traefik进行链接来扩展其功能,它提供了很多功能,通过一个全局控制面板和Dashboard来增强traefik的观测和控制:

  • Traefik代理和代理组的网络活动的指标
  • 服务健康问题和安全漏洞警报
  • 扩展Traefik功能的插件

在Traefik可以使用Traefik Pilot的功能之前,必须先连接他们,只需要对Traefik的静态配置进行少量更改即可。

Traefik代理必须要能访问互联网才能连接Traefik Pilot,通过HTTP在443端口上建立连接

首先需要在Traefik Pilot主页(https://pilot.traefik.io/)上创建账号,注册新的Traefik实例并开始使用Traefik Poilt。登录后,可以通过选择Register New Traefik IInstance来创建新实例。
image.png
另外,当 Traefik 尚未连接到 Traefik Pilot 时,Traefik Web UI 中将出现一个响铃图标,我们可以选择 Connect with Traefik Pilot 导航到 Traefik Pilot UI 进行操作。
image.png
登录完成后,Traefik Pilot 会生成一个新实例的令牌,我们需要将这个 Token 令牌添加到 Traefik 静态配置中。
image.png
我们这里就是在 values-prod.yaml 文件中启用 Pilot 的配置:

# values-prod.yaml
# Activate Pilot integration
pilot:
  enabled: true
  token: "e079ea6e-536a-48c6-b3e3-f7cfaf94f477"

然后重新更新 Traefik:

➜ helm upgrade --install traefik --namespace=kube-system ./traefik -f ./values-prod.yaml

更新完成后,在 Traefik 的 Web UI 中就可以看到 Traefik Pilot UI 相关的信息了。
image.png
接下来就可以在 Traefik Pilot 的插件页面选择想要使用的插件,比如这里使用 Demo Plugin 这个插件。
image.png
点击右上角的 Install Plugin 按钮安装插件会弹出一个对话框提示如何安装。
image.png
首先需要将当前 Traefik 注册到 Traefik Pilot(已完成),然后需要以静态配置的方式添加这个插件到 Traefik 中,这里同样更新 values-prod.yaml 文件中的 Values 值即可:

# values-prod.yaml
# Activate Pilot integration
pilot:
  enabled: true
  token: "e079ea6e-536a-48c6-b3e3-f7cfaf94f477"

additionalArguments:
# 添加 demo plugin 的支持
- --experimental.plugins.plugindemo.modulename=github.com/traefik/plugindemo
- --experimental.plugins.plugindemo.version=v0.2.1
# 其他配置

重新更新 Traefik:

➜ helm upgrade --install traefik --namespace=kube-system ./traefik -f ./values-prod.yaml

更新完成后创建一个如下所示的 Middleware 对象:

➜ cat <<EOF | kubectl apply -f -
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: myplugin
spec:
  plugin:
    plugindemo:  # 插件名
      Headers:
        X-Demo: test
        Foo: bar
EOF

然后添加到上面的 whoami 应用的 IngressRoute 对象中去:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: simpleingressroute
  namespace: default
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`who.qikqiak.com`) && PathPrefix(`/notls`)
    kind: Rule
    services:
    - name: whoami  # K8s Service
      port: 80
    middlewares: 
    - name: myplugin  # 使用上面新建的 middleware

更新完成后,当去访问 http://who.qikqiak.com/notls 的时候就可以看到新增了两个上面插件中定义的两个 Header。
image.png
当然除了使用 Traefik Pilot 上开发者提供的插件之外,也可以根据自己的需求自行开发自己的插件,可以自行参考文档:https://doc.traefik.io/traefik-pilot/plugins/plugin-dev/

灰度发布

Traefik2.x的一个更强大的功能就是灰度发布,灰度发布有时候也会称为金丝雀发布(Canary),主要就是让一部分测试服务也参与到线上,经过测试观察是否符合上线要求。
image.png
比如现在有两个名为appv1和appv2的服务,希望通过Traefik来控制流量,将3/4的流量路由到appv1,1/4的流量路由到appv2去,这时候就可以利用Traefik2.x中提供的带权重的轮询(WRR)来实现这个功能,首先在k8s集群中部署两个服务:
appv1服务资源清单(appv1.yaml):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: appv1
spec:
  selector:
    matchLabels:
      app: appv1
  template:
    metadata:
      labels:
        use: test
        app: appv1
    spec:
      containers:
      - name: whoami
        image: containous/whoami
        ports:
        - containerPort: 80
          name: portv1
---
apiVersion: v1
kind: Service
metadata:
  name: appv1
spec:
  selector:
    app: appv1
  ports:
  - name: http
    port: 80
    targetPort: portv1

appv2服务资源清单(appv2.yaml):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: appv2
spec:
  selector:
    matchLabels:
      app: appv2
  template:
    metadata:
      labels:
        use: test
        app: appv2
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
          name: portv2
---
apiVersion: v1
kind: Service
metadata:
  name: appv2
spec:
  selector:
    app: appv2
  ports:
  - name: http
    port: 80
    targetPort: portv2

直接创建上面两个服务

➜ kubectl apply -f appv1.yaml
➜ kubectl apply -f appv2.yaml
# 通过下面的命令可以查看服务是否运行成功
➜ kubectl get pods -l use=test
NAME                     READY   STATUS    RESTARTS   AGE
appv1-58f856c665-shm9j   1/1     Running   0          12s
appv2-ff5db55cf-qjtrf    1/1     Running   0          12s

在Traekfik2.1中新增了一个TraefikService的CRD资源,可以直接利用这个对象来配置WRR,之前的版本需要通过File Provider。新建一个描述WRR的资源清单:(wrr.yaml)

apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
  name: app-wrr
spec:
  weighted:
    services:
      - name: appv1
        weight: 3  # 定义权重
        port: 80
        kind: Service  # 可选,默认就是 Service
      - name: appv2
        weight: 1
        port: 80

然后为我们的灰度发布的服务创建一个 IngressRoute 资源对象:(ingressroute.yaml)

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: wrringressroute
  namespace: default
spec:
  entryPoints:
    - web
  routes:
  - match: Host(`wrr.qikqiak.com`)
    kind: Rule
    services:
    - name: app-wrr
      kind: TraefikService

不过需要注意的是现在配置的 Service 不再是直接的 Kubernetes 对象了,而是上面定义的 TraefikService 对象,直接创建上面的两个资源对象,这个时候对域名 wrr.qikqiak.com 做上解析,去浏览器中连续访问 4 次,可以观察到 appv1 这应用会收到 3 次请求,而 appv2 这个应用只收到 1 次请求,符合上面的 3:1 的权重配置。
image.png

流量复制

除了灰度发布之外,Traefik2.0还引入了流量镜像服务,是一种可以将流入流量复制并同时将其发送给其他服务的方法,镜像服务可以获得给定百分比的请求同时也会忽略这部分请求的响应。
image.png
部署两个whoami的服务,资源清单文件如下:

apiVersion: v1
kind: Service
metadata:
  name: v1
spec:
  ports:
    - protocol: TCP
      name: web
      port: 80
  selector:
    app: v1
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: v1
  labels:
    app: v1
spec:
  selector:
    matchLabels:
      app: v1
  template:
    metadata:
      labels:
        app: v1
    spec:
      containers:
        - name: v1
          image: nginx
          ports:
            - name: web
              containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: v2
spec:
  ports:
    - protocol: TCP
      name: web
      port: 80
  selector:
    app: v2
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: v2
  labels:
    app: v2
spec:
  selector:
    matchLabels:
      app: v2
  template:
    metadata:
      labels:
        app: v2
    spec:
      containers:
        - name: v2
          image: nginx
          ports:
            - name: web
              containerPort: 80

直接创建上面的资源对象:

➜ kubectl get pods
NAME                                      READY   STATUS    RESTARTS   AGE
v1-77cfb86999-wfbl2                       1/1     Running   0          94s
v2-6f45d498b7-g6qjt                       1/1     Running   0          91s
➜ kubectl get svc 
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE
v1              ClusterIP   10.96.218.173   <none>        80/TCP      99s
v2              ClusterIP   10.99.98.48     <none>        80/TCP      96s

现在创建一个IngressRoute对象,将服务v1的流量复制50%到服务v2,如下资源清单:(mirror-ingress-route.yaml)

apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
  name: app-mirror
spec:
  mirroring:
    name: v1 # 发送 100% 的请求到 K8S 的 Service "v1"
    port: 80
    mirrors:
    - name: v2 # 然后复制 50% 的请求到 v2
      percent: 50
      port: 80
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: mirror-ingress-route
  namespace: default
spec:
  entryPoints:
  - web
  routes:   
  - match: Host(`mirror.qikqiak.com`)
    kind: Rule
    services:
    - name: app-mirror
      kind: TraefikService # 使用声明的 TraefikService 服务,而不是 K8S 的 Service

然后直接创建这个资源对象:

➜ kubectl apply -f mirror-ingress-route.yaml 
ingressroute.traefik.containo.us/mirror-ingress-route created
traefikservice.traefik.containo.us/mirroring-example created

这个时候在浏览器中去连续访问4次 mirror.qikqiak.com 可以发现有一半的请求也出现在了 v2 这个服务中:
image.png