使用 Traefik 边缘路由器

使用 Traefik 边缘路由器

## 简介

Traefik 是一个现代化的反向代理、负载均衡工具,使得微服务的部署更加容易。 Traefik 兼容所有主流的集群技术,比如 Docker, Swarm mode, Kubernetes, Marathon, Consul, Etcd, Rancher, Amazon ECS, ...

最吸引我的是,它的配置是 自动动态 的,用人话说就是:

会自动监听配置文件改动,自动发现新服务接入,并更新自己的配置,无需人工重启。

## 与 Nginx 相比

很长一段时间我都在用 Nginx 作为流量分发的入口,Nginx 配置简单,快速,功能强大,成熟稳定,balabala...

如今我把应用入口换成了 Traefik,并不是说 Nginx 比之差一些,而是 Traefik 有一些很强大的功能,作为 边缘路由器 更合适、更 cool,Nginx 在其它场景下依然使用很广泛,这里列一些 Traefik 的优势:

  1. 自带一个 dashboard 界面,可视化更直观。
  2. 自带 服务发现 能力,可自动监听配置改动、发现新服务,并自动更新无需人工重启。(像不像 Ingress?)
  3. 更现代,因为比较新,所以考虑了很多容器技术、编排工具,可以支持 本地配置DockerKubernetes 等。
  4. 提供了 Let's Encrypt 证书工具,我用它替换掉了 acme.sh,毕竟原生支持更方便,作为 边缘路由器 的角色也很合理。
  5. 折腾一下 ...

## 安装

### 使用二进制文件

可以从 Github Release 页面获取最新的二进制文件。

bash
1# 解压
2& tar -zxvf traefik_${traefik_version}_linux_${arch}.tar.gz
3
4# 然后运行
5& ./traefik --help

### 使用官方 Docker 镜像

可以在 Docker Official Images 选择一个镜像来运行。

bash
1docker run -d -p 8080:8080 -p 80:80 \
2    -v $PWD/traefik.toml:/etc/traefik/traefik.toml traefik:v2.4

### 使用 helm

可以从 traefik-helm-chart 获取最新的 helm chart。

bash
1# 1. 添加 repo
2& helm repo add traefik https://helm.traefik.io/traefik
3# 2. update
4& helm repo update
5# 3. install
6& helm install traefik traefik/traefik

想在 Kubenetes 使用通过 helm 安装最方便,traefik-helm-chart 的配置参数挺多,了解基本使用后也方便触类旁通。 二进制方式,和 docker 方式差不多,本文会着重介绍 docker 方式。

## 配置发现

配置分为 静态配置动态配置 两种,静态配置 作为 traefik 的启动配置,动态配置 可以是完全动态的路由配置。 Traefik 在启动的时候,会在以下位置中搜索名为 traefik.toml(或 traefik.ymltraefik.yaml)的文件(后文皆以 .yml 为例):

  • /etc/traefik/
  • $XDG_CONFIG_HOME/
  • $HOME/.config/
  • . (工作目录)

Traefik 会自动发现 动态配置,并更新自身。也被成为:配置发现

### 概述

Traefik 的服务发现,是通过 Providers 来实现的。 通过查询 providers 的 API 来查找有关路由的相关信息,Traefik 每次检测到变更,都会动态更新路由。

官方支持的 providers 有很多,这里介绍常用的 3 种:

Provider类型配置类型
File手动TOML/YAML 文件
Docker编排器标签
Kubernetes编排器自定义资源

可以从 这里查看 更多支持的 providers。

### File

file provider 可以让我们通过 TOML 或者 YAML 文件来定义动态配置。

静态配置 中,预先声明要监听的 文件 或者 文件夹

yaml
1providers:
2  file:
3    # 文件 跟 目录,2选1
4    # 要监听的文件
5    filename: dynamic_conf.yml
6    # 要监听的目录
7    directory: /path/to/config
8    # 允许 traefik 自动 watch 配置文件的变化
9    watch: true

### Docker

在启动容器的时候,可以以标签的形式通知、配置,以让 Traefik 来完成自动化配置。 如果容器停止,Traefik 也会自动销毁相关配置。

使用 静态配置,告知 Traefik 去监听 Docker 的生命周期。

yaml
1providers:
2  # 监听docker生命周期
3  docker:
4    # 用于连接所有容器的默认 docker 网络,默认为 empty
5    network: traefik-network

然后启动容器的时候添加 label,Traefik 会根据 label 的配置去生成对应路由。

yaml
1# docker-compose.yml
2version: '3'
3services:
4  blog:
5    image: 'xxx:latest'
6    labels:
7      - traefik.http.routers.blog.rule=PathPrefix(`/`)
8      - traefik.http.services.blog.loadbalancer.server.port=8080
9networks:
10  default:
11    name: traefik-network
12    external: true

以上的 labels 会生成如下动态配置:

yaml
1http:
2  # 生成一个 router 规则
3  routers:
4    blog:
5      rule: 'PathPrefix(`/`)'
6      service: blog
7  # 生成一个 service,并配置访问的 port
8  services:
9    blog:
10      loadBalancer:
11        servers:
12          - url: 'http://traefik-network:8080'

### Kubernetes

在 k8s 中使用 Traefik 作为 Ingress Controller 是一个不错的选择,新加路由只用加一个普通的 Ingress 配置文件:

yaml
1# ingress.yaml
2kind: Ingress
3apiVersion: extensions/v1beta1
4metadata:
5  name: ingress-traefik
6  namespace: xxx
7spec:
8  rules:
9    - http:
10        paths:
11          - path: /
12            backend:
13              serviceName: some-name
14              servicePort: some-port

使用 helm 安装 Traefik 是一种很方便的方式,可以参考:https://github.com/traefik/traefik-helm-chart

## 路由和负载均衡

### 概览

#### 流量流转

当请求进来当时候我们看下发生了啥,这样更有助于理解 Traefik 的一些概念。

  1. 在我们启动 Traefik 的时候,我们要定义 entrypoints(静态配置),表示流量的入口。
  2. 然后连接到 entrypointsroutes 去判断是否符合定义的规则。
  3. 如果符合,就用 middleware 中间件去处理下。
  4. 最后把流量打到 services 上面。

#### 各部分职责:

  • Providers 来发现基础设施上存在的服务(它们的 IP、运行状况等...)
  • Entrypoints 监听 traffic 的流量入口 (ports, ...)
  • Routers 分析请求 (host, path, headers, SSL, ...)
  • Middlewares 会把请求做一些调整 (authentication, rate limiting, headers, ...)

#### 示例

我们用 File Provider 来看一个完整的例子,首先是 静态配置

yaml
1entryPoints:
2  web:
3    # 监听 8081 端口的请求
4    address: :8081
5
6providers:
7  # 配置 file provider 监听目录,可以动态定义 routers / middlewares / services
8  file:
9    directory: /path/to/dynamic/conf
10    watch: true

然后我们就可以在 /path/to/dynamic/conf 目录中去定义 动态配置

yaml
1# http 路由部分
2http:
3  routers:
4    # 定义一个路由去处理请求
5    to-whoami:
6      # 路由的规则是 Host:example.com,而且请求是 /whoami/ 开头
7      rule: 'Host(`example.com`) && PathPrefix(`/whoami/`)'
8      # 如果规则匹配上,就用以下中间件处理
9      middlewares:
10        - test-user
11      # 最后再把流量打到 `whoami` 的服务上。
12      service: whoami
13
14  middlewares:
15    # 定义一个中间件,用来验证用户身份。中间件可以在这里查阅:https://doc.traefik.io/traefik/middlewares/overview/
16    test-user:
17      basicAuth:
18        users:
19          - test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/
20
21  services:
22    # 定义一个服务,以及如何把它跟现有服务关联起来
23    whoami:
24      loadBalancer:
25        servers:
26          - url: http://private/whoami-service

### EntryPoints

EntryPoints 就是 Traefik 的流量入口,定义了监听哪个端口,或者监听 TCP 还是 UDP。

yaml
1# example
2## 静态配置
3entryPoints:
4  web:
5    address: ':80'
6
7  web-secure:
8    address: ':443'

### Routers

Routers 负责将请求转发到指定服务,可以将指定 EntryPoints 的,符合自己规则 Rules 的请求,经过中间件 Middlewares 处理后,转发到指定的 Service 上面。

yaml
1## 动态配置
2http:
3  routers:
4    router-name:
5      # 监听指定 entryPoints,默认所有
6      entryPoints:
7        - 'websecure'
8        - 'other'
9      # 指定该路由规则
10      rule: 'Host(`traefik.io`) && Path(`/traefik`))'
11      # 指定服务
12      service: 'service-name'

### Services

Services 负责配置如何获取最终将处理传入请求的实际服务。

yaml
1## 动态配置
2http:
3  services:
4    service-name:
5      loadBalancer:
6        # loadBalancer 会将流量在多个实例间进行负载均衡
7        servers:
8          - url: 'http://private-ip-server-1'
9          - url: 'http://private-ip-server-2'

## HTTPS

Traefik 可以使用 ACME 自动获取证书,其它方式暂不赘述。

... 直接看例子吧,注释多。

yaml
1# entrypoints,入口
2entryPoints:
3  # http, 80 端口
4  web:
5    address: :80
6    http:
7      # 会重定向到 https
8      # https://doc.traefik.io/traefik/routing/entrypoints/#redirection
9      redirections:
10        entryPoint:
11          to: websecure
12          scheme: https
13  # https, 443 端口
14  websecure:
15    address: :443
16    http:
17      tls:
18        certResolver: nosaidResolver
19        domains:
20          - main: nosaid.com
21            sans:
22              - www.nosaid.com
23
24# https://doc.traefik.io/traefik/https/acme/#httpchallenge
25certificatesResolvers:
26  nosaidResolver:
27    acme:
28      email: hi.xieshuang@gmail.com
29      storage: /etc/traefik/acme.json # 要存储的位置,如果使用 docker 记得添加 volume
30      httpChallenge:
31        entryPoint: web # 对于 http 的请求使用 httpChallenge 方式获取证书

## 中间件

通过附加到路由,中间件可以在请求发送到服务之前来调整请求。 中间件被附件到路由上,是一种在请求发送到你的 服务 之前(或者在服务的响应发送到客户端之前)调整请求的一种方法。

Traefik 内置了许多不同功能的中间件,可以修改请求,头信息,重定向,添加身份验证等等。

中间件可以通过链式组合的方式来满足业务需求。

yaml
1http:
2  routers:
3    ttyd-router:
4      rule: 'PathPrefix(`/prefix`)'
5      service: some-service
6      middlewares:
7        - prefix-middleware
8
9  middlewares:
10    prefix-middleware:
11      stripPrefix:
12        prefixes:
13          - '/prefix'

比如上面例子中,中间件就会抹去 /prefix 前缀。 如果请求 /prefix/a/b,在 some-service 接收到请求的时候,就变成了 /a/b

## Dashboard

Traefik 自带了一个 Web UI,叫做 Dashboard。可以快速、便捷、直观的查看当前的所有 entryPointsroutesmiddleWaresbalabala

Dashboard 的开启方式比较简单,添加 静态配置,就可以访问 8080 端口来访问了。

yaml
1# 开启 dashboard
2# https://doc.traefik.io/traefik/operations/dashboard/#insecure-mode
3api:
4  insecure: true

## 参考

Traefik Official Document

一文搞懂 Traefik2.1 的使用

to-be-continued
avatar

闲暇时候的文章

会写一些 代码、心情、生活、食物、balabala 我也不知道什么类型的东西 >_<#@!

如果碰巧你找到感兴趣的东西,可以来瞅瞅。

Copyright © 2017 - 2023 xieshuang. All Rights Reserved. Power by k8s + nestjs + next + vue + typescript.
鄂ICP备20008501号-1