使用traefik创建反向代理过程见:https://blog.woyou.cool/post/1908
本文来自官网文档的部分翻译并加以解释:https://doc.traefik.io/traefik/
由于本人不善描述,故请结合下述举例进行了解
简述
traefik是一个边际路由,它在服务中扮演着网关的角色。它拦截所有请求并进行一系列处理后再传递到具体的处理服务器。
其特点是可以进行自动的服务发现。例如,我希望在项目中添加一个新的服务,如果使用nginx的话就需要手动修改nginx配置文件,并创建路由规则。而traefik则会自动监听服务状态,新加的服务也会根据规则自动创建路由。这就使得它在初始配置时略微麻烦,但是后续使用的过程比较简单。
重要概念
traefik有几个较为重要的概念:
- provider:之所以能自动进行服务发现,是因为要有人告诉它。告诉它的这个人就是provider,这个provider可以是docker socket、zookeeper、k8s、redis甚至file。traefik时刻监听它们里面的内容,并对其变化做出反应。
- Router:路由规则,例如我希望对 “n1.domain.com” 的请求全部路由到n1服务器,而“n2.domain.com”的请求全部路由到n2服务器,这就是两条根据域名区分的路由规则
具体可以设定的参数参见:https://doc.traefik.io/traefik/routing/providers/docker/
- Service:处理具体请求的服务,例如上述的n1、n2服务器,但一个服务器上也可能有多个service,此时需要通过端口进行区分
- Middleware:每个请求被traefik拦截后,都会经过一系列middleware才能到达service,用户可以指定需要哪些middleware,例如对url进行修改、对header进行修改等
具体有哪些middleware见:https://doc.traefik.io/traefik/middlewares/http/overview/ 和
配置文件
traefik有两种非常重要的配置文件:静态配置和动态配置
静态配置就是一个 traefik.yml 的配置文件,这里面配置的是traefik的一些启动参数,例如其监听的端口、是否开始dashboard等
动态配置就是用来配置各种路由规则的。traefik一旦启动后就不需要再进行配置了,所有新加入的服务都应该在该服务启动时就指定路由规则,然后等待traefik自动发现。
例如:我启动了一个traefik,此时需要新加入一个web服务S,则我应该在启动S时给定一个启动参数“rule=my-router-rule”用于路由的配置(真实的配置不是这样,但也是kv的形式),这个参数就是一个动态配置。由于不同的provider中服务的启动方式不同,故动态配置都是不尽相同的。例如若使用docker作为provider,则启动新的docker容器时,就需要加上 --label rule=my-router-rule
的参数。因为docker做provider时是使用容器的label作为动态配置的。
(三个月后的后记:不得不说,这种配置方式,当时一时爽,后来火葬场。当我再次进入这个服务器看的时候,我发现我完全忘记了当时是怎么配置的,我完全不知道访问规则是什么,就算我找到了域名解析规则,但我依旧无法想起它到底是怎么访问的,为什么可以这样,我已经怀疑人生到不会组织语言了)
举例
开启一个traefik并使用docker作为provider
#traefik静态配置文件 traefik.yml
# 使用docker作为provider
providers:
docker: {}
# 使用安全模式并开启dashboard
api:
dashboard: true
insecure: false
启动traefik
docker run -d -p 8080:8080 -p 80:80 -p 443:443 --name traefik -v /var/run/docker.sock:/var/run/docker.sock -v /home/hunt/Templates/traefik.yml:/etc/traefik/traefik.yml --network net1 -l "traefik.http.routers.dashboard.rule=Host(\`traefik.huntzou.com\`) && (PathPrefix(\`/api\`) || PathPrefix(\`/dashboard\`))" -l "traefik.http.routers.dashboard.service=api@internal" traefik
为了便于使用域名访问,我手动在host文件中添加了一些dns解析,其中192.168.190.128就是我的服务器ip
192.168.190.128 huntzou.com
192.168.190.128 n1.huntzou.com
192.168.190.128 n2.huntzou.com
192.168.190.128 n3.huntzou.com
192.168.190.128 traefik.huntzou.com
浏览器输入 http://traefik.huntzou.com/dashboard/ 即可看到traefik的dashboard。(注:结尾的 / 不能少)

启动两个nginx服务(启动完成后为了便于区分最好能修改下主页)
# 将 n1.huntzou.com 域名路由到n1 service
docker run -d --network net1 --name n1 -l "traefik.http.routers.r1.rule=Host(\`n1.huntzou.com\`)" -l "traefik.http.services.n1.loadbalancer.server.port=80" nginx
# 将 n2.huntzou.com 域名路由到n2 service
docker run -d --network net1 --name n2 -l "traefik.http.routers.r2.rule=Host(\`n2.huntzou.com\`)" -l "traefik.http.services.n2.loadbalancer.server.port=80" nginx
再次查看dashboard看到已经自动发现了这两个服务

浏览器分别访问 “n1.huntzou.com” 和 “n2.huntzou.com” 就能看到它们路由到了不同的service


当然,我这里是根据域名进行路由的,您也可以根据其他条件,例如header、url等进行路由
使用let’s encrypt
traefik支持使用let’s encrypt自动获取ssl证书(let’s encrypt证书一般90天有效,traefik会到还剩30天时自动获取更新)
修改配置文件:
## traefik.yml
# Docker configuration backend
providers:
docker: {}
# API and dashboard configuration
api:
dashboard: true
insecure: false
entryPoints:
web:
address: ":80"
# 用于http重定向到https
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
certificatesResolvers:
myresolver:
acme:
email: zouheng613@hunt
# 证书保存位置,可以将其挂载出去易于备份
storage: acme.json
httpChallenge:
entryPoint: web
修改traefik启动参数(用于使得dashboard也使用https):
sudo docker run -d -p 8080:8080 -p 80:80 -p 443:443 --name traefik -v /var/run/docker.sock:/var/run/docker.sock -v /home/ubuntu/traefik.yml:/etc/traefik/traefik.yml --network net1 -l "traefik.http.routers.dashboard.rule=Host(\`traefik.athe.top\`) && (PathPrefix(\`/api\`) || PathPrefix(\`/dashboard\`))" -l "traefik.http.routers.dashboard.service=api@internal" -l "traefik.http.routers.dashboard.tls=true" -l "traefik.http.routers.dashboard.tls.certresolver=myresolver" traefik
修改service启动参数:
sudo docker run -d --network net1 --name n1 -l "traefik.http.routers.r1.rule=Host(\`n1.athe.top\`)" -l "traefik.http.routers.r1.tls=true" -l "traefik.http.routers.r1.tls.certresolver=myresolver" nginx
再次访问n1服务(这里我用了真实的外网服务器和域名):
