服務環境搭建-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( , ) | Check if there is a key defined in the headers, with the value |
HeadersRegexp( , ) | Check if there is a key defined in the headers, with a value that matches the regular expression |
Host( , …) | Check if the request domain (host header value) targets one of the given |
HostHeader( , …) | Check if the request domain (host header value) targets one of the given |
HostRegexp( , , …) | Check if the request domain matches the given |
Method( , …) | Check if the request method is one of the given ( , , , , , ) |
Path( , , …) | Match exact request path. It accepts a sequence of literal and regular expression paths |
PathPrefix( , ) | Match request prefix path. It accepts a sequence of literal and regular expression prefix paths |
Query( , ) | 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
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL90TQNhXV650MjRUTwgDbiBHaYFGbkNDTwYVbiVHNHpleO1GTulzRilWO5xkNNh0YwIFSh9Fd4VGdsATMfd3bkFGazxyaHRGcWdUYuVzVa9GczoVdG1mWfVGc5RHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5yNwUjMxkDMyIzMwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
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
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 |
---|---|---|
| | |
| | |
| | |
| | |
| | |
| | |
-
forceSlash=false
Path | Prefix to strip | Result |
---|---|---|
| | empty |
| | empty |
| | |
| | empty |
| | |
| | |
3.4 Chain
Chain中間件使您能夠定義其他中間件的可重用組合, 這使得重用相同的組更加容易。
3.4.1 使用執行個體
以下是包含,
WhiteList
和
BasicAuth
的Chain的示例。
RedirectScheme
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