你所不了解的 Traefik

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
EMR Serverless StarRocks,5000CU*H 48000GB*H
简介: 在之前的文章中,我们简单介绍了关于 Traefik 的相关概念及组件原理机制,具体可参考:为什么选择 Traefik Ingress ?

    在之前的文章中,我们简单介绍了关于 Traefik 的相关概念及组件原理机制,具体可参考:为什么选择 Traefik Ingress ?

    作为一款革新的边缘路由器 ,意味着 Traefik 是所构建的整个应用平台的守卫者,拦截并路由每一个接入的请求:基于所设定的逻辑和规则,以确定哪些服务处理对应的请求。关于 Traefik 的模型画像,具体可参考如下所示:

    当然,除了所具备的服务代理特征之外, Traefik 同时也拥有“服务发现”功能机制,其动态检测后端服务状态信息并实时更新路由规则,从而达到服务治理之功效。

    我们以 Docker Provider 场景作为参考模型对 Traefik 生态进行简要的剖析,以使得大家能够深入了解 Traefik 相关特性。

    如下场景中,我们基于最新版的 Traefik v2.5.2 镜像为例,进行相关相关实例的部署及运行,具体如下所示:


[administrator@JavaLangOutOfMemory ~] % vi docker-compose.yaml
version: '3'
services:
  reverse-proxy:
    image: traefik:latest
    # 开启 web UI 并且 Traefik 监听 Docker
    command: --api.insecure=true --providers.docker
    ports:
      # HTTP 端口
      - "80:80"
      # Web UI 端口(通过 --api.insecure=true 启用)
      - "8080:8080"
    volumes:
      # Traefik 监听 Docker 事件
      - /var/run/docker.sock:/var/run/docker.sock

    然后,我们运行此实例,具体如下:


[administrator@JavaLangOutOfMemory ~] % docker-compose up -d reverse-proxy
[administrator@JavaLangOutOfMemory ~] %  curl -i http://192.168.56.114:8080/api/rawdata?json
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 09 Sep 2021 02:05:08 GMT
Content-Length: 1361
{"routers":{"api@internal":{"entryPoints":["traefik"],"service":"api@internal","rule":"PathPrefix(`/api`)","priority":2147483646,"status":"enabled","using":["traefik"]},"dashboard@internal":{"entryPoints":["traefik"],"middlewares":["dashboard_redirect@internal","dashboard_stripprefix@internal"],"service":"dashboard@internal","rule":"PathPrefix(`/`)","priority":2147483645,"status":"enabled","using":["traefik"]},"reverse-proxy-traefik@docker":{"entryPoints":["http"],"service":"reverse-proxy-traefik","rule":"Host(`reverse-proxy-traefik`)","status":"enabled","using":["http"]}},"middlewares":{"dashboard_redirect@internal":{"redirectRegex":{"regex":"^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$","replacement":"${1}/dashboard/","permanent":true},"status":"enabled","usedBy":["dashboard@internal"]},"dashboard_stripprefix@internal":{"stripPrefix":{"prefixes":["/dashboard/","/dashboard"]},"status":"enabled","usedBy":["dashboard@internal"]}},"services":{"api@internal":{"status":"enabled","usedBy":["api@internal"]},"dashboard@internal":{"status":"enabled","usedBy":["dashboard@internal"]},"noop@internal":{"status":"enabled"},"reverse-proxy-traefik@docker":{"loadBalancer":{"servers":[{"url":"http://172.20.0.2:80"}],"passHostHeader":true},"status":"enabled","usedBy":["reverse-proxy-traefik@docker"],"serverStatus":{"http://172.20.0.2:80":"UP"}}}}

    此时,我们也可以通过浏览器访问 http://192.168.56.114:8080/api/rawdata 接口来查看 Traefik 的 API 原始数据。

    接下来,我们部署一个 Demo 服务,基于 Traefik 进行路由创建,具体如下所示:


version: '3'
services:
  reverse-proxy:
    # 官方的 Traefik 2.0 Docker 镜像
    image: traefik:latest
    # 开启 web UI 并且告诉 Traefik 监听 Docker
    command: --api.insecure=true --providers.docker
    ports:
      # HTTP 端口
      - "80:80"
      # Web UI 端口(通过 --api.insecure=true 启用)
      - "8080:8080"
    volumes:
      # 这样 Traefik 可以监听 Docker 事件
      - /var/run/docker.sock:/var/run/docker.sock
  whoami:
    # 一个通过 API 暴露其 IP 地址的容器
    image: containous/whoami
    labels:
      - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"

    基于上面的 Yaml文件中,我们定义了 一个名称为 whoami 简单的 web 服务,此服务会打印部署的机器的相关信息(IP 地址、主机等等)。然后我们使用以下命令启动 whoami 服务,具体:


[administrator@JavaLangOutOfMemory ~] % docker-compose up -d whoami

    此时,我们再次进行请求 Api 接口,结果如下所示:


[administrator@JavaLangOutOfMemory ~] % curl -i http://192.168.56.114:8080/api/rawdata?json
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 09 Sep 2021 02:09:25 GMT
Content-Length: 1705
{"routers":{"api@internal":{"entryPoints":["traefik"],"service":"api@internal","rule":"PathPrefix(`/api`)","priority":2147483646,"status":"enabled","using":["traefik"]},"dashboard@internal":{"entryPoints":["traefik"],"middlewares":["dashboard_redirect@internal","dashboard_stripprefix@internal"],"service":"dashboard@internal","rule":"PathPrefix(`/`)","priority":2147483645,"status":"enabled","using":["traefik"]},"reverse-proxy-traefik@docker":{"entryPoints":["http"],"service":"reverse-proxy-traefik","rule":"Host(`reverse-proxy-traefik`)","status":"enabled","using":["http"]},"whoami@docker":{"entryPoints":["http"],"service":"whoami-traefik","rule":"Host(`whoami.docker.localhost`)","status":"enabled","using":["http"]}},"middlewares":{"dashboard_redirect@internal":{"redirectRegex":{"regex":"^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$","replacement":"${1}/dashboard/","permanent":true},"status":"enabled","usedBy":["dashboard@internal"]},"dashboard_stripprefix@internal":{"stripPrefix":{"prefixes":["/dashboard/","/dashboard"]},"status":"enabled","usedBy":["dashboard@internal"]}},"services":{"api@internal":{"status":"enabled","usedBy":["api@internal"]},"dashboard@internal":{"status":"enabled","usedBy":["dashboard@internal"]},"noop@internal":{"status":"enabled"},"reverse-proxy-traefik@docker":{"loadBalancer":{"servers":[{"url":"http://172.20.0.2:80"}],"passHostHeader":true},"status":"enabled","usedBy":["reverse-proxy-traefik@docker"],"serverStatus":{"http://172.20.0.2:80":"UP"}},"whoami-traefik@docker":{"loadBalancer":{"servers":[{"url":"http://172.20.0.3:80"}],"passHostHeader":true},"status":"enabled","usedBy":["whoami@docker"],"serverStatus":{"http://172.20.0.3:80":"UP"}}}}

    通过查看 /api/rawdata 接口返回的数据,我们发现 Traefik 已自动检测到新的容器并更新了相应的配置。前面在介绍 Traefik 的时候,我们说过,当 Traefik 检测到新服务时,它会自动创建相应的路由,然后我们可以访问相应的路由。此时,我们借助 Curl 工具进行验证,具体如下所示:


[administrator@JavaLangOutOfMemory ~] % curl -H Host:whoami.docker.localhost http://127.0.0.1
Hostname: d1078dbb0332
IP: 127.0.0.1
IP: 172.20.0.3
RemoteAddr: 172.20.0.2:37580
GET / HTTP/1.1
Host: whoami.docker.localhost
User-Agent: curl/7.29.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.20.0.1
X-Forwarded-Host: whoami.docker.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: 814dfa472b98
X-Real-Ip: 172.20.0.1

    接下来,我们对  whoami 服务进行扩容,以验证 Traefik 的负载均衡功能,具体操作如下所示:


[administrator@JavaLangOutOfMemory ~] % docker-compose up -d --scale whoami=4
traefik_reverse-proxy_1 is up-to-date
Creating traefik_whoami_2 ... done
Creating traefik_whoami_3 ... done
Creating traefik_whoami_4 ... done

    此时,我们看一下扩容完成后当前我们的服务运行的容器状况,如下所示:


[administrator@JavaLangOutOfMemory ~] % docker-compose ps
         Name                        Command               State                                     Ports                                   
---------------------------------------------------------------------------------------------------------------------------------------------
traefik_reverse-proxy_1   /entrypoint.sh --api.insec ...   Up      0.0.0.0:80->80/tcp,:::80->80/tcp, 0.0.0.0:8080->8080/tcp,:::8080->8080/tcp
traefik_whoami_1          /whoami                          Up      80/tcp                                                                    
traefik_whoami_2          /whoami                          Up      80/tcp                                                                    
traefik_whoami_3          /whoami                          Up      80/tcp                                                                    
traefik_whoami_4          /whoami                          Up      80/tc
[administrator@JavaLangOutOfMemory ~] % curl -i http://192.168.56.114:8080/api/rawdata?json  
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 09 Sep 2021 02:28:35 GMT
Content-Length: 1882
{"routers":{"api@internal":{"entryPoints":["traefik"],"service":"api@internal","rule":"PathPrefix(`/api`)","priority":2147483646,"status":"enabled","using":["traefik"]},"dashboard@internal":{"entryPoints":["traefik"],"middlewares":["dashboard_redirect@internal","dashboard_stripprefix@internal"],"service":"dashboard@internal","rule":"PathPrefix(`/`)","priority":2147483645,"status":"enabled","using":["traefik"]},"reverse-proxy-traefik@docker":{"entryPoints":["http"],"service":"reverse-proxy-traefik","rule":"Host(`reverse-proxy-traefik`)","status":"enabled","using":["http"]},"whoami@docker":{"entryPoints":["http"],"service":"whoami-traefik","rule":"Host(`whoami.docker.localhost`)","status":"enabled","using":["http"]}},"middlewares":{"dashboard_redirect@internal":{"redirectRegex":{"regex":"^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$","replacement":"${1}/dashboard/","permanent":true},"status":"enabled","usedBy":["dashboard@internal"]},"dashboard_stripprefix@internal":{"stripPrefix":{"prefixes":["/dashboard/","/dashboard"]},"status":"enabled","usedBy":["dashboard@internal"]}},"services":{"api@internal":{"status":"enabled","usedBy":["api@internal"]},"dashboard@internal":{"status":"enabled","usedBy":["dashboard@internal"]},"noop@internal":{"status":"enabled"},"reverse-proxy-traefik@docker":{"loadBalancer":{"servers":[{"url":"http://172.20.0.2:80"}],"passHostHeader":true},"status":"enabled","usedBy":["reverse-proxy-traefik@docker"],"serverStatus":{"http://172.20.0.2:80":"UP"}},"whoami-traefik@docker":{"loadBalancer":{"servers":[{"url":"http://172.20.0.4:80"},{"url":"http://172.20.0.5:80"},{"url":"http://172.20.0.3:80"},{"url":"http://172.20.0.6:80"}],"passHostHeader":true},"status":"enabled","usedBy":["whoami@docker"],"serverStatus":{"http://172.20.0.3:80":"UP","http://172.20.0.4:80":"UP","http://172.20.0.5:80":"UP","http://172.20.0.6:80":"UP"}}}}

    此时,我们请求4次,以查看 Traefik 在四个实例之间的负载均衡,具体命令如下所示:


[administrator@JavaLangOutOfMemory ~] % curl -H Host:whoami.docker.localhost http://127.0.0.1
# 第一次
Hostname: 50f70b1ccace
IP: 127.0.0.1
IP: 172.20.0.4
RemoteAddr: 172.20.0.2:40000
...
# 第二次
Hostname: 8c2204231f98
IP: 127.0.0.1
IP: 172.20.0.5
RemoteAddr: 172.20.0.2:39660
...
# 第三次
Hostname: d1078dbb0332
IP: 127.0.0.1
IP: 172.20.0.3
RemoteAddr: 172.20.0.2:37600
...
# 第四次
Hostname: f1cf5b632fde
IP: 127.0.0.1
IP: 172.20.0.6
RemoteAddr: 172.20.0.2:50384
...

    基于此,我们通过 http://192.168.56.114:8080/dashboard/#/ 访问 Traefik Web  UI 以观测不同路由请求、服务、中间件以及其他相关联信息。具体如下所示:

    在整个首页,我们可以看到 Traefik 所支持的不同协议的请求、服务类型,涉及 HTTP、TCP 以及 UDP 等。同时,显示不同类型的 Providers 信息,涉及 Docker、K8S 及其他相关信息等。基于 HTTP 协议,可以看到所建立的 4个路由规则,5个服务以及2个自定义中间件。以 Middlewares 为例,我们点击基于 HTTP 协议的 “Middlewares ” 版块的“Explore” 链接,可以清新地看到当前所部署应用所形成的链路拓扑调用链,具体如下所示:

    针对 Traefik Middlewares 的自定义开发相关实践,大家若感兴趣的话,可参考之前文章:Traefik Middleware 插件实践,以便使的大家能够了解 Traefik 的功能之丰富。

    针对证书的自定续订功能,也是 Traefik 组件的强大功能之一,基于此,我们将分别基于 HTTP 和 DNS 两方面进行简要阐述。

    基于上述场景,其简要的活动流程解析为:

    Traefik 使用 ACME(一种协议(精确约定的通信方式),用于协商来自 LE 的证书。它是 Traefik 的一部分) 向 LELet's Encrypt,一种提供免费证书的服务请求特定域的证书,如,example.com。LE 使用一些随机生成的文本进行回答,Traefik 将这些文本放在服务器上的特定位置。LE 然后询问DNS Internet 服务器,例如 .com,该服务器指向某个 IP 地址。LE 通过端口 80/443 查看包含该随机文本的文件的 IP 地址。

    如果存在,那么这证明了请求证书的人同时控制服务器和域,因为它显示了对 DNS 记录的控制。证书已颁发,有效期为3个月,剩余不足30天时,Traefik将自动尝试续订。

    基于 HttpChallenge 的优势在于能够获得通配符证书。这些是验证所有子域 *.example.com 的证书此外,不需要打开任何端口。其相关文件配置如下所示:


## STATIC CONFIGURATION
log:
  level: INFO
api:
  insecure: true
  dashboard: true
entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
certificatesResolvers:
  lets-encr:
    acme:
      #caServer: https://acme-staging-v02.api.letsencrypt.org/directory
      storage: acme.json
      email: whatever@gmail.com
      httpChallenge:
        entryPoint: web

    基于此场景,Traefik 使用 ACME 向 LE 请求特定域的证书,如 example.com。LE 回答一些随机生成的文本,Traefik 将其作为新的 DNS TXT 记录。然后,LE 检查 example.com DNS 记录以查看文本是否存在。

    如果它存在,那么这证明了请求证书的人控制了域,证书有效期为3个月。Traefik将在剩余时间不足30天时自动尝试续订。

    相比基于 HttpChallenge ,Traefik 需要能够对 DNS 记录进行自动更新,因此需要任何管理 DNS 站点的人对此提供支持。这就是为什么要使用 Cloudflare。其相关文件配置如下所示:


## STATIC CONFIGURATION
log:
  level: INFO
api:
  insecure: true
  dashboard: true
entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
certificatesResolvers:
  lets-encr:
    acme:
      #caServer: https://acme-staging-v02.api.letsencrypt.org/directory
      email: whatever@gmail.com
      storage: acme.json
      dnsChallenge:
        provider: cloudflare
        resolvers:
          - "1.1.1.1:53"
          - "8.8.8.8:53"

    除上述特性外,在 Traefik V2.3.x 及后续的版本中,引入了一系列最新功能,包括 Traefik 插件系统、与 Traefik Pilot 的集成、对 Amazon ECS 的支持等,使的 Traefik 生态组件功能越来越丰富,应用场景越来越广泛。

    除了上述所展现的实例、告警、监控信息功能之外,Traefik Pilot 也支持自定义“插件”开发功能,其提供了丰富的插件类型,可结合实际的业务场景进行适应性装配,具体如下所示:

    综上所述,作为一款云原生边缘路由器,Traefik 功能已经能够满足绝大部分的业务场景,同时,也落地不少的行业及应用。或许,在下一个版本中,我们将迎来更为强大的 Traefik 生态,包括对谷歌团队最新推出的 Kubernetes Service API 的支持,以及用于在 Traefik Mesh 中支持 mTLS 的功能。除上述外,其他可能潜在的功能特性也会随着市场的不断变化而应运而生,最后,让我们拭目以待~

  # 参考资料

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
6月前
|
Kubernetes 负载均衡 应用服务中间件
kubernetes—Ingress详解
kubernetes—Ingress详解
127 0
|
6月前
|
Kubernetes 应用服务中间件 nginx
|
3月前
|
Kubernetes 负载均衡 应用服务中间件
在k8S中,ingress是什么?
在k8S中,ingress是什么?
|
6月前
|
Kubernetes 负载均衡 应用服务中间件
Kubernetes的Ingress
Kubernetes的Ingress
116 0
Kubernetes的Ingress
|
6月前
|
弹性计算 Kubernetes 安全
基于 Traefik 的 ForwardAuth 配置
基于 Traefik 的 ForwardAuth 配置
|
Kubernetes 应用服务中间件 Linux
kubernetes 部署 nginx-ingress-controller
kubernetes 部署 nginx-ingress-controller
271 0
|
Kubernetes 应用服务中间件 调度
kubernetes Ingress、Ingress controller
kubernetes Ingress、Ingress controller
|
负载均衡 网络架构 Docker
Traefik
Traefik 是一款开源的反向代理和负载均衡工具,它可以自动地为容器化的应用程序提供动态路由和负载均衡服务。Traefik 支持多种后端服务,并且可以根据容器的标签和元数据自动发现和配置后端服务。
562 1
|
Kubernetes 应用服务中间件 nginx
Ingress
Ingress
336 0
|
Kubernetes Cloud Native 中间件
为什么选择 Traefik Ingress ?
何为 Traefik Ingress ? 在解析此概念之前,我们回顾下 Kubernetes 生态组件 Ingress Controller (中文释义:入口控制器)的概念。
130 0