前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >你所不了解的 Traefik

你所不了解的 Traefik

原创
作者头像
Luga Lee
修改2021-11-22 10:58:11
9161
修改2021-11-22 10:58:11
举报
文章被收录于专栏:架构驿站架构驿站

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

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

traefik 拓扑图
traefik 拓扑图

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

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

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

代码语言:javascript
复制
[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

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

代码语言:javascript
复制
[administrator@JavaLangOutOfMemory ~] % docker-compose up -d reverse-proxy
代码语言:javascript
复制
[administrator@JavaLangOutOfMemory ~] %  curl -i http://192.168.56.114:8080/api/rawdata?jsonHTTP/1.1 200 OKContent-Type: application/jsonDate: Thu, 09 Sep 2021 02:05:08 GMTContent-Length: 1361
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 进行路由创建,具体如下所示:

代码语言:javascript
复制
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 服务,具体:

代码语言:javascript
复制
[administrator@JavaLangOutOfMemory ~] % docker-compose up -d whoami

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

代码语言:javascript
复制
[administrator@JavaLangOutOfMemory ~] % curl -i http://192.168.56.114:8080/api/rawdata?jsonHTTP/1.1 200 OKContent-Type: application/jsonDate: Thu, 09 Sep 2021 02:09:25 GMTContent-Length: 1705
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 工具进行验证,具体如下所示:

代码语言:javascript
复制
[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 的负载均衡功能,具体操作如下所示:

代码语言:javascript
复制
[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

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

代码语言:javascript
复制
[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
代码语言:javascript
复制
[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 在四个实例之间的负载均衡,具体命令如下所示:

代码语言:javascript
复制
[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 界面
traefik 界面

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

traefik middleware
traefik middleware

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

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

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

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

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

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

代码语言:javascript
复制
## 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。其相关文件配置如下所示:

代码语言:javascript
复制
## 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 V2.3.x 及后续的版本中,引入了一系列最新功能,包括 Traefik 插件系统、与 Traefik Pilot 的集成、对 Amazon ECS 的支持等,使的 Traefik 生态组件功能越来越丰富,应用场景越来越广泛。

traefik pilot
traefik pilot

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

traefik pilot
traefik pilot

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

   # 参考资料

  • https://github.com/DoTheEvo/ 

本文分享自微信公众号 -架构驿站(priest-arc)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档