我们再次从概述中举一个例子:
假设你已经在你的基础服务中部署了一系列的微服务。你可能用了一个服务注册器(如:etcd或consul)或者一个编排器(swarm,Mesos/Marathon)来管理这些服务。如果你希望你的用户从internet访问你的微服务,你就必须使用一个反向代理并用虚拟hosts或前缀路径来配置它:
域名 api.domain.com 将会指向你私人网路中的微服务api路径 domain.com/web 将会指向你私人网路中的微服务域名 backoffice.domain.com 将会指向你私人网路中的微服务后台,在你的多个微服务之间进行负载均衡让我们放大Traefik,并对其内部架构进行概述:
进来的请求在entrypoints结束,顾名思义,他们是进入Traefik的网路入口(监听的端口,SSL,流量重定向)然后流量被转发到所匹配的前端。前端定义从入口点到后端的路由。路由是根据请求字段创建的(Host,Path,Headers…)并可以匹配或不匹配请求。然后前端将发生请求到后端。后端可以由一个或多个服务及一条负载均衡策略组成。最后,服务将会被转发到私人网络中相应的微服务。入口点是进入Traefik的网络入口,它们可以通过下面的形式定义:
一个端口(80,443…)SSL(证书,密钥,通过受信CA签名的客户端证书来进行身份验证…)重定向到其他的入口点(重定向HTTP到HTTPS)这是一个入口点定义的例子:
[entryPoints] [entryPoints.http] address = ":80" [entryPoints.http.redirect] entryPoint = "https" [entryPoints.https] address = ":443" [entryPoints.https.tls] [[entryPoints.https.tls.certificates]] certFile = "tests/traefik.crt" keyFile = "tests/traefik.key" 两个入口点是定义http和httpsHTTP监听端口80,HTTPS监听端口443通过给出一个证书或密钥来启用SSL到https我们也可以重定向所有的流量从入口点http到https这是另一个使用客户端证书进行身份验证的例子:
[entryPoints] [entryPoints.https] address = ":443" [entryPoints.https.tls] [entryPoints.https.tls.ClientCA] files = ["tests/clientca1.crt", "tests/clientca2.crt"] optional = false [[entryPoints.https.tls.certificates]] certFile = "tests/traefik.crt" keyFile = "tests/traefik.key" 通过给出证书来启用https的SSL添加一个或多个包含PEM格式证书颁发机构的文件可以将多个CA:s包存在同一个文件中,也可以将他们保存在单独的文件。前端由一组策略组成,这些策略定义了进来的请求要怎样从入口点被转发到后端。
策略可以分为两组:修改组和匹配组
修改组的策略只修改请求。他们对正在运行的策略没有任何影响。
下面是一列现有的修改组策略:
AddPrefix: /products:将请求转发到后端之前,将前缀路径添加到现有的请求路径中ReplacePath: /serverless-path:替换路径并将旧的路径添加到X-Replaced-Path的请求头。对于映射AWS Lambda或Google Cloud Functions非常有帮助。ReplacePathRegex: ^/api/v2/(.*) /api/$1:用正则表达式来替换路径并添加旧的路径到X-Replaced-Path请求头。用一个空格来分离正则表达式和 替换空间。匹配路径确定某个特定的请求是否该向后端转发。
下面是一些关联性策略:
,是OR执行者(仅在匹配组里有效,如:Host:foo.com,bar.com) 即,任何一条策略匹配就转发请求对Headers和HeadersRegexp无效 ;是AND执行者(只在匹配组之间生效,如:Host:foo.com;Path:/bar) 即,所有策略都匹配上才转发请求下面是一列现有的匹配组策略以及示例:
匹配组描述Headers: Content-Type, application/json匹配HTTP头。它接受逗号分隔的键值对,且键值都必须是文本HeadersRegexp: Content-Type, application/(text/json)匹配HTTP头。它接受逗号分隔的键值对,且键必须是文本,值可以是文本或正则表达式Host: traefik.io, www.traefik.io匹配请求host。它接受一个由文本和正则表达式组成的序列Method: GET, POST, PUT匹配HTTP请求方式.接受一个http方法的序列Path: /products/, /articles/{category}/{id:[0-9]+}匹配准确的请求路径。接受一个由正则表达式和文本组成的序列PathStrip: /products/在转发请求到后台之前,精准匹配路径并去掉路径。它接受一系列文本路径。PathStripRegex: /articles/{category}/{id:[0-9]+}在转发请求到后台之前,精准匹配路径并去掉路径。它接受一系列文本和正则表达式路径。PathPrefix: /products/, /articles/{category}/{id:[0-9]+}匹配请求路径的前缀。它接受一个由文本和正则表达前缀路径组成的序列PathPrefixStrip: /products/在转发请求到后端之前,匹配路径前缀并去掉前缀路径。它接受一个文本前缀路径序列。从Traefik1.3开始,剥离的前缀路径可以在X-Forwarded-Prefix头中使用PathPrefixStripRegex: /articles/{category}/{id:[0-9]+}在转发请求到后端之前,匹配路径前缀并去掉前缀路径。它接受一个文本和正则前缀组成的路径序列。从Traefik1.3开始,剥离的前缀路径可以在X-Forwarded-Prefix头中使用Query: foo=bar, bar=baz匹配Query字符参数。它接受一个键=值对序列为了将正则表达式和Host及路径匹配器一起使用,你必须声明一个随意命名的变量,后跟冒号分离的正则表达式,所有变量都要用大括号括起来。可以使用go的正则包支持的任何模板(如:/posts/{id:[0-9]+})
Note 变量没有特殊意义.但是,它是嵌入正则表达式和定义语法的gorilla/mux依赖性所必需的。
你可以选择启用passHostHeader来转发客户端Host头到后端。你也可以选择在特定的header中配置passTLSClientCert选项来将客户端证书传递给后端。
本节介绍何时使用各种各样的路径匹配器
如果你的后端只在特定的路径监听,请使用Path。例如,Path:/products 将会匹配 /products 但不匹配 /products/shoes
如果你的后端监听在一个特定的基础路径同时也处理子路径的请求。比如:PathPrefix: /products 即匹配/products也匹配 /products/shoes 和 /products/shirts。因为路径是按原样转发的,所以你的后端预计会监听 /products。
如果你的后端监听在根路径(/),但可以在特定前缀上路由,请使用一个*Strip匹配器。比如:PathPrefixStrip: /products 将匹配/products,也匹配/products/shoes 和 /products/shirts.
因为路径在转发前被剥离了,所以你的后端应监听在’/’。如果你的后端正在为某些资产服务(如,图片或javascript文件),那么很可能它必须返回被恰当构建的相对URLS。
继续这个例子,后端应该返回/products/shoes/image.png (而不是/images.png,Traefik可能无法和同一后端关联 )
X-Forwarded-Prefix 头(Traefik1.3后可以使用)可以被要求动态的构建这样的URLs
除了通过路径来区分你的后端,也可以在组合中增加一个Host匹配器。这样,你后端的命名空间出路径还可以基于基础hosts发生。
这是一个前端定义的例子:
[frontends] [frontends.frontend1] backend = "backend2" [frontends.frontend1.routes.test_1] rule = "Host:test.localhost,test2.localhost" [frontends.frontend2] backend = "backend1" passHostHeader = true [frontends.frontend2.passTLSClientCert] pem = true priority = 10 entrypoints = ["https"] # overrides defaultEntryPoints [frontends.frontend2.routes.test_1] rule = "HostRegexp:localhost,{subdomain:[a-z]+}.localhost" [frontends.frontend3] backend = "backend2" [frontends.frontend3.routes.test_1] rule = "Host:test3.localhost;Path:/test" 定义了3个前端:frontend1, frontend2and frontend3如果策略Host:test.localhost,test2.localhost匹配上了,frontend1将会把流量转发到backend2如果策略HostRegexp:localhost,{subdomain:[a-z]+}.localhost匹配上,frontend2将把流量转发到 backend1(转发客户端Host头到后端)如果策略Host:test3.localhost和 Path:/test 匹配上了,frontend3将会把流量转发到 backend2