天天看點

服務環境搭建-Traefik網關服務服務環境搭建-Traefik網關服務

服務環境搭建-Traefik網關服務

1. 說明

Traefik網關服務

用于提供一個實作反向代理、中間件鑒權、服務負載均衡、與服務發現的環境。

2. 反向代理

2.1 基本概念

EntryPoints:入口點是進入Traefik的網絡入口點。它們定義了接收資料包的端口,以及是偵聽

TCP

還是

UDP

。入口點是靜态配置的一部分,它們可以通過使用檔案(TOML或YAML)或CLI參數來定義。

Routers:路由器負責将傳入的請求連接配接到能夠處理它們的服務。在這個過程中,路由器可能會使用一些中間件來更新請求,或者在将請求轉發給服務之前采取行動。

Rule:

Rule

是一組配置有值的比對器,這些值确定特定請求是否比對特定條件。 如果該規則得到驗證,則路由器将變為活動狀态,調用中間件,然後将請求轉發到服務。

轉發到

Host

example.com

的服務
rule = "Host(`example.com`)"
           
轉發到

Host

example.com

或者

Host

example.org

并且

Path

/traefik

的服務
rule = "Host(`example.com`) || (Host(`example.org`) && Path(`/traefik`))"
           

Rule所有可用的配置器

可以使用

AND(&&)

OR(||)

運算符組合多個比對器。 也可以使用括号。
Rule Description
Headers(

key

,

value

)
Check if there is a key

key

defined in the headers, with the value

value

HeadersRegexp(

key

,

regexp

)
Check if there is a key

key

defined in the headers, with a value that matches the regular expression

regexp

Host(

example.com

, …)
Check if the request domain (host header value) targets one of the given

domains

HostHeader(

example.com

, …)
Check if the request domain (host header value) targets one of the given

domains

HostRegexp(

example.com

,

{subdomain:[a-z]+}.example.com

, …)
Check if the request domain matches the given

regexp

Method(

GET

, …)
Check if the request method is one of the given

methods

(

GET

,

POST

,

PUT

,

DELETE

,

PATCH

,

HEAD

)
Path(

/path

,

/articles/{cat:[a-z]+}/{id:[0-9]+}

, …)
Match exact request path. It accepts a sequence of literal and regular expression paths
PathPrefix(

/products/

,

/articles/{cat:[a-z]+}/{id:[0-9]+}

)
Match request prefix path. It accepts a sequence of literal and regular expression prefix paths
Query(

foo=bar

,

bar=baz

)
Match Query String parameters. It accepts a sequence of key=value pairs

2.2 Traefik監聽Docker服務

簡單例子

配置

docker

、部署/公開服務

啟用docker提供程式

将标簽附加到容器(在docker-compose檔案中)

version: "3"
services:
  my-container:
    # ...
    labels:
      - traefik.http.routers.my-container.rule=Host(`example.com`)
           
為容器指定自定義端口:将對

http://example.com

的請求轉發到

http:// <容器的私有IP>:12345

version: "3"
services:
  my-container:
    # ...
    labels:
      - traefik.http.routers.my-container.rule=Host(`example.com`)
      # Tell Traefik to use the port 12345 to connect to `my-container`
      - traefik.http.services.my-service.loadbalancer.server.port=12345
           
為每個容器指定多個路由器和服務

将請求轉發到容器上的多個端口需要使用路由器上的

service

參數引用服務負載均衡器端口定義。

在此示例中,除了将

http://example-a.com

請求轉發到

http://<private IP of container>:8000

外,還将

http://example-b.com

的請求轉發到

http://<private IP of container>:9000

version: "3"
services:
  my-container:
    # ...
    labels:
      - traefik.http.routers.www-router.rule=Host(`example-a.com`)
      - traefik.http.routers.www-router.service=www-service
      - traefik.http.services.www-service.loadbalancer.server.port=8000
      - traefik.http.routers.admin-router.rule=Host(`example-b.com`)
      - traefik.http.routers.admin-router.service=admin-service
      - traefik.http.services.admin-service.loadbalancer.server.port=9000
           

3. 中間件

連接配接到路由器上的中間件是在請求被發送到服務(或在服務的回答被發送到客戶機之前)之前調整請求的一種方法。通常用來做一些權限校驗與調整請求。

在Traefik中有幾個可用的中間件,一些可以修改請求、頭,一些負責重定向,一些添加身份驗證,等等。

3.1 ForwardAuth

服務環境搭建-Traefik網關服務服務環境搭建-Traefik網關服務

Traefik提供的

ForwardAuth

中間件可以使用外部服務轉發身份驗證。

FrwardAuth

中間件将身份驗證委派給外部服務。 如果服務以

2XX

響應碼回答,則将授予通路權限,并執行原始請求。 否則,将傳回來自身份驗證伺服器的響應。我們用此中間件來完成服務的鑒權:

3.1.1 使用執行個體

将身份驗證轉發到

http://example.com/auth

labels:
  - "traefik.http.middlewares.test-auth.forwardauth.address=http://example.com/auth"
           

3.1.2 轉發請求頭

以下請求屬性以

X-Forwarded- headers

的形式提供給

forward-auth

目标端點。

Property Forward-Request Header
HTTP Method X-Forwarded-Method
Protocol X-Forwarded-Proto
Host X-Forwarded-Host
Request URI X-Forwarded-Uri
Source IP-Address X-Forwarded-For

3.1.3 配置項

address

address

定義認證伺服器的位址

labels:
  - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth"
           

trustForwardHeader

trustForwardHeader

選項設定為

true

以信任所有

X-Forwarded-*

頭。

labels:
  - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true"
           

authResponseHeaders

authResponseHeaders

選項是要從身份驗證伺服器響應中複制并根據轉發的請求進行設定的标頭清單,以替換所有現有的沖突标頭。

labels:
  - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret"
           

authResponseHeadersRegex

authResponseHeadersRegex

選項是正規表達式,用于比對要從身份驗證伺服器響應中複制的标頭,并在轉發與正規表達式比對的所有标頭後,根據轉發的請求進行設定。 它允許将正規表達式與标題鍵進行部分比對。 字元串(

^

)的開頭和字元串(

$

)的結尾應用于確定與标題鍵完全比對。

labels:
  - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex=^X-"
           

authRequestHeaders

authRequestHeaders

選項是要從請求複制到身份驗證伺服器的标頭清單。 它允許過濾不應傳遞到身份驗證伺服器的标頭。 如果未設定或為空,則傳遞所有請求标頭。

labels:
  - "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders=Accept,X-CustomHeader"
           

3.2 Add Prefix

服務環境搭建-Traefik網關服務服務環境搭建-Traefik網關服務

AddPrefix中間件在轉發請求之前添加字首更新請求的路徑。

3.2.1 使用執行個體

給原請求的path添加字首
# Prefixing with /foo
labels:
  - "traefik.http.middlewares.add-foo.addprefix.prefix=/foo"
           

3.2.2 配置項

prefix

prefix

是要在請求的URL中的目前路徑之前添加的字元串,它應該包含一個斜杠(/)。

3.3 StripPrefix

從URL路徑中删除指定的字首。

3.3.1 使用執行個體

删除原請求path的字首
# Strip prefix /foobar and /fiibar
labels:
  - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar,/fiibar"
           

3.3.2 配置項

General

StripPrefix

中間件将比對的路徑字首去除,并将其存儲在

X - Forwarded - Prefix

頭檔案中。

prefixes

prefixes

選項定義從請求URL中去除的字首。

forceSlash

Optional, Default=true

forceSlash

選項可通過在必要時将其替換為

/

來確定所得的剝離路徑不是空字元串。

添加這個選項是為了保持這個中間件的初始(非直覺)行為,以避免引入破壞性更改。

建議顯式設定forceSlash為false。

forceSlash的行為示例

  • forceSlash=true

Path Prefix to strip Result

/

/

/

/foo

/foo

/

/foo/

/foo

/

/foo/

/foo/

/

/bar

/foo

/bar

/foo/bar

/foo

/bar

  • forceSlash=false

Path Prefix to strip Result

/

/

empty

/foo

/foo

empty

/foo/

/foo

/

/foo/

/foo/

empty

/bar

/foo

/bar

/foo/bar

/foo

/bar

3.4 Chain

服務環境搭建-Traefik網關服務服務環境搭建-Traefik網關服務

Chain中間件使您能夠定義其他中間件的可重用組合, 這使得重用相同的組更加容易。

3.4.1 使用執行個體

以下是包含

WhiteList

BasicAuth

RedirectScheme

的Chain的示例。
labels:
  - "traefik.http.routers.router1.service=service1"
  - "traefik.http.routers.router1.middlewares=secured"
  - "traefik.http.routers.router1.rule=Host(`mydomain`)"
  - "traefik.http.middlewares.secured.chain.middlewares=https-only,known-ips,auth-users"
  - "traefik.http.middlewares.auth-users.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"
  - "traefik.http.middlewares.https-only.redirectscheme.scheme=https"
  - "traefik.http.middlewares.known-ips.ipwhitelist.sourceRange=192.168.1.7,127.0.0.1/32"
  - "http.services.service1.loadbalancer.server.port=80"
           

4. 負載均衡

負載平衡器能夠在程式的多個執行個體之間負載平衡請求,每個服務都有一個負載均衡器,即使隻有一台伺服器可以轉發流量。

目前隻支援輪詢負載均衡

使用兩個伺服器聲明服務(使用負載平衡)

http:
  services:
    my-service:
      loadBalancer:
      # 在以下服務中實作負載均衡
        servers:
        - url: "http://private-ip-server-1/"
        - url: "http://private-ip-server-2/"
           

5. 服務發現

Traefik可以自動發現服務。其服務發現是通過 providers來實作的, providers是基礎設定元件,其思想是Traefik查詢提供程式的API,以查找有關路由的相關資訊,并且當Traefik檢測到更改時,它會動态更新路由。

使用Docker作為Traefik的提供商

指定docker作為Traefik的providers

Traefik需要通路docker套接字來擷取它的動态配置。你可以用

endpoint

來指定要使用哪個Docker API端點。

使Traefik監聽Docker事件

volumes:
   - /var/run/docker.sock:/var/run/docker.sock:ro
           

使用docker部署服務時,通過

labels

标簽附加資訊,告訴Traefik服務可以處理的請求的特征,這意味着當部署服務時,Traefik會立即檢測到該服務并實時更新路由規則。反之亦然:當您從基礎設施中删除服務時,路由将随之消失。

如下例子:

whoami:
    image: traefik/whoami
    container_name: whoami
    networks:
      - proxy
    labels:
    # 通知Traefik路由的名稱為routers,規則為:通路Host為example.com、path為/whoami的請求轉發到whoami的服務
     - "traefik.http.routers.whoami.rule=Host(`example.com`) && Path(`/whoami`)"
           

6. 綜合執行個體

6.1 實作目标

使用Traefik監聽Docker服務,自動發現服務與自動負載均衡。啟動兩個whoami的docker服務,

http://example.com/web

的請求轉發到whoami_web服務;

http://example.com/svv_runtime

http://example.com/svv/...

的請求轉發到whoami_svv服務的根路徑下。同時請求這兩個服務之前進行鑒權,當鑒權成功時才可以順利通路服務。

6.2 實作方式

# docker-compose.yml
version: '3'

services:
  # traefik服務
  traefik:
    image: traefik:v2.4
    container_name: traefik
    restart: always
    # 禁止容器程序擷取新的權限
    security_opt:
      - no-new-privileges:true
    # traefik服務監聽80與8080兩個端口
    ports:
      - 80:80
      - 8080:8080
    command:
      - "--api=true"
      # 啟用Web UI并監聽docker
      - "--api.insecure=true"
      # 開啟控制台(預設開啟)
      - "--api.dashboard=true"
      # 入口點定義
      - "--entrypoints.web.address=:80"
      # 指定traefik的提供商為docker
      - "--providers.docker=true"
      # 通路docker套接字擷取動态配置
      - "--providers.docker.endpoint=unix:///var/run/docker.sock"
      # 指定docker網絡為proxy
      - "--providers.docker.network=proxy"
    
    # 使Traefik監聽Docker事件
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    # 建立docker自定義網絡為proxy
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"
      # 通路traefik的背景的Host為example.com
      - "traefik.http.routers.traefik.rule=Host(`example.com`)"
  # whoami服務
  whoami_web:
    image: traefik/whoami
    container_name: whoami_web
    networks:
      - proxy
    labels:
      # 建立名為whoami_web的路由,将path為/web請求轉發到該服務
      - "traefik.http.routers.whoami_web.rule=Path(`/web`)"
      # 将名為whoami_web的路由與test-auth的鑒權中間件進行連接配接
      - "[email protected]"
      # 将請求轉發到address為http://ip:port/auth的鑒權服務,若服務響應2xx的狀态碼,則授權通路,并執行原始請求。否則,将傳回鑒權伺服器的響應
      - "traefik.http.middlewares.test-auth.forwardauth.address=http://ip:port/auth"
  whoami_svv:
    image: traefik/whoami
    container_name: whoami_svv
    networks:
      - proxy
    labels:
     # 建立名為whoami_svv的路由,将path字首為/svv_runtime請求轉發到該服務
     - "traefik.http.routers.whoami_svv.rule=PathPrefix(`/svv_runtime`)"
     # 建立名為middlewareschain的中間件鍊路
     - "traefik.http.routers.whoami_svv.middlewares=middlewareschain"
     # middlewareschain中間件鍊路包含鑒權中間件test-auth與删除字首中間件test-stripprefix
     - "traefi[email protected]docker,[email protected]"
     # 将請求轉發到address為http://ip:port/auth的鑒權服務,若服務響應2xx的狀态碼,則授權通路,并執行原始請求。否則,将傳回鑒權伺服器的響應
     - "traefik.http.middlewares.test-auth.forwardauth.address=http://ip:port/auth"
     # 将原請求Path删除字首svv_runtime
     - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/svv_runtime"

networks:
  proxy:
    external: true