本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 [署名 4.0 国际 (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/deed.zh) 本文作者: 苏洋 创建时间: 2020年12月02日 统计字数: 7130字 阅读时间: 15分钟阅读 本文链接: https://soulteary.com/2020/12/02/easier-way-to-use-traefik-2.html ----- # 更简单的 Traefik 2 使用方式 经过一年多的实践,对于使用 Traefik 有了一些更深入的体会,本篇先来介绍如何简化使用,后续会逐步展开聊聊如何在云上使用这款“云原生”工具,以及结合它做一些提升业务效率和开发效率的实践。 在 [Traefik 2 使用指南,愉悦的开发体验](https://soulteary.com/2020/01/28/traefik-2-user-guide-pleasant-development-experience.html)、[配置基于Traefik v2的 Web 服务器](https://soulteary.com/2020/02/01/configure-traefik-v2-based-web-server.html) 文章中,使用 Traefik 的方案引入了比较多的配置,如果你并不是在一个复杂场景使用,这样的配置是可以简化的。 ## 简化程序配置文件 一般情况下将参数变为配置,更利于在版本控制软件中进行版本管理。在 v2 版本中,因为有了动态配置的概念,传统的固定配置,使用简写的参数来替换,并记录在容器启动配置中,可以在减少分发文件数量的情况下,达到相同的效果。 ### 使用参数取代 traefik.toml 在之前的文章中,我提供了一般情况下,使用的默认配置内容: ```Toml [global] checkNewVersion = false sendAnonymousUsage = false [log] level = "WARN" format = "common" [api] dashboard = true insecure = true [ping] [accessLog] [providers] [providers.docker] watch = true exposedByDefault = false endpoint = "unix:///var/run/docker.sock" swarmMode = false useBindPortIP = false network = "traefik" [providers.file] watch = true directory = "/etc/traefik/config" debugLogGeneratedTemplate = true [entryPoints] [entryPoints.http] address = ":80" [entryPoints.https] address = ":443" ``` 想要达到相同的效果,只需要在 `command` 字段内添加下面的内容即可: ```yaml version: '3' services: traefik: ... command: - "--global.sendanonymoususage=false" - "--global.checknewversion=false" - "--entrypoints.http.address=:80" - "--entrypoints.https.address=:443" - "--api=true" - "--api.insecure=true" - "--api.dashboard=true" - "--api.debug=false" - "--ping=true" - "--log.level=warn" - "--log.format=common" - "--accesslog=false" - "--providers.docker=true" - "--providers.docker.watch=true" - "--providers.docker.exposedbydefault=false" - "--providers.docker.endpoint=unix:///var/run/docker.sock" - "--providers.docker.swarmMode=false" - "--providers.docker.useBindPortIP=false" - "--providers.docker.network=traefik" - "--providers.file=true" - "--providers.file.watch=true" - "--providers.file.directory=/etc/traefik/config" - "--providers.file.debugloggeneratedtemplate=true" ... ``` 现在,你就可以将 **traefik.toml** 配置文件删除掉了。 ## 简化 dashboard.toml 前文中,我们将 Traefik 的内置 dashboard 等路由通过配置文件来定义,像下面这样。 ```Toml [http.middlewares.dash-compress.compress] [http.middlewares.dash-auth.basicAuth] users = [ "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", ] [http.routers.dashboard-redirect-https] rule = "Host(`dashboard.lab.io`, `dashboard.lab.com`)" entryPoints = ["http"] service = "noop" middlewares = ["https-redirect"] priority = 100 [http.routers.dashboard] rule = "Host(`dashboard.lab.io`, `dashboard.lab.com`)" entrypoints = ["https"] service = "dashboard@internal" middlewares = ["dash-compress"] [http.routers.dashboard.tls] [http.routers.api] rule = "Host(`dashboard.lab.io`, `dashboard.lab.com`) && PathPrefix(`/api`)" entrypoints = ["https"] service = "api@internal" middlewares = ["dash-compress"] [http.routers.api.tls] [http.routers.ping] rule = "Host(`dashboard.lab.io`, `dashboard.lab.com`) && PathPrefix(`/ping`)" entrypoints = ["https"] service = "ping@internal" middlewares = ["dash-compress"] [http.routers.ping.tls] ``` 其实,只需要将配置保留剩下这两条需要被预先定义的“中间件”即可,如果你不需要页面压缩,或者不需要访问密码,那么也可以不对下面的内容进行保存: ```Toml [http.middlewares.dash-compress.compress] [http.middlewares.dash-auth.basicAuth] users = [ "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", ] ``` 接着在容器配置中添加一些 traefik 能够解析处理的规则在 `labels` 字段中即可: ```yaml version: '3' services: traefik: ... labels: - "traefik.enable=true" - "traefik.docker.network=traefik" # 默认请求转发 https 端口 - "traefik.http.routers.traefik-dash-default.middlewares=https-redirect@file" - "traefik.http.routers.traefik-dash-default.entrypoints=http" - "traefik.http.routers.traefik-dash-default.rule=Host(`dashboard.guava.lab.com`)" - "traefik.http.routers.traefik-dash-default.service=dashboard@internal" # 处理网页 - "traefik.http.routers.traefik-dash-web.entrypoints=https" - "traefik.http.routers.traefik-dash-web.rule=Host(`dashboard.guava.lab.com`) && PathPrefix(`/`)" - "traefik.http.routers.traefik-dash-web.tls=true" - "traefik.http.routers.traefik-dash-web.service=dashboard@internal" # 处理接口 - "traefik.http.routers.traefik-dash-api.entrypoints=https" - "traefik.http.routers.traefik-dash-api.rule=Host(`dashboard.guava.lab.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))" - "traefik.http.routers.traefik-dash-api.tls=true" - "traefik.http.routers.traefik-dash-api.service=api@internal" ... ``` ## 单独抽象保存的 default.toml 配置 虽然我们将 90% 的内容都迁移到了 compose 配置文件中,但是还是有一些内容暂时是不好进行重写的,比如下面提到的“内容Gzip压缩”和“HTTP转发HTTPS”: ```yaml # 提供 Gzip 压缩 [http.middlewares.gzip.compress] # tricks 实现,提供 HTTP 默认转发 HTTPS # https://github.com/containous/traefik/issues/4863#issuecomment-491093096 [http.services] [http.services.noop.LoadBalancer] [[http.services.noop.LoadBalancer.servers]] url = "" # or url = "localhost" [http.routers] [http.routers.https-redirect] entryPoints = ["http"] rule = "HostRegexp(`{any:.*}`)" middlewares = ["https-redirect"] service = "noop" [http.middlewares.https-redirect.redirectScheme] scheme = "https" ``` 这里倒不是说不能够在应用内配置,而是如果这两个中间件在应用内配置,会出现每个应用都需要配置重复配置的问题。尽管独立的配置会让应用的可迁移性更好,然而这份配置可以提供不论是在本地、私有云,还是公有云 SLB 环境下的一致行为,维护一份配置,总比维护几份要来的方便,不是吗? ## 完整的容器配置 一如既往,这里给出完整的 compose 配置: ```yaml version: '3' services: traefik: container_name: traefik image: traefik:v2.3.4 restart: always ports: - 80:80 - 443:443 networks: - traefik command: - "--global.sendanonymoususage=false" - "--global.checknewversion=false" - "--entrypoints.http.address=:80" - "--entrypoints.https.address=:443" - "--api=true" - "--api.insecure=true" - "--api.dashboard=true" - "--api.debug=false" - "--ping=true" - "--log.level=warn" - "--log.format=common" - "--accesslog=false" - "--providers.docker=true" - "--providers.docker.watch=true" - "--providers.docker.exposedbydefault=false" - "--providers.docker.endpoint=unix:///var/run/docker.sock" - "--providers.docker.swarmMode=false" - "--providers.docker.useBindPortIP=false" - "--providers.docker.network=traefik" - "--providers.file=true" - "--providers.file.watch=true" - "--providers.file.directory=/etc/traefik/config" - "--providers.file.debugloggeneratedtemplate=true" volumes: # 仅限标准的 Linux 环境 - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - /var/run/docker.sock:/var/run/docker.sock:ro - ./config/:/etc/traefik/config/:ro - ./ssl/:/data/ssl/:ro labels: - "traefik.enable=true" - "traefik.docker.network=traefik" # 默认请求转发 https 端口 - "traefik.http.routers.traefik-dash-default.middlewares=https-redirect@file" - "traefik.http.routers.traefik-dash-default.entrypoints=http" - "traefik.http.routers.traefik-dash-default.rule=Host(`dashboard.guava.lab.com`)" - "traefik.http.routers.traefik-dash-default.service=dashboard@internal" # 处理网页 - "traefik.http.routers.traefik-dash-web.entrypoints=https" - "traefik.http.routers.traefik-dash-web.rule=Host(`dashboard.guava.lab.com`) && PathPrefix(`/`)" - "traefik.http.routers.traefik-dash-web.tls=true" - "traefik.http.routers.traefik-dash-web.service=dashboard@internal" # 处理接口 - "traefik.http.routers.traefik-dash-api.entrypoints=https" - "traefik.http.routers.traefik-dash-api.rule=Host(`dashboard.guava.lab.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))" - "traefik.http.routers.traefik-dash-api.tls=true" - "traefik.http.routers.traefik-dash-api.service=api@internal" healthcheck: test: ["CMD-SHELL", "wget -q --spider --proxy off localhost:8080/ping || exit 1"] interval: 3s retries: 12 logging: driver: "json-file" options: max-size: "1m" networks: traefik: external: true ``` ## 最后 官方在前一阵推出了 [https://traefik.io/traefik-pilot/](https://traefik.io/traefik-pilot/),除了作为统一的管理中心之外,还提供了许多有用的[中间件](https://pilot.traefik.io/plugins),比如请求/响应头改写、IP 禁止名单、IP地址转换、fail2ban 等等。 因为暂时官方无意将 pilot 开源(可能也会是长期状况),如果你不介意“联公网”使用,可以试试注册 pilot 使用。 --EOF