還不會 Traefik?看完這篇文章,你就徹底搞懂了~

大家好,我是喬克。

提到 Traefik,有些人可能並不熟悉,但是提到 Nginx,應該都耳熟能詳。

暫且我們把 Traefik 當成和 Nginx 差不多的一類軟件,待讀完整篇文章,你就會對 Traefik 有不一樣的認識。

本文主要帶大家對 Traefik 有一個全面的認識,我將從下面幾個方面作介紹。

本文基於 Traefik 2.5.3 進行介紹。

什麼是 Traefik

Traefik 是一個開源的邊緣路由網關,它簡單易用並且功能全面。官方【1】的介紹是:Traefik is an [open-source](https://github.com/traefik/traefik) _Edge Router_ that makes publishing your services a fun and easy experience.

Traefik 原生支持多種集羣,如 Kubernetes、Docker、Docker Swarm、AWS、Mesos、Marathon 等;並且可以同時處理許多集羣。

Traefik 的核心概念及能力

Traefik 是一個邊緣路由器,它會攔截外部的請求並根據邏輯規則選擇不同的操作方式,這些規則決定着這些請求到底該如何處理。Traefik 提供自動發現能力,會實時檢測服務,並自動更新路由規則。

從上圖可知,請求首先會連接到entrypoints,然後分析這些請求是否與定義的rules匹配,如果匹配,則會通過一系列middlewares,再到對應的services上。

這就涉及到以下幾個重要的核心組件。

Providers

Providers是基礎組件,Traefik 的配置發現是通過它來實現的,它可以是協調器,容器引擎,雲提供商或者鍵值存儲。

Traefik通過查詢ProvidersAPI來查詢路由的相關信息,一旦檢測到變化,就會動態的更新路由。

Entrypoints

EntrypointsTraefik的網絡入口,它定義接收請求的接口,以及是否監聽 TCP 或者 UDP。

Routers

Routers主要用於分析請求,並負責將這些請求連接到對應的服務上去,在這個過程中,Routers 還可以使用 Middlewares 來更新請求,比如在把請求發到服務之前添加一些 Headers。

Services

Services負責配置如何到達最終將處理傳入請求的實際服務。

Middlewares

Middlewares用來修改請求或者根據請求來做出一些判斷(authentication, rate limiting, headers, ...),中間件被附件到路由上,是一種在請求發送到你的服務之前(或者在服務的響應發送到客戶端之前)調整請求的一種方法。

部署 Traefik

Traefik 的部署方式有多種,這裏主要採用Helm方式進行部署管理。

Helm 部署

環境:kubernetes: 1.22.3 helm: 3.7.1

1、添加 traefik helm 倉庫
$ helm repo add traefik https://helm.traefik.io/traefik
$ helm repo update
2、將 traefik 包下載到本地進行管理
$ helm  search repo traefik
NAME            CHART VERSION APP VERSION DESCRIPTION                                  
traefik/traefik 10.6.0        2.5.3       A Traefik based Kubernetes ingress controller
$ helm pull traefik/traefik
3、部署 Traefik

默認的value.yaml[2] 配置文件配置比較多,可能需要花一定的時間去梳理,不過根據相關的註釋還是可以很快的理解。

這裏自定義一個配置文件my-value.yaml,如下:

service:
  type: NodePort 

ingressRoute:
  dashboard:
    enabled: false
ports:
  traefik:
    port: 9000
    expose: true
  web:
    port: 8000
    expose: true
  websecure:
    port: 8443
    expose: true
persistence:
  enabled: true
  name: data
  accessMode: ReadWriteOnce
  size: 5G
  storageClass: "openebs-hostpath"
  path: /data
additionalArguments:
  - "--serversTransport.insecureSkipVerify=true"
  - "--api.insecure=true"
  - "--api.dashboard=true"

進行部署,命令如下:

$ kubectl create ns traefik-ingress
$ helm install traefik -n traefik-ingress -f my-value.yaml .

這裏不是使用的是默認的value.yaml[2] 配置文件。

然後可以看到部署結果,如下:

# kubectl get all -n traefik-ingress 
NAME                           READY   STATUS    RESTARTS   AGE
pod/traefik-77ff894bb5-qqszd   1/1     Running   0          6m26s

NAME              TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                                     AGE
service/traefik   NodePort   10.108.170.22   <none>        9000:32271/TCP,80:31728/TCP,443:30358/TCP   6m26s

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/traefik   1/1     1            1           6m26s

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/traefik-77ff894bb5   1         1         1       6m26s

然後可以通過NodePort訪問 Dashboard 頁面,如下:

使用 Traefik

創建第一個路由規則

我們上面訪問 Dashboard 是採用的NodePort的方式,既然已經把Traefik部署好了,爲什麼不使用路由網關的方式呢?

下面我們就來創建第一個路由網關來訪問Dashboard

Traefik 創建路由規則有多種方式,比如:

這裏暫時介紹前面兩種方式,關於 GatewayAPI 的方式在後續進行介紹。

原生 Ingress 路由規則

原生 Ingress 的路由規則,寫法就比較簡單,如下。

# cat traefik-ingress.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: traefik-dashboard-ingress
  annotations:
    kubernetes.io/ingress.class: traefik  
    traefik.ingress.kubernetes.io/router.entrypoints: web
spec:
  rules:
  - host: traefik-web.coolops.cn 
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: traefik
            port:
              number: 9000

創建路由規則,命令如下:

# kubectl apply -f traefik-ingress.yaml -n traefik-ingress 
ingress.networking.k8s.io/traefik-dashboard-ingress created

現在就可以通過域名 http://traefik-web.coolops.cn:31728/dashboard/#/ 進行訪問了(31728 是 80 端口的映射端口),如下:

使用 CRD 方式配置路由規則

在早期版本,Traefik 僅提供 kubernetes ingress 方式配置路由規則,社區認爲採用開發一個自定義 CRD 的類型能夠更好的提供 Kubernetes 的訪問配置【3】。

IngressRoute的配置方式也比較簡單,如下:

# cat traefik-ingressRoute.yaml 
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: traefik-dashboard-route
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`traefik-web2.coolops.cn`)
    kind: Rule
    services:
      - name: traefik
        port: 9000

部署命令如下:

# kubectl apply -f traefik-ingressRoute.yaml -n traefik-ingress 
ingressroute.traefik.containo.us/traefik-dashboard-route created

然後就可以通過 http://traefik-web2.coolops.cn:31728/dashboard/#/ 進行訪問了。

暴露 HTTP 服務

首先,部署一個簡單的whoami[4] 應用,YAML 文件如下:

---
apiVersion: v1
kind: Pod
metadata:
  name: whoami
  labels:
    app: whoami
spec:
  containers:
    - name: whoami
      image: traefik/whoami:latest
      ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: whoami
spec:
  ports:
    - port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app: whoami
  type: ClusterIP

部署成功後,創建一個路由規則,使外部可以訪問。

# cat ingressroute.yaml 
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-route
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`whoami.coolops.cn`)
    kind: Rule
    services:
      - name: whoami
        port: 80

創建過後,就可以進行訪問了,如下:

暴露 HTTPS 服務

上面的whoami應用,是通過HTTP進行訪問的,如果要通過HTTPS進行訪問,應該如何配置呢?

Traefik支持 HTTPS 和 TLS,對於證書可以選擇自有證書,也可以使用 Let's Encrypt【5】自動生成證書。這裏會分別介紹這兩種方式。

自有證書配置 HTTPS

現在公司基本都會自己購買更安全的證書,那對於自有證書配置 HTTPS 就會使用更加頻繁,這裏主要介紹這種配置方式。

1、申請或者購買證書

我這裏是在騰訊雲申請的免費證書。然後下載對應的證書,並上傳到服務器上。

2、將證書文件保存爲 Secret
# kubectl create secret tls whoami-tls --cert=1_whoami.coolops.cn_bundle.crt --key=2_whoami.coolops.cn.key
3、創建 IngressRoute 對象,使其可以通過 TLS 訪問
# cat ingressroutetls.yaml 
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-route-tls
spec:
  entryPoints:
  - websecure
  routes:
  - match: Host(`whoami.coolops.cn`)
    kind: Rule
    services:
      - name: whoami
        port: 80 
  tls:
    secretName: whoami-tls

創建完成後,就可以通過 https://whoami.coolops.cn:30358/ 進行訪問了(30358 是 443 映射出來的端口)。

自動生成 HTTPS 證書

Traefik除了使用自有證書外,還支持Let's Encrypt自動生成證書【6】。

要使用Let's Encrypt自動生成證書,需要使用ACME。需要在靜態配置中定義 "證書解析器",Traefik負責從ACME服務器中檢索證書。

然後,每個 "路由器" 被配置爲啓用 TLS,並通過 tls.certresolver 配置選項與一個證書解析器關聯。

TraefikACME驗證方式主要有以下三種:

如果使用tlsChallenge,則要求Let's Encrypt到 Traefik 443 端口必須是可達的。如果使用httpChallenge,則要求Let's Encrypt到 Traefik 80端口必須是可達的。如果使用dnsChallenge,則需要對應的providers[7]。

但是我們上面部署Traefik的時候並沒有把 80 和 443 端口暴露出來,要測試tlsChallengehttpChallenge的話就必須暴露,下面我們更改一下my-value.yaml,如下:

service:
  type: NodePort 

ingressRoute:
  dashboard:
    enabled: false
ports:
  traefik:
    port: 9000
    expose: true
  web:
    port: 8000
    hostPort: 80
    expose: true
  websecure:
    port: 8443
    hostPort: 443
    expose: true
persistence:
  enabled: true
  name: data
  accessMode: ReadWriteOnce
  size: 5G
  storageClass: "openebs-hostpath"
  path: /data
additionalArguments:
  - "--serversTransport.insecureSkipVerify=true"
  - "--api.insecure=true"
  - "--api.dashboard=true"

然後重新更新一下Traefik,命令如下:

helm upgrade traefik -n traefik-ingress -f my-value.yaml .

現在我們就可以直接通過 80 或 443 端口進行訪問了。

1、tlsChallenge

上面已經介紹過,要使用tlsChallenge,必須能訪問入口的 443 端口,現在我們入口已經放開,接下來就修改Traefikmy-value.yaml配置,如下:

......
deployment:
  initContainers:
    - name: volume-permissions
      image: busybox:1.31.1
      command: ["sh""-c""chmod -Rv 600 /data/*"]
      volumeMounts:
        - name: data
          mountPath: /data
additionalArguments:
  - "--serversTransport.insecureSkipVerify=true"
  - "--api.insecure=true"
  - "--api.dashboard=true"
  - "--certificatesresolvers.coolops.acme.email=coolops@163.com"
  - "--certificatesresolvers.coolops.acme.storage=/data/acme.json"
  - "--certificatesresolvers.coolops.acme.tlschallenge=true"

PS:這裏需要將 / data 目錄權限給更改一下,默認是 0660, 權限太大是不允許的。

然後我們創建一個ingressRoute,如下:

# cat ingressrouteautotls.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-route-auto-tls
spec:
  entryPoints:
  - websecure
  routes:
  - match: Host(`whoami3.coolops.cn`)
    kind: Rule
    services:
      - name: whoami
        port: 80 
  tls:
    certResolver: coolops

這時候我們訪問 https://whoami3.coolops.cn 是可以正常使用證書的,如下:

2、httpChallenge

下面再使用httpChallenge進行測試,修改my-value.yaml配置文件如下:

......
deployment:
  initContainers:
    - name: volume-permissions
      image: busybox:1.31.1
      command: ["sh""-c""chmod -Rv 600 /data/*"]
      volumeMounts:
        - name: data
          mountPath: /data
additionalArguments:
  - "--serversTransport.insecureSkipVerify=true"
  - "--api.insecure=true"
  - "--api.dashboard=true"
  - "--certificatesresolvers.coolops.acme.email=coolops@163.com"
  - "--certificatesresolvers.coolops.acme.storage=/data/acme.json"
  - "--certificatesresolvers.coolops.acme.httpchallenge=true"
  - "--certificatesresolvers.coolops.acme.httpchallenge.entrypoint=web"

更新Traefik過後,然後再創建一個ingressRoute進行測試,YAML 文件如下:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-route-auto-tls-http
spec:
  entryPoints:
  - websecure
  routes:
  - match: Host(`whoami4.coolops.cn`)
    kind: Rule
    services:
      - name: whoami
        port: 80
  tls:
    certResolver: coolops

然後使用https://whoami4.coolops.cn,效果如下:

3、dnsChallenge

dnsChallenge在使用上相對比較麻煩,因爲需要配置對應的provider,不過它可以生成通配符證書,這裏以阿里雲 DNS【8】爲例。

使用阿里 DNS 的前提是您的域名是在阿里雲上面,不然在簽署證書的時候會報錯,如下:

Unable to obtain ACME certificate for domains \"*.coolops.cn\" : unable to generate a certificate for the domains [*.coolops.cn]: error: one or more domains had a problem:\n[*.coolops.cn] [*.coolops.cn] acme: error presenting token: alicloud: zone coolops.cn. not found in AliDNS for domain coolops.cn\n" providerName=coolops.acme

使用阿里雲的 DNS 校驗需要配置 3 個環境變量:ALICLOUD_ACCESS_KEYALICLOUD_SECRET_KEYALICLOUD_REGION_ID,分別對應我們平時開發阿里雲應用的時候的密鑰,可以登錄阿里雲後臺獲取,由於這是比較私密的信息,所以我們用 Secret 對象來創建:

$ kubectl create secret generic traefik-alidns --from-literal=ALICLOUD_ACCESS_KEY=<aliyun ak> --from-literal=ALICLOUD_SECRET_KEY=<aliyun sk>--from-literal=ALICLOUD_REGION_ID=cn-beijing -n traefik-ingress

修改 Traefik 的 my-value.yaml,如下:

......
additionalArguments:
  - "--serversTransport.insecureSkipVerify=true"
  - "--api.insecure=true"
  - "--api.dashboard=true"
  - "--certificatesresolvers.coolops.acme.email=coolops@163.com"
  - "--certificatesresolvers.coolops.acme.storage=/data/acme.json"
  - "--certificatesresolvers.coolops.acme.dnschallenge=true"
  - "--certificatesResolvers.coolops.acme.dnsChallenge.provider=alidns"
envFrom:
  - secretRef: 
      name: traefik-alidns

更新Traefik過後,然後再創建一個ingressRoute進行測試,YAML 文件如下(由於 coolops.cn 不在阿里雲上,所以換了一個域名):

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-route-auto-tls-dns
spec:
  entryPoints:
  - websecure
  routes:
  - match: Host(`whoami6.coolops.cn`)
    kind: Rule
    services:
      - name: whoami
        port: 80 
  tls:
    certResolver: coolops 
    domains:
    - main: "*.coolops.cn"

然後訪問域名後,就可以看到證書籤署 成功,如下:

中間件的使用

在介紹Traefik的核心概念的時候有提到一個請求匹配Rules後,會經過一系列的Middleware,再到具體的Services上。這個Middleware是什麼呢?

MiddlewareTraefik 2.0之後新增的功能,用戶可以根據不通的需求來選擇不同的 Middleware 來滿足服務,提高了定製化的能力。

Traefik 內置了很多不同功能的 Middleware,主要是針對 HTTP 和 TCP,HTTP 佔大部分 [9],這裏挑選幾個比較常用的進行演示。

強制跳轉 HTTPS

強制跳轉 HTTPS 是經常會配置的功能,這裏還是以上沒的whoami應用爲例。

1、創建一個 HTTPS 的 ingressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-route-auto-tls
spec:
  entryPoints:
  - websecure
  routes:
  - match: Host(`whoami3.coolops.cn`)
    kind: Rule
    services:
      - name: whoami
        port: 80 
  tls:
    certResolver: coolops
2、定義一個跳轉 HTTPS 的中間件

這裏會用到RedirectScheme的內置中間件,配置如下:

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: redirect-https-middleware
spec:
  redirectScheme:
    scheme: https
3、定義一個 HTTP 的 ingressRoute,並使用 Middleware
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami3-route
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`whoami3.coolops.cn`)
    kind: Rule
    services:
      - name: whoami
        port: 80
    middlewares:
    - name: redirect-https-middleware

然後訪問http://whoami3.coolops.cn就會被強制跳轉到https://whoami3.coolops.cn

去除請求路徑前綴

有時候會遇到這麼一個需求:

這種需求是非常常見的,在NGINX中,我們可以配置多個Location來定製規則,使用Traefik也可以這麼做。

但是定製不同的前綴後,由於應用本身並沒有這些前綴,導致請求返回404,這時候我們就需要對請求的path進行處理,還是以whoami應用爲例。

1、創建一個帶前綴的 ingressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami7-route
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`whoami7.coolops.cn`) && PathPrefix('/coolops')
    kind: Rule
    services:
      - name: whoami
        port: 80

我們現在訪問是會返回404狀態的。

2、定義去除前綴的中間件
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: prefix-coolops-url-middleware
spec:
  stripPrefix:
    prefixes:
      - /coolops
3、修改上面的 ingressRoute,應用中間件
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami7-route
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`whoami7.coolops.cn`) && PathPrefix('/coolops')
    kind: Rule
    services:
      - name: whoami
        port: 80
    middlewares:
    - name: prefix-coolops-url-middleware

然後就可以正常訪問了。

添加 IP 白名單

在工作中,有一些 URL 並不希望對外暴露,比如 prometheus、grafana 等的 url,這時候我們希望通過白名單 IP 來達到需求,就可以使用Traefik中的ipWhiteList中間件來完成。

1、定義白名單 IP 的中間件
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: ip-white-list-middleware
spec:
  ipWhiteList:
    sourceRange:
      - 127.0.0.1/32
      - 192.168.100.180

然後將中間件應用到對應的 Rules 上,就可以完成白名單功能。

除了上面的功能,Traefik 內置 Middleware 還支持很多其他功能,比如限流、認證鑑權等,可以通過引用【9】進行查看。

暴露 TCP 服務

Traefik 2.0 支持暴露 TCP,這裏以 Redis 爲例。

1、部署一個 Redis 服務
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec:
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:5.0.14
        ports:
        - containerPort: 6379
          protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    app: redis
2、暴露 Redis 端口

暴露 TCP 端口使用的是 SNI【10】,而 SNI 又是依賴 TLS 的,所以我們需要配置證書纔行,但是如果沒有證書的話,我們可以使用通配符*進行配置。

(1)、添加一個 redis 的 entrypoints

修改Traefik的部署文件my-value.yaml,添加如下內容:

ports:
  traefik:
    port: 9000
    expose: true
  web:
    port: 8000
    hostPort: 80
    expose: true
  websecure:
    port: 8443
    hostPort: 443
    expose: true
  redis:
    port: 6379
    containerPort: 6379
    hostPort: 6379
additionalArguments:
  - "--entryPoints.redis.address=:6379"
  - "--serversTransport.insecureSkipVerify=true"
  - "--api.insecure=true"
  - "--api.dashboard=true"
  - "--certificatesresolvers.coolops.acme.email=coolops@163.com"
  - "--certificatesresolvers.coolops.acme.storage=/data/acme.json"
  - "--certificatesresolvers.coolops.acme.httpchallenge=true"
  - "--certificatesresolvers.coolops.acme.httpchallenge.entrypoint=web"

在啓動參數中添加--entryPoints.redis.address=:6379用來指定 entrypoint。

(2)、創建 ingressRoute 進行對外暴露
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
  name: redis-traefik-tcp
spec:
  entryPoints:
    - redis
  routes:
  - match: HostSNI(`*`)
    services:
    - name: redis
      port: 6379

然後可以使用客戶端工具進行 Redis 的操作了。

# redis-cli -h redis.coolops.cn 
redis.coolops.cn:6379> set  a b
OK
redis.coolops.cn:6379> get a
"b"
redis.coolops.cn:6379>

灰度發佈

Traefik2.0 以後的一個更強大的功能就是灰度發佈,灰度發佈我們有時候也會稱爲金絲雀發佈(Canary),主要就是讓一部分測試的服務也參與到線上去,經過測試觀察看是否符號上線要求。

假設一個應用現在運行着V1版本,新的V2版本需要上線,這時候我們需要在集羣中部署好V2版本,然後通過Traefik提供的帶權重的輪詢(WRR)來實現該功能。

1、部署 appv1、appv2 應用

appv1.yaml

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: appv1
spec:
  selector:
    matchLabels:
      app: appv1
  template:
    metadata:
      labels:
        use: test
        app: appv1
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        lifecycle:
          postStart:
            exec:
              command:  ["/bin/sh""-c""echo Hello v1 > /usr/share/nginx/html/index.html"]
        ports:
        - containerPort: 80
          name: portv1

---

apiVersion: v1
kind: Service
metadata:
  name: appv1
spec:
  selector:
    app: appv1
  ports:
  - name: http
    port: 80
    targetPort: portv1

appv2.yaml

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: appv2
spec:
  selector:
    matchLabels:
      app: appv2
  template:
    metadata:
      labels:
        use: test
        app: appv2
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        lifecycle:
          postStart:
            exec:
              command:  ["/bin/sh""-c""echo Hello v2 > /usr/share/nginx/html/index.html"]
        ports:
        - containerPort: 80
          name: portv2

---

apiVersion: v1
kind: Service
metadata:
  name: appv2
spec:
  selector:
    app: appv2
  ports:
  - name: http
    port: 80
    targetPort: portv2
2、創建 TraefikService

在 Traefik2.1 以後新增了一個 TraefikService的 CRD 資源,我們可以直接利用這個對象來配置 WRR

apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
  name: app-wrr
spec:
  weighted:
    services:
      - name: appv1
        weight: 3
        port: 80
        kind: Service
      - name: appv2
        weight: 1
        port: 80
        kind: Service
3、創建 ingressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: app-ingressroute-canary 
spec:
  entryPoints:
    - web
  routes:
  - match: Host(`app.coolops.cn`)
    kind: Rule
    services:
    - name: app-wrr
      kind: TraefikService

注意:這裏配置的不是Service類型,而是TraefikService

然後就可以通過訪問http://app.coolops.cn來校驗結果。

V2測試沒問題後,就可以將流量全切到V2了。

流量複製

Traefik 2.0之後還引入了鏡像服務[11],它可以將請求的流量按規則複製一份發送給其他服務,並且會忽略這部分請求的響應。

這個功能在做一些壓測或者問題復現的時候還是很有用。

這裏依然以上沒的 appv1 和 appv2 爲例進行簡單的演示。

1、創建 TraefikService,定義複製規則
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
  name: app-mirror
spec:
  mirroring:
    name: appv1
    port: 80
    mirrors:
    - name: appv2
      percent: 50
      port: 80

上面定義的意思是將請求到 appv1 的 50% 請求複製到 appv2。

2、創建 ingressRoute,進行效果演示
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: app-ingressroute-mirror
spec:
  entryPoints:
    - web
  routes:
  - match: Host(`mirror.coolops.cn`)
    kind: Rule
    services:
    - name: app-mirror
      kind: TraefikService

然後進行測試,效果如下:

發了 4 次請求,appv1 可以正常接收 4 次請求,appv2 可以收到 2 次請求,收到的響應是 appv1 的,並沒有 appv2 的響應。

Kubernetes Gateway API

我們在上面創建路由規則要麼使用ingress,要麼使用ingressRoute,其實在Traefik 2.4以後支持Kubernetes Gateway API[12] 提供的CRD方式創建路由規則。

什麼是 Gateway API?

Gateway API【13】是一個由SIG-NETWORK社區管理的開源項目。它是Kubernetes中服務網絡模型的資源集合。這些資源(GatewayClass、Gateway、HTTPRoute、TCPRoute、Service)旨在通過表達式的、可擴展的和麪向角色的接口來發展 Kubernetes 服務網絡,這些接口由許多供應商實現,並得到了廣泛的行業支持。

使用 Gateway API

1、安裝 Gateway API 的 CRD

Traefik Gateway provider 僅支持 v0.3.0 (v1alpha1).

kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.3.0" \
| kubectl apply -f -
2、創建 rbac,給 traefik 授權
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: gateway-role
rules:
  - apiGroups:
      - ""
    resources:
      - services
      - endpoints
      - secrets
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - networking.x-k8s.io
    resources:
      - gatewayclasses
      - gateways
      - httproutes
      - tcproutes
      - tlsroutes
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - networking.x-k8s.io
    resources:
      - gatewayclasses/status
      - gateways/status
      - httproutes/status
      - tcproutes/status
      - tlsroutes/status
    verbs:
      - update

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: gateway-controller

roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: gateway-role
subjects:
  - kind: ServiceAccount
    name: traefik
    namespace: traefik-ingress
2、Traefik 開啓 gateway api 支持

修改my-value.yaml 文件,如下:

......
additionalArguments:
  - "--entryPoints.redis.address=:6379"
  - "--serversTransport.insecureSkipVerify=true"
  - "--api.insecure=true"
  - "--api.dashboard=true"
  - "--certificatesresolvers.coolops.acme.email=coolops@163.com"
  - "--certificatesresolvers.coolops.acme.storage=/data/acme.json"
  - "--certificatesresolvers.coolops.acme.httpchallenge=true"
  - "--certificatesresolvers.coolops.acme.httpchallenge.entrypoint=web"
  - "--experimental.kubernetesgateway"
  - "--providers.kubernetesgateway"

更新 Traefik,命令如下:

helm upgrade traefik -n traefik-ingress -f my-value.yaml .
4、通過 Gateway api 的方式暴露 traefik dashboard 應用
(1)、創建 GatewayClass
apiVersion: networking.x-k8s.io/v1alpha1
kind: GatewayClass
metadata:
  name: traefik
spec:
  controller: traefik.io/gateway-controller
(2)、創建 gateway
apiVersion: networking.x-k8s.io/v1alpha1
kind: Gateway
metadata: 
  name: http-gateway
  namespace: traefik-ingress 
spec: 
  gatewayClassName: traefik
  listeners: 
    - protocol: HTTP
      port: 8000 
      routes: 
        kind: HTTPRoute
        namespaces:
          from: All
        selector:
          matchLabels:
            app: traefik
(3)、創建 HTTPRoute
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
  name: whoami-gateway-api-route 
  namespace: traefik-ingress
  labels:
    app: traefik
spec:
  hostnames:
    - "traefik1.coolops.cn"
  rules:
    - matches:
        - path:
            type: Prefix
            value: /
      forwardTo:
        - serviceName: traefik 
          port: 9000
          weight: 1
(4)、現在就可以直接在瀏覽器訪問了

GatewayClass在集羣中可以只創建一個,然後GatewayHTTPRoute是需要對應的。

比如我這裏要暴露 default 命名空間下的 whoami 應用,YAML 就應該如下:

apiVersion: networking.x-k8s.io/v1alpha1
kind: Gateway
metadata: 
  name: http-gateway
spec: 
  gatewayClassName: traefik
  listeners: 
    - protocol: HTTP
      port: 8000 
      routes: 
        kind: HTTPRoute
        namespaces:
          from: All
        selector:
          matchLabels:
            app: whoami
---
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
  name: whoami-gateway-api-route 
  labels:
    app: whoami 
spec:
  hostnames:
    - "whoami8.coolops.cn"
  rules:
    - matches:
        - path:
            type: Prefix
            value: /
      forwardTo:
        - serviceName: whoami 
          port: 80
          weight: 1

最後

Traefik是一個功能比較強大的邊緣網關,基本能滿足絕大部分的場景需求,而且還有Mesh等工具,比較好用,有興趣的朋友可以到官網 [14] 進行學習,也歡迎交流。

最後,求關注。如果你還想看更多優質原創文章,歡迎關注我們的公衆號「運維開發故事」。

如果我的文章對你有所幫助,還請幫忙點贊、在看、轉發一下,你的支持會激勵我輸出更高質量的文章,非常感謝!

來源:本文轉自公衆號 “運維開發故事”,點擊查看原文

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/wfBfQ0pzhNh7-A31aPIG6A