首頁技術(shù)文章正文

Traefik2.0 如何實(shí)現(xiàn)灰度測試?

更新時(shí)間:2019-12-12 來源:黑馬程序員 瀏覽量:

Traefik目前的最新版本是 v2.0.2,截止該版本,要實(shí)現(xiàn)灰度發(fā)布、流量復(fù)制這些高級功能,只能通過 File Provider 來實(shí)現(xiàn)。

灰度發(fā)布我們有時(shí)候也會(huì)稱為金絲雀發(fā)布(Canary),主要就是讓一部分測試的服務(wù)也參與到線上去,經(jīng)過測試觀察看是否符號(hào)上線要求。


1576137828931_Traefik2.0-灰度測試.jpg

發(fā)布架構(gòu)概述

canary deployment(灰度發(fā)布 NGINX服務(wù))

比如現(xiàn)在有兩個(gè)名為 appv1 和 appv2 的 Nginx 服務(wù),我們希望通過 Traefik 來控制我們的流量,將 3?4 的流量路由到 appv1,1/4 的流量路由到 appv2 去,這個(gè)時(shí)候就可以利用 Traefik2.0 中提供的帶權(quán)重的輪詢(WRR)來實(shí)現(xiàn)該功能,首先在 Kubernetes 集群中部署上面的兩個(gè)服務(wù)。

NGINX-server1服務(wù)的資源清單

appv1.yaml

```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 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 ```


NGINX-server2服務(wù)的資源清單

appv1.yaml

```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 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 ```

直接創(chuàng)建上面兩個(gè)服務(wù):

```shell
$ kubectl apply -f appv1.yaml
$ kubectl apply -f appv2.yaml

通過下面的命令可以查看服務(wù)是否運(yùn)行成功

$ kubectl get pods -l use=test -n kube-system
NAME                     READY   STATUS    RESTARTS   AGE
appv1-684f8cbc7-b9zm9    1/1     Running   0          2m27s
appv2-645d7666b5-qjrjs   1/1     Running   0          37s
```

ConfigMap 開啟Provider


由于 WRR 這個(gè)功能目前只支持 File Provider,所以我們需要開啟該 Provider 才能使用,這里需要注意的是由于需要開啟 File Provider,所以我們需要提供一個(gè)文件用于該 Provider 的配置,我們這里是用在 Kubernetes 集群中的,所以可以通過一個(gè) ConfigMap 對象,將配置文件內(nèi)容掛載到 Traefik 的 Pod 中去,如下所示,我們通過將一個(gè)名為 traefik-dynamic-conf 的 ConfigMap 對象掛載到了 /config 目錄下面去,然后通過 --providers.file.filename參數(shù)指定配置文件開啟 File Provider,另外添加 - --providers.file.watch=true 參數(shù)可以讓 Traefik 動(dòng)態(tài)更新配置:

```yaml
......
      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 獲取。

創(chuàng)建對應(yīng)的 ConfigMap 對象

上面是開啟 `File Provider` 的配置,接下來需要?jiǎng)?chuàng)建對應(yīng)的 ConfigMap 對象,首先創(chuàng)建一個(gè)名為 `traefik-dynamic.toml` 的文件,內(nèi)容如下所示:

``toml [http] [http.routers] [http.routers.Router0] entryPoints = ["web"] service = "app" rule = "Host(nginx.chuanzhi.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/"

```

上面這個(gè)配置文件就是我們需要配置的灰度發(fā)布的規(guī)則

創(chuàng)建一個(gè)名為 Router0 的路由,在 web 這個(gè)入口點(diǎn)上面監(jiān)聽 Host=nginx.chuanzhi.com 這樣的請求,將請求路由給名為 app 的服務(wù),而該服務(wù)則將請求路由給了 appv1 這個(gè)服務(wù),權(quán)重為 3,另外一部分請求路由給了 appv2 這個(gè)服務(wù),權(quán)重為 1,也就是有 3?4 的請求會(huì)被路由到 http://appv1/ 這個(gè)真實(shí)的服務(wù)上,這個(gè)地址也就是我們 Kubernetes 集群中的 appv1 這個(gè) Service 對象的 FQDN 地址,當(dāng)然我們也可以用全路徑(http://appv1.kube-system.svc.cluster.local:80)表示,因?yàn)槎荚?kube-system 這個(gè)命名空間下面,所以直接用服務(wù)名也是可以的,同樣的另外的 1?4 請求會(huì)被路由到 http://appv2/ 這個(gè)真實(shí)的服務(wù)上。

現(xiàn)在通過上面的配置文件來創(chuàng)建對應(yīng)的 ConfigMap 對象:

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

測試及日志分析

然后將域名 nginx.chuanzhi.com 解析到 Traefik 所在的 Pod,這個(gè)時(shí)候我們打開兩個(gè)終端,分別去觀察 appv1 和 appv2 兩個(gè)應(yīng)用的日志。

在瀏覽器中連續(xù)訪問 nginx.chuanzhi.com 4 次,我們可以觀察到 appv1 這應(yīng)用會(huì)收到 3 次請求,而 appv2 這個(gè)應(yīng)用只收到 1 次請求,符合上面我們的 3:1的權(quán)重配置。推薦了解linux云計(jì)算+運(yùn)維開發(fā)課程。

1576137846139_Traefik2.0-2.jpg


不知道是否是 Traefik 的 BUG,同時(shí)將 KubernetesCRD Provider 和 File Provider 開啟的時(shí)候,識(shí)別不了 File Provider 中的配置,該問題還有待驗(yàn)證。

在2.0.4 版本中測試通過支持crd 方式 金絲雀部署 如下:

```
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  creationTimestamp: '2019-11-06T15:53:21Z'
  generation: 1
  name: traefik-nginx
  namespace: default
spec:
  entryPoints:
    - web
  routes:
    - kind: Rule
      match: Host(`ng.101.101.244.212.nip.io`) && PathPrefix(`/`)
      services:
        - name: appv1
          port: 80
          weight: 3    # 權(quán)重
        - name: appv2
          port: 80
          weight: 1    # 權(quán)重
```

這種配置方式支持k8s的service服務(wù)發(fā)現(xiàn)

分享到:
在線咨詢 我要報(bào)名
和我們在線交談!