评论

收藏

[Oracle] 还不会Traefik?看这篇文章就够了!(文末送书)

数据库 数据库 发布于:2021-12-29 11:56 | 阅读数:598 | 评论:0

大家好,我是乔克。


提到Traefik,有些人可能并不熟悉,但是提到Nginx,应该都耳熟能详。
暂且我们把Traefik当成和Nginx差不多的一类软件,待读完整篇文章,你就会对Traefik有不一样的认识。
本文主要带大家对Traefik有一个全面的认识,我将从下面几个方面作介绍。 DSC0000.png
本文基于Traefik 2.5.3进行介绍。

什么是Traefik
Traefik是一个开源的边缘路由网关,它简单易用并且功能全面。官方【1】的介绍是:​​Traefik is an [open-source](https://github.com/traefik/traefik) _Edge Router_ that makes publishing your services a fun and easy experience.​​
Traefik原生支持多种集群,如Kubernetes、Docker、Docker Swarm、AWS、Mesos、Marathon等;并且可以同时处理许多集群。
DSC0001.png image.png


Traefik的核心概念及能力
Traefik是一个边缘路由器,它会拦截外部的请求并根据逻辑规则选择不同的操作方式,这些规则决定着这些请求到底该如何处理。Traefik提供自动发现能力,会实时检测服务,并自动更新路由规则。 DSC0002.png
从上图可知,请求首先会连接到​​entrypoints​​​,然后分析这些请求是否与定义的​​rules​​​匹配,如果匹配,则会通过一系列​​middlewares​​​,再到对应的​​services​​上。
这就涉及到以下几个重要的核心组件。





  • Providers
  • Entrypoints
  • Routers
  • Services
  • Middlewares



Providers
​​Providers​​是基础组件,Traefik的配置发现是通过它来实现的,它可以是协调器,容器引擎,云提供商或者键值存储。
​​Traefik​​​通过查询​​Providers​​​的​​API​​来查询路由的相关信息,一旦检测到变化,就会动态的更新路由。
Entrypoints
​​Entrypoints​​​是​​Traefik​​的网络入口,它定义接收请求的接口,以及是否监听TCP或者UDP。
Routers
​​Routers​​主要用于分析请求,并负责将这些请求连接到对应的服务上去,在这个过程中,Routers还可以使用Middlewares来更新请求,比如在把请求发到服务之前添加一些Headers。
Services
​​Services​​负责配置如何到达最终将处理传入请求的实际服务。
Middlewares
​​Middlewares​​用来修改请求或者根据请求来做出一些判断(authentication, rate limiting, headers, ...),中间件被附件到路由上,是一种在请求发送到你的服务之前(或者在服务的响应发送到客户端之前)调整请求的一种方法。

部署Traefik
Traefik的部署方式有多种,这里主要采用​​Helm​​方式进行部署管理。
Helm部署
环境:kubernetes: 1.22.3helm: 3.7.1
1、添加traefik helm仓库
$ helm repo add traefik https://helm.traefik.io/traefik
$ helm repo update
2、将traefik包下载到本地进行管理
$ helm  search repo traefik
NAME            CHART VERSION APP VERSION DESCRIPTION                                  
traefik/traefik 10.6.0        2.5.3       A Traefik based Kubernetes ingress controller
$ helm pull traefik/traefik
3、部署Traefik
默认的​​value.yaml​​[2]配置文件配置比较多,可能需要花一定的时间去梳理,不过根据相关的注释还是可以很快的理解。
这里自定义一个配置文件​​my-value.yaml​​,如下:
service:
  type: NodePort 
ingressRoute:
  dashboard:
    enabled: false
ports:
  traefik:
    port: 9000
    expose: true
  web:
    port: 8000
    expose: true
  websecure:
    port: 8443
    expose: true
persistence:
  enabled: true
  name: data
  accessMode: ReadWriteOnce
  size: 5G
  storageClass: "openebs-hostpath"
  path: /data
additionalArguments:
  - "--serversTransport.insecureSkipVerify=true"
  - "--api.insecure=true"
  - "--api.dashboard=true"
进行部署,命令如下:
$ kubectl create ns traefik-ingress
$ helm install traefik -n traefik-ingress -f my-value.yaml .
这里不是使用的是默认的​​value.yaml​​[2]配置文件。
然后可以看到部署结果,如下:
# kubectl get all -n traefik-ingress 
NAME                           READY   STATUS    RESTARTS   AGE
pod/traefik-77ff894bb5-qqszd   1/1     Running   0          6m26s
NAME              TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                                     AGE
service/traefik   NodePort   10.108.170.22   <none>        9000:32271/TCP,80:31728/TCP,443:30358/TCP   6m26s
NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/traefik   1/1     1            1           6m26s
NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/traefik-77ff894bb5   1         1         1       6m26s
然后可以通过​​NodePort​​​访问Dashboard页面,如下: DSC0003.png

使用Traefik
创建第一个路由规则
我们上面访问Dashboard是采用的​​NodePort​​​的方式,既然已经把​​Traefik​​部署好了,为什么不使用路由网关的方式呢?
下面我们就来创建第一个路由网关来访问​​Dashboard​​。
Traefik创建路由规则有多种方式,比如:





  • 原生Ingress写法
  • 使用CRD IngressRoute方式
  • 使用GatewayAPI的方式



这里暂时介绍前面两种方式,关于GatewayAPI的方式在后续进行介绍。
原生Ingress路由规则
原生Ingress的路由规则,写法就比较简单,如下。
# cat traefik-ingress.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: traefik-dashboard-ingress
  annotations:
    kubernetes.io/ingress.class: traefik  
    traefik.ingress.kubernetes.io/router.entrypoints: web
spec:
  rules:
  - host: traefik-web.coolops.cn 
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: traefik
            port:
              number: 9000
创建路由规则,命令如下:
# kubectl apply -f traefik-ingress.yaml -n traefik-ingress 
ingress.networking.k8s.io/traefik-dashboard-ingress created
现在就可以通过域名http://traefik-web.coolops.cn:31728/dashboard/#/ 进行访问了(31728是80端口的映射端口),如下: DSC0004.png
使用CRD方式配置路由规则
在早期版本,Traefik仅提供kubernetes ingress方式配置路由规则,社区认为采用开发一个自定义CRD的类型能够更好的提供Kubernetes的访问配置【3】。
​​IngressRoute​​的配置方式也比较简单,如下:
# cat traefik-ingressRoute.yaml 
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: traefik-dashboard-route
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`traefik-web2.coolops.cn`)
    kind: Rule
    services:
      - name: traefik
        port: 9000 
部署命令如下:
# kubectl apply -f traefik-ingressRoute.yaml -n traefik-ingress 
ingressroute.traefik.containo.us/traefik-dashboard-route created
然后就可以通过http://traefik-web2.coolops.cn:31728/dashboard/#/ 进行访问了。 DSC0005.png
暴露HTTP服务
首先,部署一个简单的​​whoami​​[4]应用,YAML文件如下:
---
apiVersion: v1
kind: Pod
metadata:
  name: whoami
  labels:
    app: whoami
spec:
  containers:
    - name: whoami
      image: traefik/whoami:latest
      ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: whoami
spec:
  ports:
    - port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app: whoami
  type: ClusterIP
部署成功后,创建一个路由规则,使外部可以访问。
# cat ingressroute.yaml 
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-route
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`whoami.coolops.cn`)
    kind: Rule
    services:
      - name: whoami
        port: 80 
创建过后,就可以进行访问了,如下: DSC0006.png
暴露HTTPS服务
上面的​​whoami​​应用,是通过​​HTTP​​进行访问的,如果要通过​​HTTPS​​进行访问,应该如何配置呢?
​​Traefik​​支持HTTPS和TLS,对于证书可以选择自有证书,也可以使用Let's Encrypt【5】自动生成证书。这里会分别介绍这两种方式。
自有证书配置HTTPS
现在公司基本都会自己购买更安全的证书,那对于自有证书配置HTTPS就会使用更加频繁,这里主要介绍这种配置方式。
1、申请或者购买证书
我这里是在腾讯云申请的免费证书。 DSC0007.png 然后下载对应的证书,并上传到服务器上。
2、将证书文件保存为Secret
# kubectl create secret tls whoami-tls --cert=1_whoami.coolops.cn_bundle.crt --key=2_whoami.coolops.cn.key
3、创建IngressRoute对象,使其可以通过TLS访问
# cat ingressroutetls.yaml 
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-route-tls
spec:
  entryPoints:
  - websecure
  routes:
  - match: Host(`whoami.coolops.cn`)
    kind: Rule
    services:
      - name: whoami
        port: 80 
  tls:
    secretName: whoami-tls
创建完成后,就可以通过https://whoami.coolops.cn:30358/ 进行访问了(30358是443映射出来的端口)。 DSC0008.png
自动生成HTTPS证书
​​Traefik​​除了使用自有证书外,还支持​​Let's Encrypt​​自动生成证书【6】。
要使用​​Let's Encrypt​​自动生成证书,需要使用​​ACME​​。需要在静态配置中定义 "证书解析器",​​Traefik​​负责从​​ACME​​服务器中检索证书。
然后,每个 "路由器 "被配置为启用TLS,并通过tls.certresolver配置选项与一个证书解析器关联。
​​Traefik​​的​​ACME​​验证方式主要有以下三种:





  • tlsChallenge
  • httpChallenge
  • dnsChallenge



如果使用​​tlsChallenge​​,则要求​​Let's Encrypt​​到 Traefik ​​443​​ 端口必须是可达的。如果使用​​httpChallenge​​,则要求​​Let's Encrypt​​到 Traefik ​​80​​端口必须是可达的。如果使用​​dnsChallenge​​,则需要对应的​​providers​​[7]。
但是我们上面部署​​Traefik​​的时候并没有把80和443端口暴露出来,要测试​​tlsChallenge​​和​​httpChallenge​​的话就必须暴露,下面我们更改一下​​my-value.yaml​​,如下:
service:
  type: NodePort 
ingressRoute:
  dashboard:
    enabled: false
ports:
  traefik:
    port: 9000
    expose: true
  web:
    port: 8000
    hostPort: 80
    expose: true
  websecure:
    port: 8443
    hostPort: 443
    expose: true
persistence:
  enabled: true
  name: data
  accessMode: ReadWriteOnce
  size: 5G
  storageClass: "openebs-hostpath"
  path: /data
additionalArguments:
  - "--serversTransport.insecureSkipVerify=true"
  - "--api.insecure=true"
  - "--api.dashboard=true"
然后重新更新一下​​Traefik​​,命令如下:
helm upgrade traefik -n traefik-ingress -f my-value.yaml .
现在我们就可以直接通过80或443端口进行访问了。
1、tlsChallenge
上面已经介绍过,要使用​​tlsChallenge​​,必须能访问入口的443端口,现在我们入口已经放开,接下来就修改​​Traefik​​的​​my-value.yaml​​配置,如下:
......
deployment:
  initContainers:
    - name: volume-permissions
      image: busybox:1.31.1
      command: ["sh", "-c", "chmod -Rv 600 /data/*"]
      volumeMounts:
        - name: data
          mountPath: /data
additionalArguments:
  - "--serversTransport.insecureSkipVerify=true"
  - "--api.insecure=true"
  - "--api.dashboard=true"
  - "--certificatesresolvers.coolops.acme.email=coolops@163.com"
  - "--certificatesresolvers.coolops.acme.storage=/data/acme.json"
  - "--certificatesresolvers.coolops.acme.tlschallenge=true"
PS:这里需要将/data目录权限给更改一下,默认是0660,权限太大是不允许的。
然后我们创建一个​​ingressRoute​​,如下:
# cat ingressrouteautotls.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-route-auto-tls
spec:
  entryPoints:
  - websecure
  routes:
  - match: Host(`whoami3.coolops.cn`)
    kind: Rule
    services:
      - name: whoami
        port: 80 
  tls:
    certResolver: coolops
这时候我们访问https://whoami3.coolops.cn是可以正常使用证书的,如下: DSC0009.png
2、httpChallenge
下面再使用​​httpChallenge​​进行测试,修改​​my-value.yaml​​配置文件如下:
......
deployment:
  initContainers:
    - name: volume-permissions
      image: busybox:1.31.1
      command: ["sh", "-c", "chmod -Rv 600 /data/*"]
      volumeMounts:
        - name: data
          mountPath: /data
additionalArguments:
  - "--serversTransport.insecureSkipVerify=true"
  - "--api.insecure=true"
  - "--api.dashboard=true"
  - "--certificatesresolvers.coolops.acme.email=coolops@163.com"
  - "--certificatesresolvers.coolops.acme.storage=/data/acme.json"
  - "--certificatesresolvers.coolops.acme.httpchallenge=true"
  - "--certificatesresolvers.coolops.acme.httpchallenge.entrypoint=web"
更新​​Traefik​​过后,然后再创建一个​​ingressRoute​​进行测试,YAML文件如下:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-route-auto-tls-http
spec:
  entryPoints:
  - websecure
  routes:
  - match: Host(`whoami4.coolops.cn`)
    kind: Rule
    services:
      - name: whoami
        port: 80
  tls:
    certResolver: coolops
然后使用​​​​https://whoami4.coolops.cn​​​​,效果如下: DSC00010.png
3、dnsChallenge
​​dnsChallenge​​在使用上相对比较麻烦,因为需要配置对应的​​provider​​,不过它可以生成通配符证书,这里以阿里云DNS【8】为例。
使用阿里DNS的前提是您的域名是在阿里云上面,不然在签署证书的时候会报错,如下:
Unable to obtain ACME certificate for domains "*.coolops.cn" : unable to generate a certificate for the domains [*.coolops.cn]: error: one or more domains had a problem:\n[*.coolops.cn] [*.coolops.cn] acme: error presenting token: alicloud: zone coolops.cn. not found in AliDNS for domain coolops.cn\n" providerName=coolops.acme
使用阿里云的 DNS 校验需要配置3个环境变量:​​ALICLOUD_ACCESS_KEY​​、​​ALICLOUD_SECRET_KEY​​、​​ALICLOUD_REGION_ID​​,分别对应我们平时开发阿里云应用的时候的密钥,可以登录阿里云后台获取,由于这是比较私密的信息,所以我们用 Secret 对象来创建:
$ kubectl create secret generic traefik-alidns --from-literal=ALICLOUD_ACCESS_KEY=<aliyun ak> --from-literal=ALICLOUD_SECRET_KEY=<aliyun sk>--from-literal=ALICLOUD_REGION_ID=cn-beijing -n traefik-ingress
修改Traefik的my-value.yaml,如下:
......
additionalArguments:
  - "--serversTransport.insecureSkipVerify=true"
  - "--api.insecure=true"
  - "--api.dashboard=true"
  - "--certificatesresolvers.coolops.acme.email=coolops@163.com"
  - "--certificatesresolvers.coolops.acme.storage=/data/acme.json"
  - "--certificatesresolvers.coolops.acme.dnschallenge=true"
  - "--certificatesResolvers.coolops.acme.dnsChallenge.provider=alidns"
envFrom:
  - secretRef: 
      name: traefik-alidns
更新​​Traefik​​过后,然后再创建一个​​ingressRoute​​进行测试,YAML文件如下(由于coolops.cn不在阿里云上,所以换了一个域名):
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-route-auto-tls-dns
spec:
  entryPoints:
  - websecure
  routes:
  - match: Host(`whoami6.coolops.cn`)
    kind: Rule
    services:
      - name: whoami
        port: 80 
  tls:
    certResolver: coolops 
    domains:
    - main: "*.coolops.cn"
然后访问域名后,就可以看到证书签署 成功,如下: DSC00011.png
中间件的使用
在介绍​​Traefik​​的核心概念的时候有提到一个请求匹配​​Rules​​后,会经过一系列的​​Middleware​​,再到具体的​​Services​​上。这个​​Middleware​​是什么呢?
DSC00012.png image.png

​​Middleware​​是​​Traefik 2.0​​之后新增的功能,用户可以根据不通的需求来选择不同的Middleware来满足服务,提高了定制化的能力。
Traefik内置了很多不同功能的Middleware,主要是针对HTTP和TCP,HTTP占大部分[9],这里挑选几个比较常用的进行演示。
强制跳转HTTPS
强制跳转HTTPS是经常会配置的功能,这里还是以上没的​​whoami​​应用为例。
1、创建一个HTTPS的ingressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-route-auto-tls
spec:
  entryPoints:
  - websecure
  routes:
  - match: Host(`whoami3.coolops.cn`)
    kind: Rule
    services:
      - name: whoami
        port: 80 
  tls:
    certResolver: coolops
2、定义一个跳转HTTPS的中间件
这里会用到​​RedirectScheme​​的内置中间件,配置如下:
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: redirect-https-middleware
spec:
  redirectScheme:
    scheme: https
3、定义一个HTTP的ingressRoute,并使用Middleware
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami3-route
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`whoami3.coolops.cn`)
    kind: Rule
    services:
      - name: whoami
        port: 80
    middlewares:
    - name: redirect-https-middleware
然后访问​​​​http://whoami3.coolops.cn​​​​就会被强制跳转到​​​​https://whoami3.coolops.cn​​​​。 DSC00013.png
去除请求路径前缀
有时候会遇到这么一个需求:





  • 只有一个域名
  • 相通过这个域名访问不同的应用



这种需求是非常常见的,在​​NGINX​​中,我们可以配置多个​​Location​​来定制规则,使用​​Traefik​​也可以这么做。
但是定制不同的前缀后,由于应用本身并没有这些前缀,导致请求返回​​404​​,这时候我们就需要对请求的​​path​​进行处理,还是以​​whoami​​应用为例。
1、创建一个带前缀的ingressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami7-route
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`whoami7.coolops.cn`) && PathPrefix('/coolops')
    kind: Rule
    services:
      - name: whoami
        port: 80 
我们现在访问是会返回​​404​​状态的。 DSC00014.png
2、定义去除前缀的中间件
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: prefix-coolops-url-middleware
spec:
  stripPrefix:
    prefixes:
      - /coolops
3、修改上面的ingressRoute,应用中间件
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami7-route
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`whoami7.coolops.cn`) && PathPrefix('/coolops')
    kind: Rule
    services:
      - name: whoami
        port: 80
    middlewares:
    - name: prefix-coolops-url-middleware
然后就可以正常访问了。
添加IP白名单
在工作中,有一些URL并不希望对外暴露,比如prometheus、grafana等的url,这时候我们希望通过白名单IP来达到需求,就可以使用​​Traefik​​中的​​ipWhiteList​​中间件来完成。
1、定义白名单IP的中间件
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: ip-white-list-middleware
spec:
  ipWhiteList:
    sourceRange:
      - 127.0.0.1/32
      - 192.168.100.180
然后将中间件应用到对应的Rules上,就可以完成白名单功能。
除了上面的功能,Traefik内置Middleware还支持很多其他功能,比如限流、认证鉴权等,可以通过引用【9】进行查看。
暴露TCP服务
Traefik 2.0支持暴露TCP,这里以Redis为例。
1、部署一个Redis服务
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec:
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:5.0.14
        ports:
        - containerPort: 6379
          protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    app: redis
2、暴露Redis端口
暴露TCP端口使用的是SNI【10】,而SNI又是依赖TLS的,所以我们需要配置证书才行,但是如果没有证书的话,我们可以使用通配符​​*​​进行配置。
(1)、添加一个redis的entrypoints
修改​​Traefik​​的部署文件​​my-value.yaml​​,添加如下内容:
ports:
  traefik:
    port: 9000
    expose: true
  web:
    port: 8000
    hostPort: 80
    expose: true
  websecure:
    port: 8443
    hostPort: 443
    expose: true
  redis:
    port: 6379
    containerPort: 6379
    hostPort: 6379
additionalArguments:
  - "--entryPoints.redis.address=:6379"
  - "--serversTransport.insecureSkipVerify=true"
  - "--api.insecure=true"
  - "--api.dashboard=true"
  - "--certificatesresolvers.coolops.acme.email=coolops@163.com"
  - "--certificatesresolvers.coolops.acme.storage=/data/acme.json"
  - "--certificatesresolvers.coolops.acme.httpchallenge=true"
  - "--certificatesresolvers.coolops.acme.httpchallenge.entrypoint=web"
在启动参数中添加​​--entryPoints.redis.address=:6379​​用来指定entrypoint。
(2)、创建ingressRoute进行对外暴露
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
  name: redis-traefik-tcp
spec:
  entryPoints:
    - redis
  routes:
  - match: HostSNI(`*`)
    services:
    - name: redis
      port: 6379
然后可以使用客户端工具进行Redis的操作了。
# redis-cli -h redis.coolops.cn 
redis.coolops.cn:6379> set  a b
OK
redis.coolops.cn:6379> get a
"b"
redis.coolops.cn:6379> 
灰度发布
Traefik2.0 以后的一个更强大的功能就是灰度发布,灰度发布我们有时候也会称为金丝雀发布(Canary),主要就是让一部分测试的服务也参与到线上去,经过测试观察看是否符号上线要求。
假设一个应用现在运行着​​V1​​版本,新的​​V2​​版本需要上线,这时候我们需要在集群中部署好​​V2​​版本,然后通过​​Traefik​​提供的​​带权重的轮询(WRR)​​来实现该功能。
1、部署appv1、appv2应用
​​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: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        lifecycle:
          postStart:
            exec:
              command:  ["/bin/sh", "-c", "echo Hello v1 > /usr/share/nginx/html/index.html"]
        ports:
        - containerPort: 80
          name: portv1
---
apiVersion: v1
kind: Service
metadata:
  name: appv1
spec:
  selector:
    app: appv1
  ports:
  - name: http
    port: 80
    targetPort: portv1
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
        imagePullPolicy: IfNotPresent
        lifecycle:
          postStart:
            exec:
              command:  ["/bin/sh", "-c", "echo Hello v2 > /usr/share/nginx/html/index.html"]
        ports:
        - containerPort: 80
          name: portv2
---
apiVersion: v1
kind: Service
metadata:
  name: appv2
spec:
  selector:
    app: appv2
  ports:
  - name: http
    port: 80
    targetPort: portv2
2、创建TraefikService
在 Traefik2.1以后新增了一个 ​​TraefikService​​的 CRD 资源,我们可以直接利用这个对象来配置 ​​WRR​​。
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
  name: app-wrr
spec:
  weighted:
    services:
      - name: appv1
        weight: 3
        port: 80
        kind: Service
      - name: appv2
        weight: 1
        port: 80
        kind: Service
3、创建ingressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: app-ingressroute-canary 
spec:
  entryPoints:
    - web
  routes:
  - match: Host(`app.coolops.cn`)
    kind: Rule
    services:
    - name: app-wrr
      kind: TraefikService
注意:这里配置的不是​​Service​​类型,而是​​TraefikService​​。
然后就可以通过访问​​​​http://app.coolops.cn​​​​来校验结果。 DSC00015.png
待​​V2​​测试没问题后,就可以将流量全切到​​V2​​了。
流量复制
在​​Traefik 2.0​​之后还引入了​​镜像服务​​[11],它可以将请求的流量按规则复制一份发送给其他服务,并且会忽略这部分请求的响应。
这个功能在做一些压测或者问题复现的时候还是很有用。
这里依然以上没的appv1和appv2为例进行简单的演示。
1、创建TraefikService,定义复制规则
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
  name: app-mirror
spec:
  mirroring:
    name: appv1
    port: 80
    mirrors:
    - name: appv2
      percent: 50
      port: 80
上面定义的意思是将请求到appv1的50%请求复制到appv2。
2、创建ingressRoute,进行效果演示
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: app-ingressroute-mirror
spec:
  entryPoints:
    - web
  routes:
  - match: Host(`mirror.coolops.cn`)
    kind: Rule
    services:
    - name: app-mirror
      kind: TraefikService
然后进行测试,效果如下: DSC00016.png
发了4次请求,appv1可以正常接收4次请求,appv2可以收到2次请求,收到的响应是appv1的,并没有appv2的响应。
Kubernetes Gateway API
我们在上面创建路由规则要么使用​​ingress​​,要么使用​​ingressRoute​​,其实在​​Traefik 2.4​​以后支持​​Kubernetes Gateway API​​[12]提供的​​CRD​​方式创建路由规则。
什么是Gateway API?
​​Gateway API​​【13】是一个由​​SIG-NETWORK​​社区管理的开源项目。它是​​Kubernetes​​中服务网络模型的资源集合。这些资源(GatewayClass、Gateway、HTTPRoute、TCPRoute、Service)旨在通过表达式的、可扩展的和面向角色的接口来发展Kubernetes服务网络,这些接口由许多供应商实现,并得到了广泛的行业支持。
DSC00017.png image.png






  • GatewayClass:GatewayClass 是基础结构提供程序定义的群集范围的资源。此资源表示可以实例化的网关类。一般该资源是用于支持多个基础设施提供商用途的,这里我们只部署一个即可。
  • Gateway:Gateway 与基础设施配置的生命周期是 1:1。当用户创建网关时,GatewayClass 控制器会提供或配置一些负载平衡基础设施。
  • HTTPRoute:HTTPRoute 是一种网关 API 类型,用于指定 HTTP 请求从网关侦听器到 API 对象(即服务)的路由行为。



使用Gateway API
1、安装Gateway API 的CRD
Traefik Gateway provider 仅支持 v0.3.0 (v1alpha1).
kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.3.0" \
| kubectl apply -f -
2、创建rbac,给traefik授权
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: gateway-role
rules:
  - apiGroups:
      - ""
    resources:
      - services
      - endpoints
      - secrets
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - networking.x-k8s.io
    resources:
      - gatewayclasses
      - gateways
      - httproutes
      - tcproutes
      - tlsroutes
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - networking.x-k8s.io
    resources:
      - gatewayclasses/status
      - gateways/status
      - httproutes/status
      - tcproutes/status
      - tlsroutes/status
    verbs:
      - update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: gateway-controller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: gateway-role
subjects:
  - kind: ServiceAccount
    name: traefik
    namespace: traefik-ingress 
2、Traefik开启gateway api支持
修改​​my-value.yaml​​ 文件,如下:
......
additionalArguments:
  - "--entryPoints.redis.address=:6379"
  - "--serversTransport.insecureSkipVerify=true"
  - "--api.insecure=true"
  - "--api.dashboard=true"
  - "--certificatesresolvers.coolops.acme.email=coolops@163.com"
  - "--certificatesresolvers.coolops.acme.storage=/data/acme.json"
  - "--certificatesresolvers.coolops.acme.httpchallenge=true"
  - "--certificatesresolvers.coolops.acme.httpchallenge.entrypoint=web"
  - "--experimental.kubernetesgateway"
  - "--providers.kubernetesgateway"
更新Traefik,命令如下:
helm upgrade traefik -n traefik-ingress -f my-value.yaml .
4、通过Gateway api的方式暴露traefik dashboard应用
(1)、创建GatewayClass
apiVersion: networking.x-k8s.io/v1alpha1
kind: GatewayClass
metadata:
  name: traefik
spec:
  controller: traefik.io/gateway-controller
(2)、创建gateway
apiVersion: networking.x-k8s.io/v1alpha1
kind: Gateway
metadata: 
  name: http-gateway
  namespace: traefik-ingress 
spec: 
  gatewayClassName: traefik
  listeners: 
    - protocol: HTTP
      port: 8000 
      routes: 
        kind: HTTPRoute
        namespaces:
          from: All
        selector:
          matchLabels:
            app: traefik
(3)、创建HTTPRoute
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
  name: whoami-gateway-api-route 
  namespace: traefik-ingress
  labels:
    app: traefik
spec:
  hostnames:
    - "traefik1.coolops.cn"
  rules:
    - matches:
        - path:
            type: Prefix
            value: /
      forwardTo:
        - serviceName: traefik 
          port: 9000
          weight: 1
(4)、现在就可以直接在浏览器访问了
DSC00018.png image.png

​​GatewayClass​​在集群中可以只创建一个,然后​​Gateway​​和​​HTTPRoute​​是需要对应的。
比如我这里要暴露default命名空间下的whoami应用,YAML就应该如下:
apiVersion: networking.x-k8s.io/v1alpha1
kind: Gateway
metadata: 
  name: http-gateway
spec: 
  gatewayClassName: traefik
  listeners: 
    - protocol: HTTP
      port: 8000 
      routes: 
        kind: HTTPRoute
        namespaces:
          from: All
        selector:
          matchLabels:
            app: whoami
---
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
  name: whoami-gateway-api-route 
  labels:
    app: whoami 
spec:
  hostnames:
    - "whoami8.coolops.cn"
  rules:
    - matches:
        - path:
            type: Prefix
            value: /
      forwardTo:
        - serviceName: whoami 
          port: 80
          weight: 1


最后
​​Traefik​​是一个功能比较强大的边缘网关,基本能满足绝大部分的场景需求,而且还有​​Mesh​​等工具,比较好用,有兴趣的朋友可以到官网[14]进行学习,也欢迎交流。


最后,求关注。如果你还想看更多优质原创文章,欢迎关注我们的公众号「运维开发故事」。






关注下面的标签,发现更多相似文章