更新時間:2019-12-12 來源:黑馬程序員 瀏覽量:
Traefik目前的最新版本是 v2.0.2,截止該版本,要實現灰度發布、流量復制這些高級功能,只能通過 File Provider 來實現。
灰度發布我們有時候也會稱為金絲雀發布(Canary),主要就是讓一部分測試的服務也參與到線上去,經過測試觀察看是否符號上線要求。
發布架構概述
canary deployment(灰度發布 NGINX服務)
比如現在有兩個名為 appv1 和 appv2 的 Nginx 服務,我們希望通過 Traefik 來控制我們的流量,將 3?4 的流量路由到 appv1,1/4 的流量路由到 appv2 去,這個時候就可以利用 Traefik2.0 中提供的帶權重的輪詢(WRR)來實現該功能,首先在 Kubernetes 集群中部署上面的兩個服務。
NGINX-server1服務的資源清單
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服務的資源清單
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 ```
直接創建上面兩個服務:
```shell
$ kubectl apply -f appv1.yaml
$ kubectl apply -f appv2.yaml
通過下面的命令可以查看服務是否運行成功
$ 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 這個功能目前只支持 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 動態更新配置:
```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 獲取。
創建對應的 ConfigMap 對象
上面是開啟 `File Provider` 的配置,接下來需要創建對應的 ConfigMap 對象,首先創建一個名為 `traefik-dynamic.toml` 的文件,內容如下所示:
``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/"
```
上面這個配置文件就是我們需要配置的灰度發布的規則
創建一個名為 Router0 的路由,在 web 這個入口點上面監聽 Host=nginx.chuanzhi.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/ 這個真實的服務上。
現在通過上面的配置文件來創建對應的 ConfigMap 對象:
shell $ kubectl create configmap traefik-dynamic-conf --from-file=traefik-dynamic.toml -n kube-system
測試及日志分析
然后將域名 nginx.chuanzhi.com 解析到 Traefik 所在的 Pod,這個時候我們打開兩個終端,分別去觀察 appv1 和 appv2 兩個應用的日志。
在瀏覽器中連續訪問 nginx.chuanzhi.com 4 次,我們可以觀察到 appv1 這應用會收到 3 次請求,而 appv2 這個應用只收到 1 次請求,符合上面我們的 3:1的權重配置。推薦了解linux云計算+運維開發課程。
不知道是否是 Traefik 的 BUG,同時將 KubernetesCRD Provider 和 File Provider 開啟的時候,識別不了 File Provider 中的配置,該問題還有待驗證。
在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 # 權重
- name: appv2
port: 80
weight: 1 # 權重
```
這種配置方式支持k8s的service服務發現