zoukankan      html  css  js  c++  java
  • 还不会Traefik?看这篇文章就够了!【转】

    提到Traefik,有些人可能并不熟悉,但是提到Nginx,应该都耳熟能详。

    暂且我们把Traefik当成和Nginx差不多的一类软件,待读完整篇文章,你就会对Traefik有不一样的认识。

    本文主要带大家对Traefik有一个全面的认识,我将从下面几个方面作介绍。

    本文基于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等;并且可以同时处理许多集群。

    image.png

    Traefik的核心概念及能力

    Traefik是一个边缘路由器,它会拦截外部的请求并根据逻辑规则选择不同的操作方式,这些规则决定着这些请求到底该如何处理。Traefik提供自动发现能力,会实时检测服务,并自动更新路由规则。

    从上图可知,请求首先会连接到entrypoints,然后分析这些请求是否与定义的rules匹配,如果匹配,则会通过一系列middlewares,再到对应的services上。

    这就涉及到以下几个重要的核心组件。

    • Providers
    • Entrypoints
    • Routers
    • Services
    • Middlewares

    Providers

    Providers是基础组件,Traefik的配置发现是通过它来实现的,它可以是协调器,容器引擎,云提供商或者键值存储。

    Traefik通过查询ProvidersAPI来查询路由的相关信息,一旦检测到变化,就会动态的更新路由。

    Entrypoints

    EntrypointsTraefik的网络入口,它定义接收请求的接口,以及是否监听TCP或者UDP。

    Routers

    Routers主要用于分析请求,并负责将这些请求连接到对应的服务上去,在这个过程中,Routers还可以使用Middlewares来更新请求,比如在把请求发到服务之前添加一些Headers。

    Services

    Services负责配置如何到达最终将处理传入请求的实际服务。

    Middlewares

    Middlewares用来修改请求或者根据请求来做出一些判断(authentication, rate limiting, headers, ...),中间件被附件到路由上,是一种在请求发送到你的服务之前(或者在服务的响应发送到客户端之前)调整请求的一种方法。

    部署Traefik

    Traefik的部署方式有多种,这里主要采用Helm方式进行部署管理。

    Helm部署

    环境:kubernetes: 1.22.3 helm: 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页面,如下:

    使用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端口的映射端口),如下:

    使用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/#/ 进行访问了。

    暴露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 
    

    创建过后,就可以进行访问了,如下:

    暴露HTTPS服务

    上面的whoami应用,是通过HTTP进行访问的,如果要通过HTTPS进行访问,应该如何配置呢?

    Traefik支持HTTPS和TLS,对于证书可以选择自有证书,也可以使用Let's Encrypt【5】自动生成证书。这里会分别介绍这两种方式。

    自有证书配置HTTPS

    现在公司基本都会自己购买更安全的证书,那对于自有证书配置HTTPS就会使用更加频繁,这里主要介绍这种配置方式。

    1、申请或者购买证书

    我这里是在腾讯云申请的免费证书。

    然后下载对应的证书,并上传到服务器上。

    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映射出来的端口)。

    自动生成HTTPS证书

    Traefik除了使用自有证书外,还支持Let's Encrypt自动生成证书【6】。

    要使用Let's Encrypt自动生成证书,需要使用ACME。需要在静态配置中定义 "证书解析器",Traefik负责从ACME服务器中检索证书。

    然后,每个 "路由器 "被配置为启用TLS,并通过tls.certresolver配置选项与一个证书解析器关联。

    TraefikACME验证方式主要有以下三种:

    • tlsChallenge
    • httpChallenge
    • dnsChallenge

    如果使用tlsChallenge,则要求Let's Encrypt到 Traefik 443 端口必须是可达的。如果使用httpChallenge,则要求Let's Encrypt到 Traefik 80端口必须是可达的。如果使用dnsChallenge,则需要对应的providers[7]。

    但是我们上面部署Traefik的时候并没有把80和443端口暴露出来,要测试tlsChallengehttpChallenge的话就必须暴露,下面我们更改一下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端口,现在我们入口已经放开,接下来就修改Traefikmy-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是可以正常使用证书的,如下:

    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,效果如下:

    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_KEYALICLOUD_SECRET_KEYALICLOUD_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"
    

    然后访问域名后,就可以看到证书签署 成功,如下:

    中间件的使用

    在介绍Traefik的核心概念的时候有提到一个请求匹配Rules后,会经过一系列的Middleware,再到具体的Services上。这个Middleware是什么呢?

    image.png

    MiddlewareTraefik 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

    去除请求路径前缀

    有时候会遇到这么一个需求:

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

    这种需求是非常常见的,在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状态的。

    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来校验结果。

    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
    

    然后进行测试,效果如下:

    发了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服务网络,这些接口由许多供应商实现,并得到了广泛的行业支持。

    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)、现在就可以直接在浏览器访问了

    image.png

    GatewayClass在集群中可以只创建一个,然后GatewayHTTPRoute是需要对应的。

    比如我这里要暴露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]进行学习,也欢迎交流。

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

    如果我的文章对你有所帮助,还请帮忙点赞、在看、转发一下,你的支持会激励我输出更高质量的文章,非常感谢!

    你还可以把我的公众号设为「星标」,这样当公众号文章更新时,你会在第一时间收到推送消息,避免错过我的文章更新。


    我是 乔克,《运维开发故事》公众号团队中的一员,一线运维农民工,云原生实践者,这里不仅有硬核的技术干货,还有我们对技术的思考和感悟,欢迎关注我们的公众号,期待和你一起成长!

    引用

    [1] https://doc.traefik.io/traefik/ [2] https://github.com/traefik/traefik-helm-chart/blob/master/traefik/values.yaml [3] https://doc.traefik.io/traefik/providers/kubernetes-crd/ [4] https://github.com/traefik/whoami [5] https://letsencrypt.org/zh-cn/ [6] https://doc.traefik.io/traefik/https/acme/ [7] https://doc.traefik.io/traefik/https/acme/#tlschallenge [8] https://go-acme.github.io/lego/dns/alidns/ [9] https://doc.traefik.io/traefik/middlewares/http/overview/ [10] https://doc.traefik.io/traefik/routing/routers/#configuring-tcp-routers [11] https://doc.traefik.io/traefik/routing/services/#mirroring-service [12] https://doc.traefik.io/traefik/providers/kubernetes-gateway/ [13] https://gateway-api.sigs.k8s.io/ [14] https://traefik.io/

    本文分享自微信公众号 - 运维开发故事(mygsdcsf),作者:乔克

    原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

  • 相关阅读:
    开学第二周java作业暨动手动脑p1
    开学第一周
    暑假第九周
    暑假第八周
    bzoj4033:[HAOI2015]树上染色
    bzoj4472:[Jsoi2015]salesman
    dp专题复习
    bzoj1864:[Zjoi2006]三色二叉树
    bzoj1190:[HNOI2007]梦幻岛宝珠
    bzoj2794:[Poi2012]Cloakroom
  • 原文地址:https://www.cnblogs.com/paul8339/p/15656435.html
Copyright © 2011-2022 走看看