Kubernetes 1.18.3 部署 Traefik2.2
Traefik的中間件,灰度發布,流量復制基於上篇文章環境。
1.部署whoami
應用和SVC
apiVersion: v1
kind: Service
metadata:
name: whoami
spec:
ports:
- protocol: TCP
name: web
port: 80
selector:
app: whoami
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: whoami
labels:
app: whoami
spec:
replicas: 2
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- name: whoami
image: containous/whoami
ports:
- name: web
containerPort: 80
2.部署 IngressRoute 對象
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: simpleingressroute
spec:
entryPoints:
- web
routes:
- match: Host(`who.heian.com`) && PathPrefix(`/notls`)
kind: Rule
services:
- name: whoami
port: 80
3.配置 HTTPS 路由
[root@k8s-master1 who]# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=who.heian.com"
Generating a 2048 bit RSA private key
..........................................................................+++
..........+++
writing new private key to 'tls.key'
-----
[root@k8s-master1 who]# kubectl create secret tls who-tls --cert=tls.crt --key=tls.key
secret/who-tls created
創建一個 HTTPS 訪問應用的 IngressRoute 對象
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroutetls
spec:
entryPoints:
- websecure
routes:
- match: Host(`who.heian.com`) && PathPrefix(`/tls`)
kind: Rule
services:
- name: whoami
port: 80
tls:
secretName: who-tls
4 . 中間件
中間件是 Traefik2.0 中一個非常有特色的功能,我們可以根據自己的各種需求去選擇不同的中間件來滿足服務,Traefik 官方已經內置了許多不同功能的中間件,其中一些可以修改請求,頭信息,一些負責重定向,一些添加身份驗證等等,而且中間件還可以通過鏈式組合的方式來適用各種情況。
同樣比如上面我們定義的 whoami 這個應用,我們可以通過 https://who.heian.com/tls
來訪問到應用,但是如果我們用 http
來訪問的話呢就不行了,就會404了,因為我們根本就沒有簡單80端口這個入口點,
所以要想通過 http
來訪問應用的話自然我們需要監聽下 web
這個入口點:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroutetls-http
spec:
entryPoints:
- web
routes:
- match: Host(`who.heian.com`) && PathPrefix(`/tls`)
kind: Rule
services:
- name: whoami
port: 80
注意這里我們創建的 IngressRoute 的 entryPoints 是 web
,然后創建這個對象,這個時候我們就可以通過 http 訪問到這個應用了。
但是我們如果只希望用戶通過 https 來訪問應用的話呢?按照以前的知識,我們是不是可以讓 http 強制跳轉到 https 服務去,對的,在 Traefik 中也是可以配置強制跳轉的,只是這個功能現在是通過中間件來提供的了。
如下所示,我們使用 redirectScheme
中間件來創建提供強制跳轉服務:
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: redirect-https
spec:
redirectScheme:
scheme: https
然后將這個中間件附加到 http 的服務上面去,因為 https 的不需要跳轉:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroutetls-http
spec:
entryPoints:
- web
routes:
- match: Host(`who.heian.com`) && PathPrefix(`/tls`)
kind: Rule
services:
- name: whoami
port: 80
middlewares:
- name: redirect-https
這個時候我們再去訪問 http 服務可以發現就會自動跳轉到 https 去了。關於更多中間件的用法可以查看文檔 Traefik Docs。
5. 灰度發布
Traefik2.0 的一個更強大的功能就是灰度發布,灰度發布我們有時候也會稱為金絲雀發布(Canary),主要就是讓一部分測試的服務也參與到線上去,經過測試觀察看是否符號上線要求。
比如現在我們有兩個名為 appv1
和 appv2
的服務,我們希望通過 Traefik 來控制我們的流量,將 3⁄4 的流量路由到 appv1,¼ 的流量路由到 appv2 去,這個時候就可以利用 Traefik2.0 中提供的帶權重的輪詢(WRR)來實現該功能
首先在 Kubernetes 集群中部署上面的兩個服務。
為了對比結果我們這里提供的兩個服務一個是 heian99/myapp:v2,一個是heian99/myapp:v1,方便測試。
appv1 服務的資源清單如下所示:(appv1.yaml)heian99/myapp:v1
apiVersion: apps/v1
kind: Deployment
metadata:
name: appv1
spec:
selector:
matchLabels:
app: appv1
template:
metadata:
labels:
use: test
app: appv1
spec:
containers:
- name: myappv1
image: heian99/myapp:v1
ports:
- containerPort: 80
name: portv1
---
apiVersion: v1
kind: Service
metadata:
name: appv1
spec:
selector:
app: appv1
ports:
- name: http
port: 80
targetPort: portv1
appv2 服務的資源清單如下所示:(appv2.yaml)heian99/myapp:v2
apiVersion: apps/v1
kind: Deployment
metadata:
name: appv2
spec:
selector:
matchLabels:
app: appv2
template:
metadata:
labels:
use: test
app: appv2
spec:
containers:
- name: myappv2
image: heian99/myapp:v2
ports:
- containerPort: 80
name: portv2
---
apiVersion: v1
kind: Service
metadata:
name: appv2
spec:
selector:
app: appv2
ports:
- name: http
port: 80
targetPort: portv2
直接創建上面兩個服務:
[root@k8s-master1 test]# kubectl apply -f .
deployment.apps/appv1 created
service/appv1 created
deployment.apps/appv2 created
service/appv2 created
[root@k8s-master1 test]# kubectl get pods -l use=test
NAME READY STATUS RESTARTS AGE
appv1-597bbc966f-chwpj 1/1 Running 0 69s
appv2-5f5489b4c5-7gsnd 1/1 Running 0 69s
在 Traefik2.1 中新增了一個 TraefikService
的 CRD 資源,我們可以直接利用這個對象來配置 WRR,之前的版本需要通過 File Provider,比較麻煩,新建一個描述 WRR 的資源清單:(wrr.yaml)
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
name: app-wrr
spec:
weighted:
services:
- name: appv1
weight: 3 # 定義權重
port: 80
kind: Service # 可選,默認就是 Service
- name: appv2
weight: 1
port: 80
然后為我們的灰度發布的服務創建一個 IngressRoute 資源對象:(ingressroute.yaml)
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: wrringressroute
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`app.heian.com`)
kind: Rule
services:
- name: app-wrr
kind: TraefikService
不過需要注意的是現在我們配置的 Service 不再是直接的 Kubernetes 對象了,而是上面我們定義的 TraefikService 對象,直接創建上面的兩個資源對象,這個時候我們對域名 app.heian.com
做上解析,去瀏覽器中連續訪問 4 次,我們可以觀察到 appv1 這應用會收到 3 次請求,而 appv2 這個應用只收到 1 次請求,符合上面我們的 3:1
的權重配置。
6. 流量復制
除了灰度發布之外,Traefik 2.0 還引入了流量鏡像服務,是一種可以將流入流量復制並同時將其發送給其他服務的方法,鏡像服務可以獲得給定百分比的請求同時也會忽略這部分請求的響應。
同樣的在 2.0 中只能通過 FileProvider 進行配置,在 2.1 版本中我們已經可以通過 TraefikService
資源對象來進行配置了,現在我們部署兩個 whoami 的服務,資源清單文件如下所示:
apiVersion: v1
kind: Service
metadata:
name: v1
spec:
ports:
- protocol: TCP
name: web
port: 80
selector:
app: v1
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: v1
labels:
app: v1
spec:
selector:
matchLabels:
app: v1
template:
metadata:
labels:
app: v1
spec:
containers:
- name: v1
image: heian99/myapp:v1
ports:
- name: web
containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: v2
spec:
ports:
- protocol: TCP
name: web
port: 80
selector:
app: v2
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: v2
labels:
app: v2
spec:
selector:
matchLabels:
app: v2
template:
metadata:
labels:
app: v2
spec:
containers:
- name: v2
image: heian99/myapp:v2
ports:
- name: web
containerPort: 80
現在我們創建一個 IngressRoute 對象,將服務 v1 的流量復制 50% 到服務 v2,如下資源對象所示:(mirror-ingress-route.yaml)
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
name: app-mirror
spec:
mirroring:
name: v1 # 發送 100% 的請求到 K8S 的 Service "v1"
port: 80
mirrors:
- name: v2 # 然后復制 50% 的請求到 v2
percent: 50
port: 80
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: mirror-ingress-route
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`mirror.heian.com`)
kind: Rule
services:
- name: app-mirror
kind: TraefikService # 使用聲明的 TraefikService 服務,而不是 K8S 的 Service
這個時候我們在瀏覽器中去連續訪問4次 mirror.heian.com
可以發現有一半的請求也出現在了 v2
這個服務中: