• Traefik 2.0 实现灰度发布


    文章转载自:https://mp.weixin.qq.com/s?__biz=MzU4MjQ0MTU4Ng==&mid=2247484478&idx=1&sn=238390dc34340ec291aed517f4a6cb9f&chksm=fdb90b23cace8235ef224bd086f9f3e9e29e07fa18d444e0edde5e76efa39bdbb921588726b8&cur_album_id=1319287026209947648&scene=190#rd

    灰度发布我们有时候也会称为金丝雀发布(Canary),主要就是让一部分测试的服务也参与到线上去,经过测试观察看是否符号上线要求。

    这篇使用的是FileProvider提供的灰度发布,高版本使用 TraefikService 对象提供的,地址:https://www.cnblogs.com/sanduzxcvbnm/p/15749641.html

    k8s版本:1.20.12
    traefik版本:2.4.8

    比如现在我们有两个名为 appv1 和 appv2 的 Nginx 服务,我们希望通过 Traefik 来控制我们的流量,将 3/4 的流量路由到 appv1,1/4 的流量路由到 appv2 去,这个时候就可以利用 Traefik2.0 中提供的带权重的轮询(WRR)来实现该功能,首先在 Kubernetes 集群中部署上面的两个服务。

    截止v2.0.2版本,要实现上面的灰度发布、流量复制这些高级功能,只能通过 FileProvider 来实现,所以我们不能直接使用前面的 KubernetesCRDProvider 了。

    appv1 服务的资源清单如下所示:(appv1.yaml)

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: appv1
      namespace: kube-system
    spec:
      selector:
        matchLabels:
          app: appv1
      template:
        metadata:
          labels:
            use: test
            app: appv1
        spec:
          containers:
          - name: nginx
            image: nginx:1.15-alpine
            ports:
            - containerPort: 80
              name: portv1
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: appv1
      namespace: kube-system
    spec:
      selector:
        app: appv1
      ports:
      - name: http
        port: 80
        targetPort: portv1
    

    appv2 服务的资源清单如下所示:(appv2.yaml)

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

    直接创建上面两个服务:

    # kubectl apply -f appv1.yaml
    deployment.apps/appv1 created
    service/appv1 created
    
    # kubectl apply -f appv2.yaml
    deployment.apps/appv2 created
    service/appv2 created
    
    # 通过下面的命令可以查看服务是否运行成功
    # kubectl get pods -l use=test -n kube-system
    NAME                     READY   STATUS    RESTARTS   AGE
    appv1-9d5c487-ssj9s      1/1     Running   0          51s
    appv2-5b94b97989-cjmgj   1/1     Running   0          47s
    

    由于 WRR 这个功能目前只支持 FileProvider,所以我们需要开启该 Provider 才能使用.
    这里需要注意的是由于需要开启 FileProvider,所以我们需要提供一个文件用于该 Provider 的配置,我们这里是用在 Kubernetes 集群中的,所以可以通过一个 ConfigMap 对象,将配置文件内容挂载到 Traefik 的 Pod 中去.
    如下所示,我们通过将一个名为 traefik-dynamic-conf 的 ConfigMap 对象挂载到了 /config 目录下面去,然后通过 --providers.file.filename参数指定配置文件开启 FileProvider,另外添加 ---providers.file.watch=true 参数可以让 Traefik 动态更新配置:

    # 参考内容
    
    ......
          volumes:
          - name: config
            configMap:
              name: traefik-dynamic-conf
          containers:
          - image: traefik:v2.0.2
            name: traefik-ingress-lb
            volumeMounts:
            - name: config
              mountPath: /config
            ports:
            - name: web
              containerPort: 80
              hostPort: 80
            - name: admin
              containerPort: 8080
              hostPort: 8080
            args:
            - --entrypoints.web.Address=:80
            - --api.insecure=true
            - --providers.file.watch=true
            - --providers.file.filename=/config/traefik-dynamic.toml
            - --api
            - --api.debug=true
            - --api.dashboard=true
            - --accesslog
    

    完整的 YAML 文件可以前往 https://github.com/cnych/kubeapp/tree/master/traefik2/canary 获取。

    上面是开启 FileProvider 的配置。

    我这里安装的traefik是使用kubeoperator安装k8s集群时选择的,对照上面的文件,修改步骤有两种,第一种是修改对应的yaml文件,第二种是通过kubepi进行修改

    修改对应的yaml文件

    ......
            volumeMounts:
              - name: data
                mountPath: /data
              - name: tmp
                mountPath: /tmp
              - name: config
                mountPath: /config
            args:
              - "--global.checknewversion"
              - "--global.sendanonymoususage"
              - "--entryPoints.traefik.address=:18443/tcp"
              - "--entryPoints.web.address=:80/tcp"
              - "--entryPoints.websecure.address=:443/tcp"
              - "--api.insecure=true"
              - "--api.dashboard=true"
              - "--ping=true"
              - "--providers.kubernetescrd"
              - "--providers.kubernetesingress"
              - "--providers.file.watch=true"
              - "--providers.file.filename=/config/traefik-dynamic.toml"
          volumes:
            - name: data
              emptyDir: {}
            - name: tmp
              emptyDir: {}
                  volumes:
            - name: config
              configMap:
                name: traefik-dynamic-conf
    

    通过kubepi进行修改

    等创建ConfigMap 对象后再通过kubepi添加挂载点

    接下来需要创建对应的 ConfigMap 对象,首先创建一个名为 traefik-dynamic.toml 的文件,内容如下所示:

    [http]
      [http.routers]
        [http.routers.Router0]
          entryPoints = ["web"]
          service = "app"
          rule = "Host(`www.daniel.com`)"
    
      [http.services]
        [http.services.app]
    
          [[http.services.app.weighted.services]]
            name = "appv1"
            weight = 3
    
          [[http.services.app.weighted.services]]
            name = "appv2"
            weight = 1
    
        [http.services.appv1]
          [http.services.appv1.loadBalancer]
            [[http.services.appv1.loadBalancer.servers]]
              url = "http://appv1/"
    
        [http.services.appv2]
          [http.services.appv2.loadBalancer]
            [[http.services.appv2.loadBalancer.servers]]
              url = "http://appv2/"
    

    上面这个配置文件就是我们需要配置的灰度发布的规则,创建一个名为 Router0 的路由,在 web 这个入口点上面监听 Host=www.daniel.com 这样的请求,将请求路由给名为 app 的服务,而该服务则将请求路由给了 appv1 这个服务,权重为 3,另外一部分请求路由给了 appv2 这个服务,权重为 1,也就是有 3/4 的请求会被路由到 http://appv1/ 这个真实的服务上,这个地址也就是我们 Kubernetes 集群中的 appv1 这个 Service 对象的 FQDN 地址,当然我们也可以用全路径( http://appv1.kube-system.svc.cluster.local:80)表示,因为都在 kube-system 这个命名空间下面,所以直接用服务名也是可以的,同样的另外的 1/4 请求会被路由到 http://appv2/ 这个真实的服务上。

    # kubectl create configmap traefik-dynamic-conf --from-file=traefik-dynamic.toml -n kube-system
    

    创建完成后,再更新 Traefik2.0,就可以将配置文件通过 ConfigMap 挂载到 Traefik Pod 的 /config/traefik-dynamic.toml 路径下面去了。

    创建ConfigMap 对象后再通过kubepi添加挂载点

    或者是

    检查:确保新traefik 的pod起来后,在/config目录下有traefik-dynamic.toml文件

    添加IngressRoute

    ---
    apiVersion: traefik.containo.us/v1alpha1
    kind: IngressRoute
    metadata:
      labels:
        app.kubernetes.io/name: traefik
        kubernetes.io/ingress.class: traefik
      name: app-test
      namespace: test
    spec:
      entryPoints:
        - web
      routes:
        - kind: Rule
          match: Host(`www.daniel.com`)
          services:
            - name: app # 指向app,但是根据traefik-dynamic.toml文件又进行分流,按比例到appv1和appv2
              port: 80
    

    然后将域名www.daniel.com 解析到 Traefik 所在的 Pod,这个时候我们打开两个终端,分别去观察 appv1 和 appv2 两个应用的日志。

    在浏览器中连续访问 www.daniel.com 4 次,我们可以观察到 appv1 这应用会收到 3 次请求,而 appv2 这个应用只收到 1 次请求,符合上面我们的 3:1 的权重配置。


    不知道是否是 Traefik 的 BUG,同时将 KubernetesCRD Provider 和 File Provider 开启的时候,识别不了 File Provider 中的配置,该问题还有待验证。
    traefik版本:2.4.8未出现该问题 :--providers.kubernetescrd

    traefik接口显示内容

    注意:隔天后在访问,会有个奇怪的现象,用firefox:95.0.2版本访问后的结果始终只有一个,用chrome:95.0.4638.54版本则可以进行灰度轮询

  • 相关阅读:
    Java 常见异常种类
    Spring3.2+mybatis3.2+Struts2.3整合配置文件大全
    Java中的基本类型和引用类型变量的区别
    【git】Git 提示fatal: remote origin already exists 错误解决办法
    【Java集合】Java中集合(List,Set,Map)
    POJ3322-经典的游戏搜索问题
    程序人生[流程图]
    不使用中间变量交换两个数
    做人要低调,别把自己太当回事
    【转】嵌套子控件设计时支持
  • 原文地址:https://www.cnblogs.com/sanduzxcvbnm/p/15745879.html
Copyright © 2020-2023  润新知