概念

让我们回顾一下在 概览 举的例子:

假设你已经在你的基础设施上部署了一堆微服务。你可能使用了一个服务发现系统(例如 etcd 或 consul)或者一个资源管理框架(swarm,Mesos/Marathon)来管理所有这些服务。 如果你想让你的用户去从互联网访问你的某些微服务, 你就必需使用虚拟hosts或前缀路径来配置一个反向代理: - 域名 api.domain.com 将指向你的私有网络中的微服务 api - 路径 domain.com/web 将指向你的私有网络中的微服务 web - 域名 backoffice.domain.com 将指向你的私有网络中的微服务 backoffice ,在你的多台实例之间负载均衡 架构

我们将Træfɪk放大,一起看看它内部的结构:

结构

  • 请求在入口点处结束, 顾名思义, 它们是Træfɪk的网络入口(监听端口, SSL, 流量重定向…)。
  • 之后流量会导向一个匹配的前端。 前端是定义入口点后端之间的路由的地方。 路由是通过请求字段(Host, Path, Headers…) 来定义的,它可以匹配或否定一个请求。
  • 前端 将会把请求发送到 后端。后端可以由一台或一个通过负载均衡策略配置后的多台服务器组成。
  • 最后, 服务器 将转发请求到对应私有网络的微服务当中去。

入口点

入口点是是Træfɪk的网络入口。 它们可以通过以下方式来定义:

  • 一个端口 (80, 443…)
  • SSL (证书, 密钥, 由受信任的CA签名的客户端证书的身份验证…)
  • 重定向到其他的入口点 (重定向 HTTPHTTPS)
    这里有一个入口点定义的例子:
  1. [entryPoints]
  2. [entryPoints.http]
  3. address = ":80"
  4. [entryPoints.http.redirect]
  5. entryPoint = "https"
  6. [entryPoints.https]
  7. address = ":443"
  8. [entryPoints.https.tls]
  9. [[entryPoints.https.tls.certificates]]
  10. certFile = "tests/traefik.crt"
  11. keyFile = "tests/traefik.key"
  • 这里定义了两个入口点,httphttps.
  • http 监听 80 端口, https 监听 443端口
  • 我们通过提供一个证书和一个密钥在 https 中开启SSL。
  • 并且我们转发所有的 http 入口点请求到 https入口点。
    这里还有一个证书身份验证的例子:
  1. [entryPoints]
  2. [entryPoints.https]
  3. address = ":443"
  4. [entryPoints.https.tls]
  5. clientCAFiles = ["tests/clientca1.crt", "tests/clientca2.crt"]
  6. [[entryPoints.https.tls.certificates]]
  7. certFile = "tests/traefik.crt"
  8. keyFile = "tests/traefik.key"
  • 我们通过提供一个证书和一个密钥在 https 中开启SSL。
  • 添加了一个或多个包含证书身份验证的PEM格式文件
  • 多个CA签名仔同一个文件或多个独立文件都是允许的。

前端

前端是入口流量从入口点转发到后端的一组规则。 前端可以通过以下规则定义:

  • Headers: Content-Type, application/json: 通过 Headers 可以添加一个匹配规则来匹配请求头部包含的值。它接受要匹配的键/值对序列。
  • HeadersRegexp: Content-Type, application/(text|json): 也可以在 Headers 中使用正则表达式。它接受要匹配的键/值对序列,序列内容解析是通过正则匹配的。
  • Host: traefik.io, www.traefik.io: 匹配请求 Host 必需在给定域名列表内。
  • HostRegexp: traefik.io, {subdomain:[a-z]+}.traefik.io: 添加匹配请求 Host 的正则表达式。 它接受一个以{}包括起来的为空或更多url变量的模版。变量的值可以以一个可选的正则表达式来匹配。
  • Method: GET, POST, PUT: Method 可以添加一个HTTP请求方法的匹配。它接受要匹配的一个或多个请求方法序列。
  • Path: /products/, /articles/{category}/{id:[0-9]+}: Path 可以添加一个URL路径的匹配。它接受一个以{}包括起来的为空或更多url变量的模版。
  • PathStrip: 和 Path 相同,但从请求的URL路径中去掉的给定的前缀。
  • PathPrefix: PathPrefix 可以添加一个URL路径前缀的匹配。它匹配给定模版中的完整URL路径前缀。
  • PathPrefixStrip: 和 PathPrefix 相同,但从请求的URL路径中去掉的给定的前缀。
  • AddPrefix : 为请求URL路径天假前缀。
    你可以为一条规则添加多个值,通过用 , 分隔开。 你可以使用多条规则,通过用 ; 分隔开。

你可以选择启用 passHostHeader 来转发客户端请求Header中的 Host 字段到后端

这里有一个前端定义的例子:

  1. [frontends]
  2. [frontends.frontend1]
  3. backend = "backend2"
  4. [frontends.frontend1.routes.test_1]
  5. rule = "Host:test.localhost,test2.localhost"
  6. [frontends.frontend2]
  7. backend = "backend1"
  8. passHostHeader = true
  9. priority = 10
  10. entrypoints = ["https"] # overrides defaultEntryPoints
  11. [frontends.frontend2.routes.test_1]
  12. rule = "HostRegexp:localhost,{subdomain:[a-z]+}.localhost"
  13. [frontends.frontend3]
  14. backend = "backend2"
  15. [frontends.frontend3.routes.test_1]
  16. rule = "Host:test3.localhost;Path:/test"
  • 这里定义了3个前端: frontend1, frontend2frontend3
  • 当规则Host:test.localhost,test2.localhost匹配时frontend1 将把流量转发到 backend2
  • 当规则Host:localhost,{subdomain:[a-z]+}.localhost匹配时frontend2 将把流量转发到 backend1 (转发客户端Header中的 Host 字段到后端)
  • 当规则Host:test3.localhost Path:/test同时匹配时frontend3 将把流量转发到 backend2

合并多条规则

正如上面例子中所展示的,你可以合并多条规则。 在TOML文件中,你可以使用多条路由:

  1. [frontends.frontend3]
  2. backend = "backend2"
  3. [frontends.frontend3.routes.test_1]
  4. rule = "Host:test3.localhost"
  5. [frontends.frontend3.routes.test_2]
  6. rule = "Path:/test"

这里,当规则Host:test3.localhost Path:/test同时匹配时 frontend3 将把流量转发到 backend2。 或者你也可以使用 ; 符号来分隔,结果是相同的:

  1. [frontends.frontend3]
  2. backend = "backend2"
  3. [frontends.frontend3.routes.test_1]
  4. rule = "Host:test3.localhost;Path:/test"

最后,你可以使用 , 符号分隔规则,为一个前端创建一个规则来绑定多个域名或路径:

  1. [frontends.frontend2]
  2. [frontends.frontend2.routes.test_1]
  3. rule = "Host:test1.localhost,test2.localhost"
  4. [frontends.frontend3]
  5. backend = "backend2"
  6. [frontends.frontend3.routes.test_1]
  7. rule = "Path:/test1,/test2"

优先级

默认情况下,路由会以规则长度(为了防止部分重叠情况)被排序(倒序): PathPrefix:/12345 将会比 PathPrefix:/1234 优先被匹配到,最后才会匹配到 PathPrefix:/1

你可以在前端自定义优先级:

  1. [frontends]
  2. [frontends.frontend1]
  3. backend = "backend1"
  4. priority = 10
  5. passHostHeader = true
  6. [frontends.frontend1.routes.test_1]
  7. rule = "PathPrefix:/to"
  8. [frontends.frontend2]
  9. priority = 5
  10. backend = "backend2"
  11. passHostHeader = true
  12. [frontends.frontend2.routes.test_1]
  13. rule = "PathPrefix:/toto"

这里,frontend1 将会比 frontend2 优先被匹配(因为10 > 5).

后端

后端用来负责将来自一个或多个前端的流量负载均衡到一组http服务器上。 这里支持多种负载均衡方法:

  • wrr: 加权轮询
  • drr: 动态轮询: 这会为表现比其他服务器好的服务器增加权重。当服务器表现有变化的时,它也会会退到正常权重。
    断路器也可以应用到后端,用于防止故障服务器上的高负载。 初始化状态是Standby。断路器只观察统计信息但并不修改请求。 当断路条件匹配时,断路器进入Tripped状态,它会返回与定义的http状态码或转发到其他前端。 一旦Tripped状态计时器超时,断路器会进入Recovering状态并重置所有统计数据。 当短路条件不匹配并且Recovery状态计时器超时时,断路器进入Standby状态。

它可以通过配置:

  • 方法: LatencyAtQuantileMS, NetworkErrorRatio, ResponseCodeRatio
  • 操作符: AND, OR, EQ, NEQ, LT, LE, GT, GE
    举个例子:

  • NetworkErrorRatio() > 0.5: 监控网络故障率大于0.5超过10秒后,为这个前端平滑切换,断路条件匹配

  • LatencyAtQuantileMS(50.0) > 50: 监控延迟超过50ms时断路条件匹配
  • ResponseCodeRatio(500, 600, 0, 600) > 0.5: 监控返回 HTTP状态码在[500-600]之间的数量/HTTP状态码在[0-600]之间的数量 的比例大于0.5时,断路条件匹配
    为了主动防治后端被高负载压垮,可以为每个后端设置最大连接数限制。

最大连接数限制可以通过为maxconn.amount配置一个整型值,同时 maxconn.extractorfunc 是用来配置通过什么样的维度来统计最大连接数。"例如下面例子中通过请求中host来统计连接数"

例如:

  1. [backends]
  2. [backends.backend1]
  3. [backends.backend1.maxconn]
  4. amount = 10
  5. extractorfunc = "request.host"
  • 当已经有10个请求是同一个Host Header时,下一个请求backend1 将返回 HTTP code 429 Too Many Requests
  • 另外一个可可行的 extractorfunc 维度配置是 client.ip,它将通过统计客户端请求IP来统计连接数。
  • 其实 extractorfunc 可以设置 request.header.ANY_HEADER 中的任意维度,它将以你提供的 ANY_HEADER 任意维度来统计连接数。
    所有的负载平衡器都支持粘滞会话(sticky sessions)。当粘滞会话被开启时,会有一个名称叫做_TRAEFIK_BACKEND的cookie在请求被初始化时被设置在请求初始化时。在随后的请求中,客户端会被直接转发到这个cookie中存储的后端(当然它要是健康可用的),如果这个后端不可用,将会指定一个新的后端。

例如:

  1. [backends]
  2. [backends.backend1]
  3. [backends.backend1.loadbalancer]
  4. sticky = true

服务器健康检查也是可配置的,当Traefik定期执行HTTP GET请求到后端时,后端返回的HTTP状态码不是200 OK,那么这个后端将被从负载均衡轮询列表中移除。健康检查可以以一个在后端URL后附加路径的路径地址与一个时间间隔 (以 time.ParseDuration 所识别的格式给出) specifying how 配置多久健康检查应该执行一次 (默认30秒). 每个后端必需在5秒内回应健康检查。

当一个后端重新返回HTTP状态码200 OK时,将被重新添加回负载均衡轮询列表。

例如:

  1. [backends]
  2. [backends.backend1]
  3. [backends.backend1.healthcheck]
  4. path = "/health"
  5. interval = "10s"

服务器

服务器可以简单的被定义为URL。你也可以设置一个自定义的 weight 给每个服务器(这个weight将会被用于负载均衡)。

这里有一个关于后端和服务器的定义的例子:

  1. [backends]
  2. [backends.backend1]
  3. [backends.backend1.circuitbreaker]
  4. expression = "NetworkErrorRatio() > 0.5"
  5. [backends.backend1.servers.server1]
  6. url = "http://172.17.0.2:80"
  7. weight = 10
  8. [backends.backend1.servers.server2]
  9. url = "http://172.17.0.3:80"
  10. weight = 1
  11. [backends.backend2]
  12. [backends.backend2.LoadBalancer]
  13. method = "drr"
  14. [backends.backend2.servers.server1]
  15. url = "http://172.17.0.4:80"
  16. weight = 1
  17. [backends.backend2.servers.server2]
  18. url = "http://172.17.0.5:80"
  19. weight = 2
  • 定义了两个后端: backend1 and backend2
  • backend1 将把流量转发到两台服务器: http://172.17.0.2:80" 权重 10http://172.17.0.3:80 权重 1 并使用默认的 wrr 负载均衡策略。
  • backend2 将把流量转发到两台服务器: http://172.17.0.4:80" 权重 1http://172.17.0.5:80 权重 2 并使用 drr 负载均衡策略。
  • 一个断路器被添加到 backend1 使用 NetworkErrorRatio() > 0.5 表达式:监控网络故障率大于0.5超过10秒为这个前端平滑切换,断路条件匹配

配置文件

Træfɪk的配置文件分为两部分:

静态 Træfɪk 配置

静态配置文件是一种全局配置文件,用来配置后端和入口点的连接。

可以通过许多方式配置Træfɪk,以下是各种配置方式的生效优先级。 上面的项目优先级大于下面的项目:

配置文件

在默认情况下, Træfɪk 会在以下几个地方寻找 traefik.toml 文件:

  • /etc/traefik/
  • $HOME/.traefik/
  • . 工作目录
    你可以通过设置configFile参数来覆盖这种默认情况:
  1. $ traefik --configFile=foo/bar/myconfigfile.toml

请转到 全局配置 部分获取详细文档。

参数

每个参数(命令)在帮助部分都有定义:

  1. $ traefik --help

需要注意的是,所有默认值也会一同被展示出来。

Key-value 存储

Træfɪk 支持多种 Key-value 存储方式:

动态 Træfɪk 配置

动态配置请关注:

我们只需要开启watch 选项来让 Træfɪk 监听配置文件变化并自动生成配置。 指向服务的路由在监测到任何变化时直接被创建或更新。

请转到后端配置 部分获取详细文档。

命令

使用方法: traefik [command] [—flag=flag_argument]

列出了所有Træfɪk可用的命令与命令描述:

  • version : 打印版本号
  • storeconfig : 将静态traefik配置存入Key-value存储。请转到存储 Træfɪk 配置 部分获取详细文档。
    每个命令都可能包含相关的标志。 所有相关的标志都会显示在:
  1. $ traefik [command] --help

需要注意的是,每个命令描述是在帮助的开始部分:

  1. $ traefik --help