天天看点

服务环境搭建-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