Traefik 企業實戰:TraefikService篇
簡介
traefik 的路由規則就可以實現 4 層和 7 層的基本負載均衡操作,使用 IngressRoute IngressRouteTCP IngressRouteUDP 資源即可。但是如果想要實現 加權輪詢、流量復制 等高級操作,traefik抽象出了一個 TraefikService 資源。此時整體流量走向為:外部流量先通過 entryPoints 端口進入 traefik,然后由 IngressRoute/IngressRouteTCP/IngressRouteUDP 匹配后進入 TraefikService,在 TraefikService 這一層實現加權輪循和流量復制,最后將請求轉發至kubernetes的service。
創建Demo應用
app-v1.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-v1
spec:
replicas: 1
selector:
matchLabels:
app: app-v1
template:
metadata:
labels:
app: app-v1
spec:
containers:
- name: app-v1
image: nginx:latest
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello app-v1 > /usr/share/nginx/html/index.html"]
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: app-v1
spec:
selector:
app: app-v1
ports:
- name: http
port: 80
targetPort: 80
type: ClusterIP
app-v2.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-v2
spec:
replicas: 1
selector:
matchLabels:
app: app-v2
template:
metadata:
labels:
app: app-v2
spec:
containers:
- name: app-v2
image: nginx:latest
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello app-v2 > /usr/share/nginx/html/index.html"]
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: app-v2
spec:
selector:
app: app-v2
ports:
- name: http
port: 80
targetPort: 80
type: ClusterIP
部署
[root@localhost traefik]# kubectl apply -f app-v1.yaml
deployment.apps/app-v1 created
service/app-v1 created
[root@localhost traefik]# kubectl apply -f app-v2.yaml
deployment.apps/app-v2 created
service/app-v2 created
[root@localhost traefik]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/app-v1-579dbbb754-nwtzw 1/1 Running 0 2m23s
pod/app-v2-7f7844f7b9-grsdk 1/1 Running 0 2m19s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/app-v1 ClusterIP 10.100.10.94 <none> 80/TCP 2m23s
service/app-v2 ClusterIP 10.104.145.150 <none> 80/TCP 2m18s
灰度發布(加權輪詢)
灰度發布也稱為金絲雀發布,讓一部分即將上線的服務發布到線上,觀察是否達到上線要求,主要通過加權輪詢的方式實現。創建 traefikService 和 inressRoute 資源,實現 wrr 加權輪詢 app-traefikService-ingressroute-wrr.yaml:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: app-ingressroute-wrr
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`traefikservice-wrr.kubesre.lc`)
kind: Rule
services:
- name: wrr
namespace: default
kind: TraefikService
---
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
name: wrr
namespace: default
spec:
weighted:
services:
- name: app-v1
port: 80
weight: 1 # 定義權重
kind: Service # 可選,默認就是 Service
- name: app-v2
port: 80
weight: 2
部署
[root@localhost traefik]# kubectl apply -f app-traefikService-ingressroute-wrr.yaml
ingressroute.traefik.containo.us/app-ingressroute-wrr created
traefikservice.traefik.containo.us/wrr created
[root@localhost traefik]# kubectl get ingressroute
NAME AGE
app-ingressroute-wrr 6s
[root@localhost traefik]# kubectl get TraefikService
NAME AGE
wrr 3m42s
添加本地hosts解析
192.168.36.139 traefikservice-wrr.kubesre.lcc
測試結果如下:
[root@localhost traefik]# for i in {1..9}; do curl http://traefikservice-wrr.kubesre.lc && sleep 1; done
Hello app-v1
Hello app-v2
Hello app-v2
Hello app-v1
Hello app-v2
Hello app-v2
Hello app-v1
Hello app-v2
Hello app-v2
會話保持(粘性會話)
當我們使用 traefik 的負載均衡時,默認情況下輪循多個 k8s 的 service 服務,如果用戶對同一內容的多次請求,可能被轉發到了不同的后端服務器。假設用戶發出請求被分配至服務器 A,保存了一些信息在 session 中,該用戶再次發送請求被分配到服務器 B,要用之前保存的信息,若服務器 A 和 B 之間沒有 session 粘滯,那么服務器 B 就拿不到之前的信息,這樣會導致一些問題。traefik 同樣也支持粘性會話,可以讓用戶在一次會話周期內的所有請求始終轉發到一臺特定的后端服務器上。創建 traefikervie 和 ingressRoute,實現基于 cookie 的會話保持 app-traefikService-ingressroute-cokie.yaml:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: app-ingressroute-cokie
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`traefikservice-cokie.kubesre.lc`)
kind: Rule
services:
- name: cokie
namespace: default
kind: TraefikService
---
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
name: cokie
namespace: default
spec:
weighted:
services:
- name: app-v1
port: 80
weight: 1 # 定義權重
- name: app-v2
port: 80
weight: 2
sticky: # 開啟粘性會話
cookie: # 基于cookie區分客戶端
name: cookie # 指定客戶端請求時,包含的cookie名稱
部署
[root@localhost traefik]# kubectl apply -f app-traefikService-ingressroute-cokie.yaml
ingressroute.traefik.containo.us/app-ingressroute-cokie created
traefikservice.traefik.containo.us/cokie created
[root@localhost traefik]# kubectl get ingressroute
NAME AGE
app-ingressroute-cokie 5s
[root@localhost traefik]# kubectl get TraefikService
NAME AGE
cokie 8s
添加本地hosts解析
192.168.36.139 traefikservice-cokie.kubesre.lcc
客戶端訪問測試,攜帶 cookie
[root@localhost traefik]# for i in {1..5}; do curl -b "cookie=default-app-v1-80" http://traefikservice-cokie.kubesre.lc/; done
Hello app-v1
Hello app-v1
Hello app-v1
Hello app-v1
Hello app-v1
[root@localhost traefik]# for i in {1..5}; do curl -b "cookie=default-app-v2-80" http://traefikservice-cokie.kubesre.lc/; done
Hello app-v2
Hello app-v2
Hello app-v2
Hello app-v2
Hello app-v2
流量復制
所謂的流量復制,也稱為鏡像服務是指將請求的流量按規則復制一份發送給其它服務,并且會忽略這部分請求的響應,這個功能在做一些壓測或者問題復現的時候很有用。創建 traefikService 和 ingressRoute app-traefikService-ingressroute-copy.yaml:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: app-ingressroute-copy
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`traefikservice-copy.kubesre.lc`)
kind: Rule
services:
- name: copy
namespace: default
kind: TraefikService
---
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
name: copy
namespace: default
spec:
mirroring:
name: app-v1 # 發送 100% 的請求到 app-v1
port: 80
mirrors:
- name: app-v2 # 然后復制 10% 的請求到 app-v2
port: 80
percent: 10
部署
[root@localhost traefik]# kubectl apply -f app-traefikService-ingressroute-copy.yaml
ingressroute.traefik.containo.us/app-ingressroute-copy created
traefikservice.traefik.containo.us/copy created
[root@localhost traefik]# kubectl get ingressroute
NAME AGE
app-ingressroute-copy 7s
[root@localhost traefik]# kubectl get TraefikService
NAME AGE
copy 13s
添加本地hosts解析
192.168.36.139 traefikservice-copy.kubesre.lc
測試結果如下:只能看到 app-v1的返回信息,
[root@localhost traefik]# for i in {1..9}; do curl http://traefikservice-copy.kubesre.lc && sleep 1; done
Hello app-v1
Hello app-v1
Hello app-v1
Hello app-v1
Hello app-v1
Hello app-v1
Hello app-v1
Hello app-v1
Hello app-v1
查看app-v2的pod日志,發現會有10%的流量請求進來
[root@localhost traefik]# kubectl logs -f app-v2-7f7844f7b9-grsdk
...
10.244.0.5 - - [23/Aug/2023:02:54:36 +0000] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0" "10.244.0.1"