Traefik高级应用实战案例
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
目录
一.环境准备
1.编写资源清单
[root@master241 ingressroutes]# cat 15-deploy-svc-cm-lb-web.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-lb-web
data:
web01: |
server {
listen 81;
listen [::]:81;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
web02: |
server {
listen 82;
listen [::]:82;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-web01
spec:
replicas: 1
selector:
matchLabels:
apps: web01
template:
metadata:
labels:
apps: web01
school: oldboyedu
spec:
volumes:
- emptyDir: {}
name: data
- name: webconf
configMap:
name: cm-lb-web
items:
- key: web01
path: default.conf
initContainers:
- name: i1
image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
env:
- name: PODNAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: PODNS
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: PODIP
valueFrom:
fieldRef:
fieldPath: status.podIP
volumeMounts:
- name: data
mountPath: /oldboyedu
command:
- /bin/sh
- -c
- 'echo "<h1> 【web01】 NameSpace: ${PODNS}, PodName: ${PODNAME}, PodIP:${PODIP}</h1>" > /oldboyedu/index.html'
containers:
- name: c1
image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
- name: webconf
mountPath: /etc/nginx/conf.d/default.conf
subPath: default.conf
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-web02
spec:
replicas: 1
selector:
matchLabels:
apps: web02
template:
metadata:
labels:
apps: web02
school: oldboyedu
spec:
volumes:
- emptyDir: {}
name: data
- name: webconf
configMap:
name: cm-lb-web
items:
- key: web02
path: default.conf
initContainers:
- name: i1
image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
env:
- name: PODNAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: PODNS
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: PODIP
valueFrom:
fieldRef:
fieldPath: status.podIP
volumeMounts:
- name: data
mountPath: /oldboyedu
command:
- /bin/sh
- -c
- 'echo "<h1> 【web02】 NameSpace: ${PODNS}, PodName: ${PODNAME}, PodIP:${PODIP}</h1>" > /oldboyedu/index.html'
containers:
- name: c1
image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
- name: webconf
mountPath: /etc/nginx/conf.d/default.conf
subPath: default.conf
---
apiVersion: v1
kind: Service
metadata:
name: svc-web01
spec:
ports:
- port: 80
targetPort: 81
selector:
apps: web01
type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
name: svc-web02
spec:
ports:
- port: 80
targetPort: 82
selector:
apps: web02
type: ClusterIP
[root@master241 ingressroutes]#
2.创建资源
[root@master241 ingressroutes]# kubectl apply -f 15-deploy-svc-cm-lb-web.yaml
configmap/cm-lb-web created
deployment.apps/deploy-web01 created
deployment.apps/deploy-web02 created
service/svc-web01 created
service/svc-web02 created
[root@master241 ingressroutes]#
[root@master241 ingressroutes]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.192.0.1 <none> 443/TCP 7h40m
svc-web01 ClusterIP 10.205.250.219 <none> 80/TCP 3s
svc-web02 ClusterIP 10.195.214.57 <none> 80/TCP 3s
[root@master241 ingressroutes]#
3.访问svc测试
[root@master241 ingressroutes]# curl 10.205.250.219
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
[root@master241 ingressroutes]#
[root@master241 ingressroutes]# curl 10.195.214.57
<h1> 【web02】 NameSpace: default, PodName: deploy-web02-f5f565d77-2lxjn, PodIP:10.100.207.52</h1>
[root@master241 ingressroutes]#
二.Traefik高级应用实战案例
1.负载均衡案例
1.1 创建IngressRoute资源
1.编写IngressRoute资源清单
[root@master241 ingressroutes]# cat 16-IngressRoute-lb-xiuxian.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: ingressroute-lb
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`lb.yinzhengjie.com`) && PathPrefix(`/`)
kind: Rule
services:
- name: svc-web01
port: 80
namespace: default
- name: svc-web02
port: 80
namespace: default
[root@master241 ingressroutes]#
2.创建IngressRoute资源并查看详细信息
[root@master241 ingressroutes]# kubectl apply -f 16-IngressRoute-lb-xiuxian.yaml
ingressroute.traefik.io/ingressroute-lb created
[root@master241 ingressroutes]#
[root@master241 ingressroutes]# kubectl describe -f 16-IngressRoute-lb-xiuxian.yaml
Name: ingressroute-lb
Namespace: default
Labels: <none>
Annotations: <none>
API Version: traefik.io/v1alpha1
Kind: IngressRoute
Metadata:
Creation Timestamp: 2025-06-06T09:33:40Z
Generation: 1
Resource Version: 2203471
UID: 0202fa07-b554-4948-a20d-7a1987c83332
Spec:
Entry Points:
web
Routes:
Kind: Rule
Match: Host(`lb.yinzhengjie.com`) && PathPrefix(`/`)
Services:
Name: svc-web01
Namespace: default
Port: 80
Name: svc-web02
Namespace: default
Port: 80
Events: <none>
[root@master241 ingressroutes]#
1.2 访问测试
1.添加解析记录
[root@worker242 ~]# echo 10.0.0.150 lb.yinzhengjie.com >> /etc/hosts
[root@worker242 ~]#
[root@worker242 ~]# tail -1 /etc/hosts
10.0.0.150 lb.yinzhengjie.com
[root@worker242 ~]#
2.访问测试
[root@worker242 ~]# for i in `seq 10`; do curl lb.yinzhengjie.com; done
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web02】 NameSpace: default, PodName: deploy-web02-f5f565d77-2lxjn, PodIP:10.100.207.52</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web02】 NameSpace: default, PodName: deploy-web02-f5f565d77-2lxjn, PodIP:10.100.207.52</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web02】 NameSpace: default, PodName: deploy-web02-f5f565d77-2lxjn, PodIP:10.100.207.52</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web02】 NameSpace: default, PodName: deploy-web02-f5f565d77-2lxjn, PodIP:10.100.207.52</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web02】 NameSpace: default, PodName: deploy-web02-f5f565d77-2lxjn, PodIP:10.100.207.52</h1>
[root@worker242 ~]#
2.灰度发布
2.1 基于TraefikService实现基于权重的调度策略
[root@master241 ingressroutes]# cat 17-TraefikService-weighted.yaml
apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: traefikservices-wrr
namespace: default
spec:
# 基于权重调度
weighted:
services:
- name: svc-web01
port: 80
# 定义调度到该svc的权重
weight: 4
# 指定类型有效值为: Service(default), TraefikService
kind: Service
- name: svc-web02
port: 80
weight: 1
[root@master241 ingressroutes]#
[root@master241 ingressroutes]# kubectl apply -f 17-TraefikService-weighted.yaml
traefikservice.traefik.io/traefikservices-wrr created
[root@master241 ingressroutes]#
[root@master241 ingressroutes]# kubectl describe -f 17-TraefikService-weighted.yaml
Name: traefikservices-wrr
Namespace: default
Labels: <none>
Annotations: <none>
API Version: traefik.io/v1alpha1
Kind: TraefikService
Metadata:
Creation Timestamp: 2025-06-06T09:42:43Z
Generation: 1
Resource Version: 2204585
UID: 78bb12fe-a163-4cb9-abe4-863aa544cb6c
Spec:
Weighted:
Services:
Kind: Service
Name: svc-web01
Port: 80
Weight: 4
Name: svc-web02
Port: 80
Weight: 1
Events: <none>
[root@master241 ingressroutes]#
2.2 创建IngressRoute资源引用TraefikService而非svc
[root@master241 ingressroutes]# cat 18-IngressRoute-TraefikService.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: ingressroute-lb-wrr
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`lb.yinzhengjie.com`) && PathPrefix(`/`)
kind: Rule
services:
# 指定TraefikService的名称
- name: traefikservices-wrr
namespace: default
# 注意,类型不再是k8s的Service,而是Traefik自实现的TraefikService
kind: TraefikService
[root@master241 ingressroutes]#
[root@master241 ingressroutes]# kubectl apply -f 18-IngressRoute-TraefikService.yaml
ingressroute.traefik.io/ingressroute-lb-wrr created
[root@master241 ingressroutes]#
[root@master241 ingressroutes]#
[root@master241 ingressroutes]# kubectl describe -f 18-IngressRoute-TraefikService.yaml
Name: ingressroute-lb-wrr
Namespace: default
Labels: <none>
Annotations: <none>
API Version: traefik.io/v1alpha1
Kind: IngressRoute
Metadata:
Creation Timestamp: 2025-06-06T09:49:22Z
Generation: 1
Resource Version: 2205407
UID: d53b0586-626c-4632-991b-1b52ec4a5cbf
Spec:
Entry Points:
web
Routes:
Kind: Rule
Match: Host(`lb.yinzhengjie.com`) && PathPrefix(`/`)
Services:
Kind: TraefikService
Name: traefikservices-wrr
Namespace: default
Events: <none>
2.3 访问测试
[root@worker242 ~]# for i in `seq 10`; do curl -s lb.yinzhengjie.com; done
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web02】 NameSpace: default, PodName: deploy-web02-f5f565d77-2lxjn, PodIP:10.100.207.52</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web02】 NameSpace: default, PodName: deploy-web02-f5f565d77-2lxjn, PodIP:10.100.207.52</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
[root@worker242 ~]#
[root@worker242 ~]# for i in `seq 10`; do curl -s lb.yinzhengjie.com; done | sort | uniq -c
8 <h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
2 <h1> 【web02】 NameSpace: default, PodName: deploy-web02-f5f565d77-2lxjn, PodIP:10.100.207.52</h1>
[root@worker242 ~]#
3.流量镜像|影子流量(Mirroring/traffic-shadow)
3.1 基于TraefikService实现基于流量镜像
[root@master241 ingressroutes]# cat 19-TraefikService-mirroring.yaml
apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: traefikservices-mirroring
namespace: default
spec:
# 发送 100% 的请求到K8S名为"svc-web01"的Service。
mirroring:
kind: Service
name: svc-web01
port: 80
# 将其中20%的请求调度到k8s名为"svc-web02"的Service。
mirrors:
- name: svc-web02
port: 80
# 是指将20%请求的流量复制一份发送给其它'svc-web02'服务,并且会忽略这部分请求的响应,这个功能在做一些压测或者问题复现的时候很有用。
percent: 20
[root@master241 ingressroutes]#
[root@master241 ingressroutes]# kubectl apply -f 19-TraefikService-mirroring.yaml
traefikservice.traefik.io/traefikservices-mirroring created
[root@master241 ingressroutes]#
[root@master241 ingressroutes]# kubectl describe -f 19-TraefikService-mirroring.yaml
Name: traefikservices-mirroring
Namespace: default
Labels: <none>
Annotations: <none>
API Version: traefik.io/v1alpha1
Kind: TraefikService
Metadata:
Creation Timestamp: 2025-06-06T10:00:12Z
Generation: 1
Resource Version: 2206748
UID: 690e7dea-6f53-417e-92b5-d081cf3f0abd
Spec:
Mirroring:
Mirrors:
Name: svc-web02
Percent: 20
Port: 80
Name: svc-web01
Port: 80
Events: <none>
[root@master241 ingressroutes]#
3.2 创建IngressRoute资源引用TraefikService而非svc
[root@master241 ingressroutes]# cat 20-IngressRoute-TraefikService.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: ingressroute-mirror
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`lb.yinzhengjie.com`) && PathPrefix(`/`)
kind: Rule
services:
- name: traefikservices-mirroring
namespace: default
kind: TraefikService
[root@master241 ingressroutes]#
[root@master241 ingressroutes]# kubectl apply -f 20-IngressRoute-TraefikService.yaml
ingressroute.traefik.io/ingressroute-mirror created
[root@master241 ingressroutes]#
[root@master241 ingressroutes]# kubectl describe -f 20-IngressRoute-TraefikService.yaml
Name: ingressroute-mirror
Namespace: default
Labels: <none>
Annotations: <none>
API Version: traefik.io/v1alpha1
Kind: IngressRoute
Metadata:
Creation Timestamp: 2025-06-06T10:02:03Z
Generation: 1
Resource Version: 2206973
UID: 1d336ce6-fef2-472d-b5aa-fbfef40c0bd1
Spec:
Entry Points:
web
Routes:
Kind: Rule
Match: Host(`lb.yinzhengjie.com`) && PathPrefix(`/`)
Services:
Kind: TraefikService
Name: traefikservices-mirroring
Namespace: default
Events: <none>
[root@master241 ingressroutes]#
3.3 访问测试
1.所有流量都打到了svc-web01
[root@worker242 ~]# for i in `seq 10`; do curl -s lb.yinzhengjie.com; done
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
<h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
[root@worker242 ~]#
[root@worker242 ~]# for i in `seq 10`; do curl -s lb.yinzhengjie.com; done | sort | uniq -c
10 <h1> 【web01】 NameSpace: default, PodName: deploy-web01-59d78b6c58-mdb4l, PodIP:10.100.207.53</h1>
[root@worker242 ~]#
2.查看svc-web01后端Pod日志
[root@master241 ingressroutes]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deploy-web01-59d78b6c58-mdb4l 1/1 Running 0 40m 10.100.207.53 worker243 <none> <none>
deploy-web02-f5f565d77-2lxjn 1/1 Running 0 40m 10.100.207.52 worker243 <none> <none>
[root@master241 ingressroutes]#
[root@master241 ingressroutes]# kubectl logs -f deploy-web01-59d78b6c58-mdb4l
... # 不难发现,上面访问执行了2次,对应产生了20条访问记录
10.100.207.42 - - [06/Jun/2025:10:06:37 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:06:37 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:06:37 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:06:37 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:06:37 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:06:37 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:06:37 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:06:37 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:06:37 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:06:37 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:07:45 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:07:45 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:07:45 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:07:45 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:07:45 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:07:45 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:07:45 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:07:45 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:07:45 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:07:45 +0000] "GET / HTTP/1.1" 200 102 "-" "curl/7.81.0" "10.0.0.242"
3.查看svc-web02后端Pod日志
[root@master241 traefik]# kubectl logs -f deploy-web02-f5f565d77-2lxjn
... # 不难发现,上面访问执行了2次,对应产生了4条访问记录
10.100.207.42 - - [06/Jun/2025:10:06:37 +0000] "GET / HTTP/1.1" 200 101 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:06:37 +0000] "GET / HTTP/1.1" 200 101 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:07:45 +0000] "GET / HTTP/1.1" 200 101 "-" "curl/7.81.0" "10.0.0.242"
10.100.207.42 - - [06/Jun/2025:10:07:45 +0000] "GET / HTTP/1.1" 200 101 "-" "curl/7.81.0" "10.0.0.242"
3.4 总结
流量镜像,也称为影子流量,是指将请求的流量按规则复制一份发送给其它服务,并且会忽略这部分请求的响应,这个功能在做一些压测或者问题复现的时候很有用。
通过上述的演示我们会发现所有的流量100%发送了svc-web01,有20%的流量被复制到svc-web02,且用户收到响应均来自svc-web01,而svc-web02并没有响应客户端,可通过查看svc-web01及svc-web02应用访问日志。
本文来自博客园,作者:尹正杰,转载请注明原文链接:https://www.cnblogs.com/yinzhengjie/p/18919982,个人微信: "JasonYin2020"(添加时请备注来源及意图备注,有偿付费)
当你的才华还撑不起你的野心的时候,你就应该静下心来学习。当你的能力还驾驭不了你的目标的时候,你就应该沉下心来历练。问问自己,想要怎样的人生。