通過 Traefik 使用 Kubernetes Service APIs 進行流量路由 (http,https,金絲雀發布)


文章轉載自:https://mp.weixin.qq.com/s?__biz=MzU4MjQ0MTU4Ng==&mid=2247490229&idx=1&sn=ca8170548b2ea6e4d2cd8518fded3853&chksm=fdb915a8cace9cbe070a4431cc8dd0602e715b902a027967497feb5316ec5ff014afbff358e8&cur_album_id=1319287026209947648&scene=190#rd

Traefik 在2.4 版本中引入了對 Service APIs 的初始支持。本文我們將演示如何通過 Traefik 來使用新的 Gateway、GatewayClass 和 HTTPRoute API 將請求路由到后端的服務 Pod。

本文講述的相當於是使用新的Service APIs形式提供http,https,金絲雀發布等有關路由功能,之前使用的是Ingress 或 IngressRoute 資源來實現這些功能的

環境

在開始使用之前我們需要先准備相關的環境:

  • 一個運行的 Kubernetes 集群,本文會假設它運行在 localhost 上。
  • kubectl 命令行工具,並配置成訪問你的集群。

本文涉及的相關配置文件可以通過下面的 GitHub 倉庫獲取:

git clone https://github.com/traefik-tech-blog/k8s-service-apis

安裝 CRD

由於目前 Kubernetes 集群上默認沒有安裝 Service APIs,所以我們需要先安裝一組支持他們的 CRD 資源,需要保證在 Traefik 中啟用 Service APIs 支持之前安裝這些資源。

目前我們可以直接使用 0.10 版本進行安裝:

kubectl apply -k "github.com/kubernetes-sigs/service-apis/config/crd?ref=v0.1.0"

安裝配置 Traefik

目前需要 Traefik 2.4+ 版本才支持 Service APIs,所以我們需要安裝 Traefik v2.4(或更高版本)並配置啟用新的 Provider,這里我們可以直接使用官方的 Helm Chart 包進行安裝:

helm repo add traefik https://helm.traefik.io/traefik
helm repo update
helm install traefik --set experimental.kubernetesGateway.enabled=true traefik/traefik

注意上面我們設置的 --set experimental.kubernetesGateway.enabled=true參數,上面的命令會安裝 Traefik 2.4,並啟用新的 Service APIs Provider,還將創建 GatewayClasses 和一個 Gateway 實例。如果還有更多的定制安裝需求,我們可以直接通過覆蓋 Chart 包的 Values 值,比如可以配置 label selector 或者 TLS 證書等等。

要驗證新功能是否已經被啟用,這里我們使用端口轉發來直接暴露 Traefik 的 Dashboard。

kubectl port-forward $(kubectl get pods --selector "app.kubernetes.io/name=traefik" --output=name) 9000:9000

然后使用瀏覽器通過 http://localhost:9000/dashboard/ 訪問 Dashboard,正常應該看到 KubernetesGateway 這個 Provider 已經激活並准備好了服務。

測試

下面我們安裝 whoami 服務來進行測試,直接使用下面的資源清單創建對應的服務即可:

# 01-whoami.yaml
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: whoami
spec:
  replicas: 2
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
        - name: whoami
          image: traefik/whoami:v1.6.0
          ports:
            - containerPort: 80
              name: http

---
apiVersion: v1
kind: Service
metadata:
  name: whoami
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: http
  selector:
    app: whoami

當測試服務部署完成后,我們就可以使用 Service API 的方式來進行流量配置了。

部署一個簡單的 Host 主機

在以前的方式中我們會創建一個 Ingress 或 IngressRoute 資源對象,這里我們將部署第一個簡單的 HTTPRoute 對象。

# 02-whoami-httproute.yaml  
---
kind: HTTPRoute
apiVersion: networking.x-k8s.io/v1alpha1
metadata:
  name: http-app-1
  namespace: default
  labels:
    app: traefik
spec:
  hostnames:
    - "whoami"
  rules:
    - matches:
        - path:
            type: Exact
            value: /
      forwardTo:
        - serviceName: whoami
          port: 80
          weight: 1

這個 HTTPRoute 資源會捕捉到向 whoami 主機名發出的請求,並將其轉發到之前部署的 whoami 服務,如果你現在對這個主機名進行請求,你會看到典型的 whoami 輸出。

curl -H "Host: whoami" http://localhost
Hostname: whoami-9cdc57b6d-pfpxs
IP: 127.0.0.1
IP: ::1
IP: 10.42.0.13
IP: fe80::9c1a:a1ff:fead:2663
RemoteAddr: 10.42.0.11:33658
GET / HTTP/1.1
Host: whoami
User-Agent: curl/7.64.1
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.42.0.1
X-Forwarded-Host: whoami
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: traefik-74d7f586dd-xxr7r
X-Real-Ip: 10.42.0.1

注意app:traefik標簽選擇器,它確保請求被路由到你的 Traefik 實例,這是上面通過 Helm Chart 包安裝的默認標簽,當然也可以進行自定義。

帶路徑的 Host 主機

上面的例子可以很容易地限制流量只在一個給定的子路徑上進行路由。

# 03-whoami-httproute-paths.yaml
--- 
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata: 
  labels: 
    app: traefik
  name: http-app-1
  namespace: default
spec: 
  hostnames: 
    - whoami
  rules: 
    - 
      forwardTo: 
        - 
          port: 80
          serviceName: whoami
          weight: 1
      matches: 
        - 
          path: 
            type: Exact
            value: /foo

創建上面修改后的 HTTPRoute,你會發現之前的請求現在返回404錯誤,而請求 /foo 路徑后綴則返回成功。

curl -H "Host: whoami" http://localhost/foo
Hostname: whoami-9cdc57b6d-pfpxs
IP: 127.0.0.1
IP: ::1
IP: 10.42.0.13
IP: fe80::9c1a:a1ff:fead:2663
RemoteAddr: 10.42.0.11:34424
GET /foo HTTP/1.1
Host: whoami
User-Agent: curl/7.64.1
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.42.0.1
X-Forwarded-Host: whoami
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: traefik-74d7f586dd-xxr7r
X-Real-Ip: 10.42.0.1

關於請求的哪些部分可以被匹配的更多信息可以在官方 Service APIs 文檔(https://kubernetes-sigs.github.io/service-apis/httproute/)中找到。

使用靜態證書的 TLS

到目前為止,我們已經創建了一個簡單的 HTTPRoute,下一步,我們需要通過 TLS 來保證這個路由的安全,首先需要先用一個證書創建一個Kubernetes Secret,如下所示:

# 04-tls-dummy-cert.yaml
--- 
apiVersion: v1
data: 
  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVVVENDQXJtZ0F3SUJBZ0lRV2pNZ2Q4OUxOUXIwVC9WMDdGR1pEREFOQmdrcWhraUc5dzBCQVFzRkFEQ0IKaFRFZU1Cd0dBMVVFQ2hNVmJXdGpaWEowSUdSbGRtVnNiM0J0Wlc1MElFTkJNUzB3S3dZRFZRUUxEQ1JxWW1SQQpaSEpwZW5wMElDaEtaV0Z1TFVKaGNIUnBjM1JsSUVSdmRXMWxibXB2ZFNreE5EQXlCZ05WQkFNTUsyMXJZMlZ5CmRDQnFZbVJBWkhKcGVucDBJQ2hLWldGdUxVSmhjSFJwYzNSbElFUnZkVzFsYm1wdmRTa3dIaGNOTWpBeE1qQTAKTVRReE1qQXpXaGNOTWpNd016QTBNVFF4TWpBeldqQllNU2N3SlFZRFZRUUtFeDV0YTJObGNuUWdaR1YyWld4dgpjRzFsYm5RZ1kyVnlkR2xtYVdOaGRHVXhMVEFyQmdOVkJBc01KR3BpWkVCa2NtbDZlblFnS0VwbFlXNHRRbUZ3CmRHbHpkR1VnUkc5MWJXVnVhbTkxS1RDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUIKQU12bEc5d0ZKZklRSWRreDRXUy9sNGhQTVRQcmVUdmVQOS9MZlBYK2h2ekFtVC90V1BJbGxGY2JJNnZzemp0NQpEWlZUMFFuQzhHYzg0K1lPZXZHcFpNaTg0M20zdTdFSUlmY3dETUF4WWQ0ZjJJcENLVW9jSFNtVGpOaVhDSnhwCjVNd2tlVXdEc1dvVVZza1RxeVpOcWp0RWVIbGNuQTFHaGZSa3dEUkZxd1QxeVhaUTBoZHpkQzRCeFhhaVk0VEQKaFQ1dnFXQmlnUlh0M1VwSkhEL1NXUG4wTEVQOHM3ckhjUkZPY0RhV3ZWMW1jTkxNZUpveWNYUTJ0M2Z1Q0Fsegp3UWZOSjFQSk45QWlLalFJcXJ1MGFnMC9wU0kyQ3NkbEUzUTFpM29tZGpCQkZDcmxNMTZyY0wwNDdtWXZKOEVvCjFMdDVGQkxnVURBZktIOFRsaXU0ZG9jQ0F3RUFBYU5wTUdjd0RnWURWUjBQQVFIL0JBUURBZ1dnTUJNR0ExVWQKSlFRTU1Bb0dDQ3NHQVFVRkJ3TUJNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqQkJnd0ZvQVV5cWNiZGhDego3Nm4xZjFtR3BaemtNb2JOYnJ3d0VRWURWUjBSQkFvd0NJSUdkMmh2WVcxcE1BMEdDU3FHU0liM0RRRUJDd1VBCkE0SUJnUUFzWlBndW1EdkRmNm13bXR1TExkWlZkZjdYWk13TjVNSkk5SlpUQ1NaRFRQRjRsdG91S2RCV0gxYm0Kd003VUE0OXVWSHplNVNDMDNlQ294Zk9Ddlczby94SFZjcDZGei9qSldlYlY4SWhJRi9JbGNRRyszTVRRMVJaVApwNkZOa3kvOEk3anF1R2V2b0xsbW9KamVRV2dxWGtFL0d1MFloVCtudVBJY1pGa0hsKzFWOThEUG5WaTJ3U0hHCkIwVU9RaFdxVkhRU0RzcjJLVzlPbmhTRzdKdERBcFcwVEltYmNCaWlXOTlWNG9Ga3VNYmZQOE9FTUY2ZXUzbW0KbUVuYk1pWFFaRHJUMWllMDhwWndHZVNhcTh1Rk82djRwOVVoWHVuc3Vpc01YTHJqQzFwNmlwaDdpMTYwZzRWawpmUXlYT09KY0o2WTl2a2drYzRLYUxBZVNzVUQvRDR1bmd6emVWQ3k0ZXhhMmlBakpzVHVRS3JkOFNUTGNNbUJkCnhtcXVKZXFWSEpoZEVMNDBMVGtEY1FPM1NzOUJpbjRaOEFXeTJkdkR1a1gwa084dm9IUnN4bWVKcnVyZ09MVmIKamVvbTVQMTVsMkkwY3FKd2lNNHZ3SlBsb25wMTdjamJUb0IzQTU5RjZqekdONWtCbjZTaWVmR3VLM21hVWdKegoxWndjamFjPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t
  tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRREw1UnZjQlNYeUVDSFoKTWVGa3Y1ZUlUekV6NjNrNzNqL2Z5M3oxL29iOHdKay83Vmp5SlpSWEd5T3I3TTQ3ZVEyVlU5RUp3dkJuUE9QbQpEbnJ4cVdUSXZPTjV0N3V4Q0NIM01BekFNV0hlSDlpS1FpbEtIQjBwazR6WWx3aWNhZVRNSkhsTUE3RnFGRmJKCkU2c21UYW83UkhoNVhKd05Sb1gwWk1BMFJhc0U5Y2wyVU5JWGMzUXVBY1Yyb21PRXc0VStiNmxnWW9FVjdkMUsKU1J3LzBsajU5Q3hEL0xPNngzRVJUbkEybHIxZFpuRFN6SGlhTW5GME5yZDM3Z2dKYzhFSHpTZFR5VGZRSWlvMApDS3E3dEdvTlA2VWlOZ3JIWlJOME5ZdDZKbll3UVJRcTVUTmVxM0M5T081bUx5ZkJLTlM3ZVJRUzRGQXdIeWgvCkU1WXJ1SGFIQWdNQkFBRUNnZ0VCQUl5SWpvbzQxaTJncHVQZitIMkxmTE5MK2hyU0cwNkRZajByTVNjUVZ4UVEKMzgvckZOcFp3b1BEUmZQekZUWnl1a1VKYjFRdUU2cmtraVA0S1E4MTlTeFMzT3NCRTVIeWpBNm5CTExYbHFBVwpEUmRHZ05UK3lhN2xiemU5NmdaOUNtRVdackJZLzBpaFdpdmZyYUNKK1dJK1VGYzkyS1ZoeldSa3FRR2VYMERiCnVSRXRpclJzUXVRb1hxNkhQS1FIeUVITHo2aWVVMHJsV3IyN0VyQkJ4RlRKTm51MnJ1MHV1Ly8wdG1SYjgzZWwKSUpXQnY1V1diSnl4dXNnMkhkc0tzTUh0eEVaYWh1UlpTNHU2TURQR3dSdjRaU0xpQm1FVVc3RUMwUEg3dCtGaAoxUDcrL0Yyd1pGSDAvSzl6eXUyc0lOMDJIbTBmSWtGejBxb09BSzQ5OXhrQ2dZRUE2SC9nVUJoOG9GUSt2cmZKCnQvbXdMeFBHZHhWb3FWR1hFVjhlQzNWbmxUSXJlREpNWm81b1hKZHNuQ0d2S1NaWUhXZ3o3SVpwLzRCL29vSWsKTDl4TEJSVTJwS0d1OGxBT1ZhYnpaVDk0TTZYSE1PTGQ0ZlUrS3ZqK1lLVm5laEM3TVNQL3RSOWhFMjN1MnRKZwp1eUdPRklFVlptNHZxS1hEelU3TTNnU0R5WXNDZ1lFQTRJRVFyZDl2MXp0T2k5REZ6WEdnY05LVmpuYmFTWnNXCm9JNm1WWFJZS1VNM1FyWUw4RjJTVmFFM0Y0QUZjOXRWQjhzV0cxdDk4T09Db0xrWTY2NjZqUFkwMXBWTDdXeTMKZXpwVEFaei9tRnc2czdic3N3VEtrTW5MejVaNW5nS3dhd3pRTXVoRGxLTmJiUi90enRZSEc0NDRrQ2tQS3JEbQphOG40bUt6ZlRuVUNnWUFTTWhmVERPZU1BS3ZjYnpQSlF6QkhydXVFWEZlUmtNSWE2Ty9JQThzMGdQV245WC9ICk12UDE4eC9iNUVMNkhIY2U3ZzNLUUFiQnFVUFQ2dzE3OVdpbG9EQmptQWZDRFFQaUxpdTBTOUJUY25EeFlYL3QKOUN5R1huQkNEZy9ZSE1FWnFuQ1RzejM4c0VqV05VcSt1blNOSkVFUmdDUVl0Y2hxSS9XaWxvWGQyd0tCZ1FEQworTlBYYlBqZ1h5MHoxN2d4VjhFU3VwQVFEY0E5dEdiT1FaVExHaU9Ha2sxbnJscG9BWnVZcWs0Q0pyaVZpYUlyCkJvREllWWpDcjVNK3FnR3VqU3lPUnpSVU40eWRRWkdIZjN1Zkp3NEM3L1k3SlY0amlzR3hSTSt3Rk9yQ0EydmIKVEdGMEZLcThaN0o2N3dQRVliUUNobDB4TmJkcVIvK1ZGTzdGQ1QxV0VRS0JnQThUaE9hZmNEUmdpd0IxRFdyRgozZ1lmT3I0dERENExrNjRYZlF6ajdtRXQyYlJzOFNEYXYwVGZPclVUUlpFTTkyTVFZMnlrbzhyMDJDbmpndmxCCm1aYnZCTEFYaVZLa0laai9TTkNYUnhzOFZkZ3psTkpzYVNZTUtsNloxK1Z3MnZUdDNQSnI0TXlhRWpHYUxlSmMKRGRTQjdYOU9ESk5acW10bGpoRzc5eXpQCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=
kind: Secret
metadata: 
  name: mysecret
  namespace: default
type: kubernetes.io/tls

有了這個 Secret 資源后,就可以開始進行安全配置了。首先,必須重新配置 Gateway,以創建一個帶有 mysecret 證書的 TLS 監聽器,可以通過使用 Helm Chart 的升級選項來進行更新,以便在 Traefik 配置中添加證書部分。

helm upgrade traefik -f 05-values.yaml traefik/traefik

其中 05-values.yaml 的內容如下所示:

# 05-values.yaml
--- 
experimental: 
  kubernetesGateway: 
    appLabelSelector: traefik
    certificates:
      - 
        group: "core"
        kind: "Secret"
        name: "mysecret"
    enabled: true

Traefik 重啟后,我們可以發現 HTTPRoute 仍然有效,只是現在我們可以用 HTTPS 訪問它了。

curl --insecure -H "Host: whoami" https://localhost/foo
Hostname: whoami-9cdc57b6d-pfpxs
IP: 127.0.0.1
IP: ::1
IP: 10.42.0.13
IP: fe80::9c1a:a1ff:fead:2663
RemoteAddr: 10.42.0.11:53158
GET /foo HTTP/1.1
Host: whoami
User-Agent: curl/7.64.1
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.42.0.1
X-Forwarded-Host: whoami
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: traefik-74d7f586dd-xxr7r
X-Real-Ip: 10.42.0.1

金絲雀發布

Traefik 2.4 通過 Service APIs 規范可以支持的另一個功能是金絲雀發布。假設你想在一個端點上運行兩個不同的服務(或同一服務的兩個版本),並將一部分請求路由到每個端點,你可以通過修改你的 HTTPRoute 來實現。

首先,我們需要運行第二個服務,這里我們快速生成一個 Nginx 的實例來進行測試。

# 06-nginx.yaml
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: whoami
          image: nginx
          ports:
            - containerPort: 80
              name: http

---
apiVersion: v1
kind: Service
metadata:
  name: whoami
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: http
  selector:
    app: nginx

HTTPRoute 資源有一個 weight 選項,可以為兩個服務分別分配不同的值。

# 07-whoami-nginx-canary.yaml
--- 
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata: 
  labels: 
    app: traefik
  name: http-app-1
  namespace: default
spec: 
  hostnames: 
    - whoami
  rules: 
    - forwardTo: 
        - port: 80
          serviceName: whoami
          weight: 3
        - port: 80
          serviceName: nginx
          weight: 1

創建上面的 HTTPRoute 后,現在我們可以再次訪問 whoami 服務 http://localhost(沒有 foo/ 路徑后綴),正常我們可以看到有大約25%的時間會看到 Nginx 的響應,而不是 whoami 的響應。

目前,Traefik 對 Service APIs 的實現只集中在 HTTP 和 HTTPS 上。然而,該規范還具有 TCP 功能,未來可能也會支持 UDP,這些都是后續需要實現的功能。當然現在開始你就可以使用 Traefik 2.4 來使用 Kubernetes Service APIs。

到這里我們就完成了使用 Traefik 2.4 測試 Kubernetes Service APIs。目前,Traefik 對 Service APIs 的實現只集中在 HTTP 和 HTTPS 上,然而,該規范還具有 TCP 功能,未來可能也會支持 UDP,這些都是后續需要實現的功能。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM