需求场景

  • 所有需要反代的场景
  • 服务器上部署了太多的docker、frp映射等服务,每个服务都占用着各自的端口,多的以至于为了记忆这些服务端口我专门要维护一个记事本…

什么是Treafik

  • Traefik是一个开源的可以使得服务发布变得轻松有趣的 边缘路由器。它负责接收你系统的请求,然后使用合适的组件来对这些请求进行处理
  • Treafik可以自适应并动态自动发现你添加的所有服务、容器等等
  • Treafik适配了当前主流的所有服务技术(docker, k8s…),这意味着你可以一次配置,终生动态,非常适合我这种懒人…

正式使用

概念

这里用最直白的语言介绍traefik配置中的几个概念,对后边直接上手写配置有一定帮助,建议阅读

静态配置

  • Traefik初始启动时会读取的配置文件,该配置仅读取一次,后面更改需要重启服务
  • 主要包括
    • 全局配置项(Global)
    • 日志配置项(Log)
    • 入口点(Entrypoints)
    • 安全证书(TLS)
    • 提供者声明(Provider)
  • 该文件对应docker中/etc/traefik/traefik.yaml
  • 容器启动时Traefik会自动在/etc/traefik/目录下寻找traefik.toml/traefik.yaml/traefik.yml文件作为其静态配置
  • Traefik提供了共三种互斥的静态配置方式,另外两种请自行查阅文档

动态配置

  • 基本等同于各个来源的Provider配置
  • 主要需要编辑的是File Provider文件,该文件包含了所有的动态路由,Traefik会自动检测文件改动并动态发现、添加路由(Router)、服务(Service)

提供者/Providers

  • 简而言之所谓的“提供者”就是告诉Traefik要去哪儿发现所有的路由规则及其对应的服务地址
  • 该角色(Provider)的独立决定了Traefik天生即适应多入口、多平台的自动适应发现
  • 本教程中将只会展示两种Provider的配置方式,其他更多的请查阅文档

入口点/EntryPoints

  • 即Traefik对外暴露的端口,理想状态下也是整台服务器对外暴露的唯一端口
  • 所有的网络请求通过该端口到达Traefik并由其接管后进行反代分流及负载均衡
  • 可以开设多个入口点,一般为80+443

路由/Routers

  • Traefik对外暴露的规则及其对内的具体服务路由规则
  • 在这里定义Traefik所接受的域名、前缀、后缀、路径等等请求规则
  • 在这里定义Traefik在接受到特定请求时该路由到的服务/Services

服务/Services

  • 路由所要代理的具体服务地址
  • 这里可以添加由Traefik管理的负载均衡,后面还可以添加亲和性等高阶使用,具体请查阅文档

开始/Let the Traefik Go

这里采用docker的方式启动,docker-compose以及手动部署等方式请自行查阅文档

Traefik主服务启动前

静态配置

  • 静态配置需要在主服务启动之前完全确定下来并映射进容器/etc/traefik/中,主服务只会在启动、重启时读取一次,后续不再监控更改
  • 文件名必须为traefik.yamltraefik.tmoltraefik.yml
  • 这里贴出我的配置,具体作用见配置项名或注释
###########################################
#                                         #
# Main Configuration File for Treafik     #
# By Chaos                                #
#                                         #
###########################################

## Global Config ##
# --------------------------------------- #
global:
  checkNewVersion: true
  sendAnonymousUsage: false
# --------------------------------------- #

## Log Config ##
# --------------------------------------- #
log:
  # all the path is defined in the container
  # u need to map it outside
  filePath: "/etc/logs/run.log"
  level: "DEBUG"
  format: "json"
accesslog:
  filePath: "/etc/logs/access.log"
  bufferingSize: 100
  format: "json"
# --------------------------------------- #

## Api Config ##
# --------------------------------------- #
# 开启Traefik的控制看板
api:
  dashboard: true
  insecure: true
# --------------------------------------- #

## Entrypoints Config ##
# --------------------------------------- #
# Definition
entryPoints:
  web: # EntryPoint name
    address: ":80"  # EntryPoint address, must be string, not a integer
  web-secure:
    address: ":443"
  frps-control:
    address: ":446"
# --------------------------------------- #

## TLS Config ##
# --------------------------------------- #
certificatesResolvers:
  sample: # 自定义名称,后边会用
    acme: # 固定
      email: "life0531@foxmail.com"
      storage: "/etc/acme.json" # 证书存储位置,该文件需要事先创建并映射到宿主机,权限为600
      httpChallenge: # 固定
        entryPoint: "web" # acme的入口
# --------------------------------------- #

## Provider Config ##
# --------------------------------------- #
## Provider-1: File ##
# ‘文件’形式的提供者,该文件需要在启动前创建,为空与否不重要,后边会自动更新
providers:
  file:
    filename: "/etc/traefik/provider_file.yaml" # 路径,容器内部
    watch: true # auto find and update or not
  
## Provider-2: Docker ##
# docker提供者,适配本机docker,自动发现新创建的容器并定义路由、服务
  docker:
    network: traefik # traefik主服务所在的docker子网,建议提前创建好一个子网
    exposedByDefault: false # 是否默认监控所有新创建的容器,
                            # 这里设置为false之后每次创建需要被反代的容器时需要添加一个特定label
# --------------------------------------- #

创建docker子网

docker network create traefik-net

启动Traefik主服务

  • 命令
docker run -d -p 80:80 -p 443:443 -p 446:446 --name traefik \
-v <path_to_traefik.yaml_directory>:/etc/traefik/ \
-v <path_to_acme.json_file>:/etc/acme.json \
-v <path_to_all_the_logs_directory>:/etc/logs/ \
-v /var/run/docker.sock:/var/run/docker.sock \
--add-host host.docker.internal:host-gateway \
--network traefik-net \
traefik:v2.0
  • Note:
    • -v /var/run/docker.sock:/var/run/docker.sock为固定值,需要挂载让Traefik有权限监控docker的启动停止,这里会有一定安全问题,具体解决方案请自行折腾
    • --add-host host.docker.internal:host-gateway添加宿主机的本地host解析,否则容器内访问宿主机很棘手

编写File Provider

文件形式的提供者主要方便宿主机本机不以集群化工具启动的服务的反代、老旧服务的反代等等,灵活易改

  • 示例如下,见注释
  • Traefik所有的配置语法均为tmolyaml
## Routers Config ##
http:
  # --------------------------------------- #
  # http routers
  routers:
    dashboard:
      rule: "<url rule>"
      # for more rules, access [here](https://www.qikqiak.com/traefik-book/routing/routers/#_2)
      service: "dashboard"
      middlewares:
        - "redirect-ssl"
      tls:
        certResolver: "sample"
  # --------------------------------------- #

  # --------------------------------------- #
  # http services
  services:
    ldashboard:
      loadBalancer:
        servers:
          - url: "http://127.0.0.1:8080"
          # use 'http://host.docker.internal:port' if need to access he host

  # --------------------------------------- #
  # http middwares
  middlewares:
    redirect-ssl:
      redirectScheme:
        scheme: "https"
        permanent: true
        port: 443
  # --------------------------------------- #


tcp:
  # --------------------------------------- #
  # http routers
  routers: 
    frps:
      entryPoints:
        - "frps-control"
      rule: "<tcp rules, details is available in  [here](https://www.qikqiak.com/traefik-book/routing/routers/#_8)>"
      service: "frps"
  # --------------------------------------- #

  # --------------------------------------- #
  # tcp services
  services:
    frps:
      loadBalancer:
        servers:
          - address: "<reverse proxy's target>"
        terminationDelay: 1000
  # --------------------------------------- #
  • 该文件是动态监听更新的,放心大胆的改

Traefik主服务启动的情况下启动需要被反代的docker容器

  • 照例先贴模板
docker run -d \
--name=<container_name> \
--expose <ports which the container will use> \
--network traefik-net \
-l "traefik.enable=true" \
-l "traefik.http.routers.<container_name>.rule=<url rule>" \
-l "traefik.http.routers.<container_name>.middlewares=redirect" \
-l "traefik.http.routers.<container_name>.tls=true" \
-l "traefik.http.routers.<container_name>.tls.certresolver=sample" \
-l "traefik.http.middlewares.redirect.redirectscheme.scheme=https" \
-l "traefik.http.middlewares.redirect.redirectscheme.permanent=true" \
<image_name>
  • 命令详解
    • -l "traefik.enable=true":开启容器暴露,让Traefik帮我代理这个容器
    • --expose <ports which the container will use>:在刚刚创建的子网中暴露端口,没啥作用,主要怕自己忘
    • -l "traefik.http.routers.<container_name>.rule=<url rule>":声明反代规则,这里需要注意反斜杠问题,举个例子:
-l "traefik.http.routers.<container_name>.rule=Host(\`url.url\`)"
  • -l "traefik.http.routers.<container_name>.middlewares=redirect":要使用的中间件

马上结束了!

  • 此时访问刚刚定义的url规则,应该能看到Traefik的dashboard,一切正常!

后记

  • Traefik给我这种不愿意记忆乱七八糟端口的懒人提供了非常方便简单的一键配置
  • 该文只是给想体验Traefik的同学一个快速、简单的上手路线,以最简单、我能理解的方式将Traefik的主要概念、配置项进行解释并给出示例
  • 由于本人水平有限,有些地方可能存在错误或者理解不到位,feel free to ask any questions!