Traefik 企業(yè)實戰(zhàn):路由規(guī)則篇
Traefik 路由規(guī)則
首先,當部署完后啟動 Traefik 時,定義了入口點(端口號和對應(yīng)的端口名稱),然后 Kubernetes 集群外部就可以通過訪問 Traefik 服務(wù)器地址和配置的入口點對 Traefik 服務(wù)進行訪問,在訪問時一般會帶上 “域名” + “入口點端口”,然后 Traefik 會根據(jù)域名和入口點端口在 Traefik 路由規(guī)則表中進行匹配,如果匹配成功,則將流量發(fā)送到 Kubernetes 內(nèi)部應(yīng)用中與外界進行交互。這里面的域名與入口點與對應(yīng)后臺服務(wù)關(guān)聯(lián)的規(guī)則,即是 Traefik 路由規(guī)則。Traefik 創(chuàng)建路由規(guī)則有多種方式:
- 原生 Ingress 寫法
- 使用 CRD IngressRoute 方式
- 使用 GatewayAPI 的方式(本節(jié)不介紹)
相較于原生 Ingress 寫法,ingressRoute 是 2.1 以后新增功能,簡單來說,他們都支持路徑 (path) 路由和域名 (host) HTTP 路由,以及 HTTPS 配置,區(qū)別在于 IngressRoute 需要定義 CRD 擴展,但是它支持了 TCP、UDP 路由以及中間件等新特性,強烈推薦使用 ingressRoute
ingress方式
ingress-app.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-app
spec:
replicas: 1
selector:
matchLabels:
app: ingress-app
template:
metadata:
labels:
app: ingress-app
spec:
containers:
- name: ingress-app
image: nginx:latest
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello ingress app > /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: ingress-app
spec:
selector:
app: ingress-app
ports:
- name: http
port: 80
targetPort: 80
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-app
spec:
rules:
- host: ingress.kubesre.lc
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ingress-app
port:
name: http
部署查看效果
[root@localhost ~]# kubectl apply -f ingress-app.yaml
deployment.apps/ingress-app created
service/ingress-app created
ingress.networking.k8s.io/ingress-app created
[root@localhost ~]# kubectl get pod,svc,ingress
NAME READY STATUS RESTARTS AGE
pod/ingress-app-578bb77b97-ps9q9 1/1 Running 0 24s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingress-app ClusterIP 10.100.253.185 <none> 80/TCP 24s
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 118d
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/ingress-app traefik ingress.kubesre.lc 80 24s
添加本地hosts解析
本地集群部署了Metallb負載均衡服務(wù),可直接使用LoadBalancer地址
192.168.36.139 ingress.kubesre.lc
訪問 http://ingress.kubesre.lc/
圖片
ingressRoute方式
ingressroute-app.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingressroute-app
spec:
replicas: 1
selector:
matchLabels:
app: ingressroute-app
template:
metadata:
labels:
app: ingressroute-app
spec:
containers:
- name: ingressroute-app
image: nginx:latest
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello ingressroute app > /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: ingressroute-app
spec:
selector:
app: ingressroute-app
ports:
- name: http
port: 80
targetPort: 80
type: ClusterIP
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroute-app
spec:
entryPoints:
- web
routes:
- match: Host(`ingressroute.kubesre.lc`) # 域名
kind: Rule
services:
- name: ingressroute-app # 與svc的name一致
port: 80 # 與svc的port name一致
部署查看效果
[root@localhost ~]# kubectl apply -f ingressroute-app.yaml
deployment.apps/ingressroute-app created
service/ingressroute-app created
ingressroute.traefik.containo.us/ingressroute-app created
[root@localhost ~]# kubectl get pod,svc,ingressroute
NAME READY STATUS RESTARTS AGE
pod/ingressroute-app-64c6b5bd86-dqr2j 1/1 Running 0 94s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingressroute-app ClusterIP 10.103.84.46 <none> 80/TCP 94s
NAME AGE
ingressroute.traefik.containo.us/ingressroute-app 94s
添加本地hosts解析
192.168.36.139 ingressroute.kubesre.lc
訪問 http://ingressroute.kubesre.lc/
圖片
匹配規(guī)則
更多匹配規(guī)則如下
規(guī)則 | 描述 |
Headers(key, value) | 檢查headers中是否有一個鍵為key值為value的鍵值對 |
HeadersRegexp(key, regexp) | 檢查headers中是否有一個鍵位key值為正則表達式匹配的鍵值對 |
Host(example.com, …) | 檢查請求的域名是否包含在特定的域名中 |
HostRegexp(example.com, {subdomain:[a-z]+}.example.com, …) | 檢查請求的域名是否包含在特定的正則表達式域名中 |
Method(GET, …) | 檢查請求方法是否為給定的methods(GET、POST、PUT、DELETE、PATCH)中 |
Path(/path, /articles/{cat:[a-z]+}/{id:[0-9]+}, …) | 匹配特定的請求路徑,它接受一系列文字和正則表達式路徑 |
PathPrefix(/products/, /articles/{cat:[a-z]+}/{id:[0-9]+}) | 匹配特定的前綴路徑,它接受一系列文字和正則表達式前綴路徑 |
Query(foo=bar, bar=baz) | 匹配查詢字符串參數(shù),接受key=value的鍵值對 |
ClientIP(10.0.0.0/16, ::1) | 如果請求客戶端 IP 是給定的 IP/CIDR 之一,則匹配。它接受 IPv4、IPv6 和網(wǎng)段格式。 |
Headers
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroute-app
spec:
entryPoints:
- web
routes:
- match: Host(`ingressroute.kubesre.lc`) && Headers(`X-Custom-Header`, `special-value`)
kind: Rule
services:
- name: ingressroute-app
port: 80
在此示例中,IngressRoute 匹配具有以下條件的請求:
- 主機頭是 ingressroute.kubesre.lc
- 該請求包含一個 X-Custom-Header 值為 的自定義標頭 special-value。
如果傳入請求滿足這些條件,Traefik 會將請求路由到端口 80 上指定的服務(wù)ingressroute-ap,Headers 區(qū)分大小寫。
[root@localhost ~]# curl -H "Host: ingressroute.kubesre.lc" -H "X-Custom-Header: special-value" http://ingressroute.kubesre.lc
Hello ingressroute app
Path
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroute-app
spec:
entryPoints:
- web
routes:
- match: Host(`ingressroute.kubesre.lc`) && Path(`/`)
kind: Rule
services:
- name: ingressroute-app
port: 80
在這個例子中,IngressRoute 配置會匹配 ingressroute.kubesre.lc 域名下的特定 URL 路徑模式。URL 路徑的模式是 / 測試訪問如下:
[root@localhost ~]# curl -H "Host: ingressroute.kubesre.lc" http://ingressroute.kubesre.lc/
Hello ingressroute app
Method
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroute-app
spec:
entryPoints:
- web
routes:
- match: Host(`ingressroute.kubesre.lc`) && Method(`GET`)
kind: Rule
services:
- name: ingressroute-app
port: 80
在這個例子中,IngressRoute 配置會匹配 ingressroute.kubesre.lc 域名下的使用 GET 方法的 HTTP 請求。
[root@localhost ~]# curl -XGET -H "Host: ingressroute.kubesre.lc" http://ingressroute.kubesre.lc/
Hello ingressroute app
配置Https
自簽名證書
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=ingressroute.kubesre.lc"
創(chuàng)建 tls 類型的 secret
kubectl create secret tls myapp-tls --cert=tls.crt --key=tls.key
創(chuàng)建 https的 ingressRoute ingressroute-app-https.yaml:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroute-app-https
spec:
entryPoints:
- websecure
routes:
- match: Host(`ingressroute.kubesre.lc`) # 域名
kind: Rule
services:
- name: ingressroute-app # 與svc的name一致
port: 80 # 與svc的port name一致
tls:
secretName: myapp-tls # 指定tls證書名稱
部署
[root@localhost ~]# kubectl apply -f ingressroute-app-https.yaml
ingressroute.traefik.containo.us/example-ingressroute-https created
[root@localhost ~]# kubectl get ingressroute
NAME AGE
ingressroute-app 8m57s
ingressroute-app-https 2s
訪問 https://ingressroute.kubesre.lc/,此時 http 和 https 站點共存
負載均衡
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroute-app-lb
spec:
entryPoints:
- web # 與 configmap 中定義的 entrypoint 名字相同
routes:
- match: Host(`lb.kubesre.lc`) # 域名
kind: Rule
services:
- name: ingress-app # 與svc的name一致
port: 80 # 與svc的port一致
- name: ingressroute-app # 與svc的name一致
port: 80 # 與svc的port一致
部署
[root@localhost ~]# kubectl apply -f ingressroute-app-lb.yaml
ingressroute.traefik.containo.us/ingressroute-app-lb created
[root@localhost ~]# kubectl get ingressroute
NAME AGE
ingressroute-app 13m
ingressroute-app-https 5m2s
ingressroute-app-lb 27s
添加本地hosts解析
192.168.36.139 lb.kubesre.lc
訪問測試,可以發(fā)現(xiàn) ingress-app 和 ingressroute-app 的內(nèi)容
[root@localhost ~]# curl http://lb.kubesre.lc/
Hello ingressroute app
[root@localhost ~]# curl http://lb.kubesre.lc/
Hello ingress app
[root@localhost ~]# curl http://lb.kubesre.lc/
Hello ingressroute app
[root@localhost ~]# curl http://lb.kubesre.lc/
Hello ingress app