Traefik 2.0新增了很多高级功能,灰度发布就是其中一个,本文我们来介绍一下基于Traefik 2.0实现灰度发布。

    注意: 目前最新版本是v2.1.1,截至目前版本要实现灰度发布、流量复制等高级功能,只能通过File Provider来实现。不能使用KubernetesCRD Provider了。

    灰度发布,就是将测试的服务放到生产去跑,然后观察是否符合上线要求,如下:
    12.1.5、灰度发布 - 图1
    1、我们把测试服务放到生产,接入少部分流量来进行观察;
    2、如果测试观察没问题,就符合上线要求,可以慢慢增加新版本数量,减少旧版本数量;
    3、如果测试观察有问题,就需要切掉该版本,对测试用户进行修数处理;

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

    appv1的资源清单(appv1.yaml)

    1. apiVersion: apps/v1
    2. kind: Deployment
    3. metadata:
    4. name: appv1
    5. namespace: default
    6. spec:
    7. selector:
    8. matchLabels:
    9. app: appv1
    10. template:
    11. metadata:
    12. labels:
    13. use: test
    14. app: appv1
    15. spec:
    16. containers:
    17. - name: nginx
    18. image: nginx
    19. ports:
    20. - containerPort: 80
    21. name: portv1
    22. ---
    23. apiVersion: v1
    24. kind: Service
    25. metadata:
    26. name: appv1
    27. namespace: default
    28. spec:
    29. selector:
    30. app: appv1
    31. ports:
    32. - name: http
    33. port: 80
    34. targetPort: portv1

    appv2的资源清单(appv2.yaml)

    1. apiVersion: apps/v1
    2. kind: Deployment
    3. metadata:
    4. name: appv2
    5. namespace: default
    6. spec:
    7. selector:
    8. matchLabels:
    9. app: appv2
    10. template:
    11. metadata:
    12. labels:
    13. use: test
    14. app: appv2
    15. spec:
    16. containers:
    17. - name: nginx
    18. image: nginx
    19. ports:
    20. - containerPort: 80
    21. name: portv2
    22. ---
    23. apiVersion: v1
    24. kind: Service
    25. metadata:
    26. name: appv2
    27. namespace: default
    28. spec:
    29. selector:
    30. app: appv2
    31. ports:
    32. - name: http
    33. port: 80
    34. targetPort: portv2

    然后创建这两个资源清单:

    1. # kubectl get pod
    2. NAME READY STATUS RESTARTS AGE
    3. appv1-684f8cbc7-kr4d5 1/1 Running 0 3m53s
    4. appv2-645d7666b5-thgt2 1/1 Running 0 3m53s

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

    1. kind: Deployment
    2. apiVersion: extensions/v1beta1
    3. metadata:
    4. name: traefik
    5. namespace: kube-system
    6. labels:
    7. k8s-app: traefik-ingress-lb
    8. spec:
    9. selector:
    10. matchLabels:
    11. k8s-app: traefik-ingress-lb
    12. template:
    13. metadata:
    14. labels:
    15. k8s-app: traefik-ingress-lb
    16. name: traefik-ingress-lb
    17. spec:
    18. serviceAccountName: traefik-ingress-controller
    19. tolerations:
    20. - operator: "Exists"
    21. nodeSelector:
    22. kubernetes.io/hostname: 172.16.0.33
    23. containers:
    24. - image: traefik:v2.0
    25. name: traefik-ingress-lb
    26. ports:
    27. - name: web
    28. containerPort: 80
    29. - name: websecure
    30. containerPort: 443
    31. - name: admin
    32. containerPort: 8080
    33. - name: redis
    34. containerPort: 6379
    35. volumeMounts:
    36. - name: config
    37. mountPath: /config
    38. args:
    39. - --entrypoints.web.Address=:80
    40. - --entrypoints.websecure.Address=:443
    41. - --entrypoints.redis.Address=:6379
    42. - --entrypoints.foo
    43. - --api.insecure=true
    44. - --providers.kubernetescrd
    45. - --providers.file.watch=true
    46. - --providers.file.filename=/config/traefik-dynamic.toml
    47. - --api
    48. - --api.dashboard=true
    49. - --accesslog
    50. # 使用 tls 验证这种方式
    51. - --certificatesresolvers.default.acme.tlsChallenge=true
    52. # # 邮箱配置
    53. - --certificatesResolvers.default.acme.email=rookieops@163.com
    54. # # 保存 ACME 证书的位置
    55. - --certificatesResolvers.default.acme.storage="acme.json"
    56. # # 下面是用于测试的ca服务,如果https证书生成成功了,则移除下面参数
    57. #- --certificatesresolvers.default.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
    58. - --certificatesresolvers.default.acme.caserver=https://acme-v02.api.letsencrypt.org/directory
    59. volumes:
    60. - name: config
    61. configMap:
    62. name: traefik-dynamic-conf
    63. ---
    64. kind: Service
    65. apiVersion: v1
    66. metadata:
    67. name: traefik
    68. namespace: kube-system
    69. spec:
    70. type: NodePort
    71. selector:
    72. k8s-app: traefik-ingress-lb
    73. ports:
    74. - protocol: TCP
    75. port: 8080
    76. name: admin
    77. - name: web
    78. port: 80
    79. protocol: TCP
    80. - name: websecure
    81. port: 443
    82. protocol: TCP
    83. - name: redis
    84. port: 6379
    85. protocol: TCP

    上面是开启 File Provider 的配置,接下来需要创建对应的 ConfigMap 对象,首先创建一个名为 traefik-dynamic.toml 的文件,内容如下所示:

    1. [http]
    2. [http.routers]
    3. [http.routers.Router0]
    4. entryPoints = ["web"]
    5. service = "app"
    6. rule = "Host(`nginx.rookieops.top`)"
    7. [http.services]
    8. [http.services.app]
    9. [[http.services.app.weighted.services]]
    10. name = "appv1"
    11. weight = 3
    12. [[http.services.app.weighted.services]]
    13. name = "appv2"
    14. weight = 1
    15. [http.services.appv1]
    16. [http.services.appv1.loadBalancer]
    17. [[http.services.appv1.loadBalancer.servers]]
    18. url = "http://appv1.default.svc.cluster.local/"
    19. [http.services.appv2]
    20. [http.services.appv2.loadBalancer]
    21. [[http.services.appv2.loadBalancer.servers]]
    22. url = "http://appv2.default.svc.cluster.local/"

    上面这个配置文件就是我们需要配置的灰度发布的规则,创建一个名为 Router0 的路由,在 web 这个入口点上面监听 Host=nginx.rookieops.top 这样的请求,将请求路由给名为 app 的服务,而该服务则将请求路由给了 appv1 这个服务,权重为 3,另外一部分请求路由给了 appv2 这个服务,权重为 1,也就是有 3⁄4 的请求会被路由到 http://appv1.default.svc.cluster.local/ 这个真实的服务上,同样的另外的 1⁄4 请求会被路由到 http://appv2.default.svc.cluster.local/ 这个真实的服务上。

    然后创建这个ConfigMap:

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

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

    然后我们测试观察如下:
    image.png