Traefik 微服务 API 网关教程(一)

随笔2周前发布 老贺
38 0 0

原文:Traefik API Gateway for Microservices

协议:CC BY-NC-SA 4.0

一、Traefik 简介

在过去的几年中,微服务已经成为企业应用开发的主流架构范例。它们已经取代了过去几十年来作为主流的应用开发的整体架构。单片应用是在模块化架构中开发的。这意味着被称为模块的离散逻辑组件被创建来基于它们的职责隔离组件。即使一个应用由离散的组件组成,它们也被打包并作为一个可执行文件部署。总的来说,应用具有非常紧密的耦合。对这些模块中的每一个的改变都不能单独发布。您需要每次发布一个完整的应用。

当您构建一个未知的应用时,单片架构非常适合。在这种情况下,您通常需要为每个功能快速构建原型。单片架构在这种情况下很有帮助,因为应用有一个统一的代码库。该架构具有以下优势。

开发简单。

测试简单。例如,您可以通过启动应用并使用 Selenium 测试 UI 来实现端到端测试。

易于部署。您只需将打包的应用复制到服务器上。

通过在负载平衡器后运行多个副本,可以轻松地进行水平扩展。

总之,您可以在这些早期阶段快速交付完整的应用。但是随着应用的有机增长,收益会逐渐减少。在后期阶段,应用变得更难维护和操作。大多数子组件承担更多的责任,成为大的子系统。每个子系统都需要一个开发团队来维护。因此,完整的应用通常由多个开发团队维护。但是应用具有高耦合性,因此开发团队在提供新功能时是相互依赖的。由于单一的二进制文件,该组织面临以下一系列问题。

季度发布:应用功能需要更多时间发布。大多数时候,一个应用的特性需要跨不同的子系统来处理。每个团队都可以进行开发,但是部署需要整套组件。因此,团队很少能独立工作。发布通常是跨不同团队的大规模协同工作,每个周期只能做几次。

弃用的技术:通常,当你使用技术时,你必须定期升级它。升级确保所有的漏洞都被覆盖。应用库通常需要频繁升级,因为它们还会添加新功能。但是升级一个整体的库是困难的。团队可以尝试使用最新的版本,但通常需要确保升级不会破坏其他子系统。在某些情况下,升级甚至会导致子系统的完全重写,这对业务来说是非常危险的。

陡峭的学习曲线:单片应用通常有很大的代码库。但是单个开发人员经常在代码库的一个非常小的子集上工作。乍一看,代码行给开发人员造成了心理瓶颈。此外,由于应用是紧密耦合的,开发人员通常需要知道其他人是如何调用代码的。因此,新开发人员的总体入职时间很长。即使是有经验的开发人员也很难对没有维护好的模块进行修改。这造成了一个随着时间推移而扩大的知识缺口。

应用扩展:通常情况下,单一应用只能垂直扩展。水平扩展应用是可能的,但是您需要确定每个子系统如何维护其内部状态。在任何情况下,应用都需要所有子系统的资源。资源不能有选择地提供给有负载的子系统。因此,对于整体式应用来说,这是一个要么全有要么全无的场景。这通常是一件昂贵的事情。

面对挑战时,组织会寻找替代架构来解决这些问题。

微服务架构

微服务架构是整体架构的替代方案(见图 1-1 )。它将单一应用转换为具有以下特征的分布式系统。

Traefik 微服务 API 网关教程(一)

图 1-1

整体服务与微服务

服务:微服务是作为可以独立工作,提供一组业务能力的服务而开发的。服务可能依赖于其他服务来执行所需的功能。独立的团队可以开发这些服务。团队可以自由选择和升级他们服务所需的技术。组织通常将服务的全部责任委托给他们各自的团队。团队必须确保他们各自的服务按照约定的可用性运行,并满足约定的质量标准。

业务环境:服务通常是围绕业务领域创建的。这确保了它不会太细粒度或太大。服务需要首先回答它是所述业务功能的所有者还是该功能的消费者。函数所有者必须维护所有相应的函数数据。如果它需要更多的支持功能,它可能会从另一个服务中使用相同的功能。因此,确定业务上下文边界有助于检查服务依赖关系。微服务旨在构建一个具有松耦合和高内聚属性的系统。聚合所有逻辑上相关的功能使服务成为一个独立的产品。

应用治理:在企业系统中,治理扮演着重要的角色。你很少想制造难以运行的系统。由于这个原因,一个治理小组保持对开发人员使用的技术的检查,以便操作团队仍然可以运行系统。但是微服务架构为各个团队提供了完全的所有权。所有权不限于开发。它还委托服务操作。因此,大多数组织必须采用 DevOps 实践。这些实践使开发团队能够有效地操作和治理服务。

自动化:自动化在微服务中起着重要的作用。它适用于所有形式,如基础设施自动化、测试自动化和发布自动化。团队需要高效运作。他们需要更频繁地测试并快速发布。这只有在他们更多地依赖机器而不是人工干预的情况下才有可能。开发后的手工测试是一个主要的瓶颈。因此,团队经常以多种方式自动化他们的测试,比如 API 测试、冒烟测试、夜间测试等等。他们经常手动执行探索性测试来验证构建。发布和基础设施准备通常通过使用 DevOps 实践来自动化。

总之,一个整体有一个集中的经营模式。这意味着所有代码都驻留在一个地方;每个人都使用同一个库,同时发布,等等。但另一方面,微服务是一种完全去中心化的方法。团队可以完全自主地做出最佳决策。采用这样的架构不仅要求软件设计的改变,还要求组织交互的改变。组织从这种应用设计中获得了以下好处。

灵活

这是组织采用微服务架构的最大驱动因素之一。组织变得更具适应性,他们可以更快地响应不断变化的业务需求。该架构提供的松散耦合允许加速开发。在将小型、松散耦合的服务部署到生产环境之前,可以单独构建、修改和测试它们。该模型指示小型独立开发团队在其定义的边界内工作。这些团队负责维护高水平的软件质量和服务可用性。

创新ˌ革新

微服务架构促进了支持每个服务的独立小型开发团队。每个团队在其服务范围内拥有所有权。他们不仅负责开发,还负责运营服务。因此,团队采用了大量的自动化和工具来帮助他们实现这些目标。这些高层次的目标推动了组织内的工程文化。

此外,开发团队通常很清楚他们服务的缺点。这样的团队可以使用他们的自主决策能力来解决这些问题。他们可以经常解决问题并提高服务质量。在这里,团队被充分授权为他们的目的选择合适的工具和框架。它最终会提高整个产品的技术质量。

弹性

故障隔离是将故障的影响限制到有限的子系统/组件的行为。这个原则允许子系统失败,只要它不影响整个应用。微服务架构的分布式特性提供了故障隔离,这是构建弹性系统的主要要求。任何出现故障的服务都可以独立处理。开发人员可以修复问题并部署新版本,而应用的其余部分继续独立运行。

弹性,或者说容错,通常被定义为应用在某些部分出现故障的情况下正常运行的能力。像微服务这样的分布式系统是基于各种原则的,比如电路断开、节流来处理故障传播。这是一个重要的方面;如果做得好,它提供了一个弹性系统的好处。但是,如果这种情况不处理,就会由于故障级联而导致频繁停机。弹性还提高了业务敏捷性,因为开发人员可以发布新的服务,而不用担心系统中断。

可量测性

可伸缩性被定义为系统处理工作增长的能力。在一个整体中,很容易量化系统的可伸缩性。在单块系统中,随着负载的增加,并非所有子系统的流量都成比例增加。通常情况下,系统的某些部分比其他部分获得更多的流量。因此,整体系统性能由服务的子集决定。通过添加更多的硬件,可以更容易地扩展单芯片系统。但有时,这也很困难,因为不同的模块可能有冲突的资源需求。总的来说,一个杂草丛生的庞然大物没有充分利用硬件。它通常会降低系统性能。

微服务提供的分离使组织能够了解每个微服务所服务的流量。分而治之原则有助于提高整体系统性能。开发人员可以为每个服务采用适当的任务并行化或集群技术来提高系统吞吐量。他们可以采用适当的编程语言和框架,用尽可能好的配置进行微调。最后,可以通过研究服务需求来分配硬件,而不是扩展整个生态系统。

可维护性

技术债务是单体系统的一个主要问题。过度生长的巨石通常有不被整个团队很好理解的部分。在一个整体中解决技术债务是困难的,因为人们经常害怕破坏任何工作特性。曾经有过这样的例子,不需要的死代码通过解决某个特定模块上的技术债务而复活了。

微服务架构遵循分而治之的原则,有助于缓解这一问题。好处可以与面向对象的应用设计联系起来,在面向对象的应用设计中,系统被分解成对象。每个对象都有一个定义好的契约,从而改进整个系统的维护。开发人员可以对每个被重构的对象进行单元测试,以验证正确性。类似地,围绕业务环境创建的微服务有一个定义好的契约。这些松散耦合的服务可以单独重构和测试。开发人员可以在验证服务契约的同时解决服务的技术债务。采用微服务通常被称为一个整体的技术债务偿还。

您已经了解了微服务架构的优势。但是架构也带来了很多挑战。一些挑战是由于系统的分布式性质,而另一些挑战是由应用环境的多样性引起的。服务可以用不同的技术实现,并以不同的方式扩展。同一服务可以有多个版本来满足不同的需求。团队应该在应用设计期间制定策略来克服这些挑战,而不是事后才想到。应用部署就是这样一个重要方面。Monoliths 已经部署在一个三层模型上。但同样的模式在微服务上效果并不好。下一节讨论部署模型中所需的更改。

n-分层部署

层部署是一种设计实现,其中 web 应用被分为应用表示、应用处理和数据管理功能。这些功能由称为的独立组件提供服务。应用层允许职责分离。各层之间的所有通信都是线性的。每一层都由自己的软件子系统管理。 n 层部署提供了改进应用可伸缩性的好处。整体式应用通常部署为三层(见图 1-2 )应用。

Traefik 微服务 API 网关教程(一)

图 1-2

三层

表示层:这一层负责提供应用的所有静态内容。它通常通过使用 Apache、Nginx 和 IIS 等 web 服务器来管理。这些 web 服务器不仅为应用提供静态 UI 组件,还通过将请求路由到应用层来处理动态内容。Web 服务器经过优化,可以处理许多静态数据请求。因此,在负载下,它们表现良好。其中一些服务器还提供不同的负载平衡机制。这些机制可以支持应用层的多个节点。

应用层:该层负责提供所有的处理功能。它包含交付应用核心功能的业务处理逻辑。开发团队负责在合适的技术堆栈(如 Java、Python 和. NET)中构建这一层。这一层能够为用户请求提供服务,并生成适当的动态响应。它接收来自表示层的请求。为了满足请求,应用层可能需要额外的数据来与数据层交互。

数据层:该层提供数据存储和数据检索的能力。这些数据管理功能超出了应用的范围。因此,应用使用数据库来满足这些需求。数据层使用 API 提供数据操作功能。应用层调用这个 API。

使用三层架构有很多好处,包括可伸缩性、性能和可用性。您可以在不同的机器上部署这些层,并以优化的方式使用可用资源。应用层提供了大部分的处理能力。因此,它需要更多的资源。另一方面,web 服务器提供静态内容,不需要很多资源。这种部署模式通过对每一层采用不同的复制策略来提高应用的可用性。

四层部署

三层部署与 monolith 应用一致。整体通常是应用层。但是有了微服务,整块被转换成几个服务。因此,三层部署模型不足以处理微服务架构。它需要以下四层部署模型(见图 1-3 )。

Traefik 微服务 API 网关教程(一)

图 1-3

四层

内容交付层:这一层负责将内容交付给最终用户。客户端可以在 web 浏览器或移动应用中使用应用。它经常要求在不同的平台上制作不同的用户界面。内容交付层负责确保应用 UI 在这些不同的平台上正常工作。该层还抽象了服务层,并允许开发人员快速开发新的服务来满足不断变化的业务需求。

网关层:这一层有两个角色。

动态发现已部署的服务,并将它们与用户请求相关联

将请求路由到服务并发送响应

对于每个请求,网关层从所有底层服务接收数据,并发回一个聚合响应。它必须处理不同的场景,比如基于角色的访问、延迟响应和错误响应。这些行为使得服务层更容易。服务层可以只关注业务需求。

服务层:这一层负责提供所有的业务功能。服务层是为微服务方法设计的。该层向其客户端提供数据,而不关心数据是如何被使用的。客户端可以是其他服务或应用 UI。每个服务都可以基于它们的请求负载模式进行扩展。客户端有责任确定新的实例。所有这些都支持应用生态系统的可插拔方法。新服务可以通过使用现有服务来构建。它们可以很容易地集成到企业环境中。

数据层:该层提供数据存储和数据检索的能力。数据管理功能仍然超出了应用的范围。但是每项服务都有专属的数据管理基础设施。可以是 MySQL 这样的 DBMS,也可以是 Mongo 这样的文档库。

四层架构(见图 1-3 )是由早期的微服务采用者如网飞、亚马逊和 Twitter 开创的。在范例的中心,网关层负责将完整的解决方案绑定在一起。网关需要一个能够将其余层链接在一起的解决方案,以便所有层都能够通信、扩展和交付。在三层架构中,表示层拥有可用于网关层的 web 服务器。但是首先,您应该确定网关层解决方案所需的特征。

网关特征

网关是所有用户流量的入口点。它通常负责将请求委托给不同的服务,整理它们的响应,并将其发送回用户。在微服务架构下,网关必须与架构的动态特性协同工作。以下部分讨论网关组件的不同特征。

应用层协议

OSI 网络模型在第 4 层和第 7 层处理流量。第 4 层仅提供底层连接细节。这一层的流量管理只能使用协议(TCP/UDP)和端口细节来执行。另一方面,第 7 层在应用层运行。它可以根据每个消息的实际内容执行流量路由。HTTP 是使用最广泛的应用协议之一。您可以检查 HTTP 头和正文来执行服务路由。

第 7 层负载平衡使负载平衡器能够做出更明智的负载平衡决策。它可以应用各种优化,比如压缩、连接重用等等。您还可以配置缓冲来卸载上游服务器的慢速连接,以提高整体吞吐量。最后,您可以应用加密来保护我们的通信。

在当前的生态系统中,有各种各样的应用协议可供选择。这些协议中的每一个都满足一组需求。团队可能会采用特定的应用协议,比如 gRPC,因为它更适合他们的微服务。这不需要其他团队适应相同的应用协议。但是在生态系统中,网关需要将流量分配给大多数服务。因此,它需要支持所需的协议。应用协议的列表非常广泛。因此,网关需要有一组丰富的当前协议。此外,通过添加新的协议来扩展这个列表应该很容易。

PROTOCOLS

HTTP/2 是 HTTP/1.1 协议的下一个版本。它是一个二进制协议,不会改变任何现有的 HTTP 语义。但它提供实时多路通信,并通过更好地利用底层 TCP 连接来提高应用性能。

gRPC 是一个二进制 RPC 协议。它提供了各种功能,例如多路复用、流、健康指标和连接池。它通常与 JSON 或协议缓冲区等有效负载序列化一起使用。

REST (表述性状态转移)是基于 HTTP 语义的应用协议。该协议表示使用 HTTP 方法访问的资源。它通常与 JSON 有效负载一起使用来描述状态。

另一个重要方面是进程间通信范式。传统上,我们基于 HTTP 创建同步应用。但是对于数据驱动的微服务,您可能希望采用异步模型,如 ReactiveX 和 Zeromq。网关组件需要支持这两种形式的通信。开发人员应该能够挑选适合他们应用的模型。

动态配置

在 monolith 应用中,您知道后端应用的位置。位置不会经常改变,并且在运行时不会创建应用的更多实例。因为大多数服务器都是已知的,所以在静态配置文件中提供这些细节更容易。

但是在微服务应用中,这种解决方案不起作用。第一个挑战来自微服务的数量。通常,在开始时有有限的服务。但是随着系统的增长,人们意识到每个业务功能可以有多个细粒度的服务。通常这个数字可以增长到几百个服务。为每个服务分配一个静态地址并在静态文件中维护相同的更新是一项艰巨的任务。

第二个挑战来自微服务提供的可扩展性。服务可以在加载期间复制。当负载减轻时,这些服务将被删除。微服务的这种运行时行为会随着生态系统中服务的数量而成倍增加。在静态配置文件中跟踪所有这些变化是不可能的。

为了解决发现问题,微服务架构提倡服务注册。它是一个包含服务实例的网络位置的数据库。服务注册表需要近乎实时地更新。它需要在新位置可用时尽快反映出来。服务注册中心需要具有高可用性。因此,它由复制数据以保持一致性的节点群集组成。

SERVICE REGISTRY PROVIDERS

下面是最广泛使用的服务注册中心提供者。

Eureka 是一个基于 REST 的解决方案,用于注册和查询服务实例。网飞开发的解决方案是其微服务之旅的一部分。它经常在 AWS 云中使用。

etcd 是一个高度可用、分布式、一致的键值存储。它用于共享配置和服务发现。Kubernetes 使用 etcd 进行服务发现和配置存储。

Consul 是由 Hashicorp 创建的用于发现和配置服务的解决方案。除了服务注册之外,Consul 还提供了广泛的功能,比如健康检查和锁定。Consul 提供了一个 API,允许客户端注册和发现服务。

Apache Zookeeper 是为 Hadoop 生态系统而创建的。它是分布式应用的高性能协调服务。馆长是一个 Java 库,创建于 Zookeeper 之上,提供服务发现特性。

网关组件需要与服务注册中心进行交互。它可以尝试轮询服务注册表,但这样效率不高。或者,服务注册中心需要将更改推送到网关。网关需要选择这些更改并重新配置自己。因此,总而言之,网关需要与注册中心很好地集成。

热重装

在微服务架构中,部署了许多服务。这些现有服务中的每一个都可以被更新,或者可以添加新的服务。所有这些更改都需要传播到网关层。此外,网关组件可能需要一些升级来解决问题。这些操作必须在不影响最终用户的情况下执行。甚至几秒钟的停机时间都是有害的。如果网关需要停机进行服务更新,那么停机时间将乘以服务更新的频率。总之,这可能导致频繁的服务中断。

网关组件应该处理所有更新,而不需要任何重启。它不能对配置更新或升级进行任何区分。

可观察性

可观性是从控制理论中借来的概念。它是在系统之外了解系统状态的过程。它包含了诊断故障所需的所有信息。微服务中的可观测性完全不同于整体系统中的可观测性。在 monolith 应用中,有一个包含以下日志的三层部署。

请求日志

应用日志

错误日志

您可以连接回日志来确定(相当准确地)系统一直在执行什么。但是在微服务架构中,您需要跟踪数十或数百种不同的服务。仅使用日志来预测应用状态不再可能。为此,我们需要新的机制。微服务架构推荐以下方法。

追踪

请求跟踪是一种分析和监控分布式架构(如微服务)的方法。在微服务中,一个用户请求通常由多个服务处理。这些服务中的每一个都执行其各自的处理。所有这些都以请求跨度的形式记录下来。一个请求的所有这些跨度被组合成整个请求的单个跟踪。因此,请求跟踪显示了每个服务为特定请求花费的时间。

任何服务失败都可以很容易地在请求跟踪中看到。该跟踪还有助于确定性能瓶颈。跟踪是调试应用行为的一个很好的解决方案,但是它是以牺牲一致性为代价的。所有服务都必须传播正确的请求垃圾邮件。如果服务不提供 span 或者通过忽略现有报头来重新生成 span,则结果请求跟踪不能捕获所述服务。

网关组件接收来自微服务生态系统外部的所有流量。它可以跨不同的服务分发请求。因此,网关组件需要为跟踪生成请求范围。

韵律学

微服务最佳实践建议生成可分析的应用指标。这些指标反映了我们服务的状态。随着时间的推移,收集指标有助于分析和改进服务性能。在失败场景中,度量有助于确定根本原因。应用级指标可以包括排队入站 HTTP 请求的数量、请求延迟、数据库连接和缓存命中率。应用还必须创建特定于其上下文的自定义指标。网关组件还必须导出可以捕获的相关指标。这些指标可以是不同应用协议的状态代码,如 HTTP(2XX、4XX、3XX、5XX)、服务错误率、请求队列等。

总之,网关组件需要提供各种各样的可观察性输出。它必须导出统计数据、指标和日志,以便与微服务架构中的监控解决方案集成。

TLS 终止

数据安全性通常是系统的非功能性需求。应用已经使用 TLS 通信实现了数据安全。TLS 通信允许使用私有-公共密钥对加密/解密数据。在网关或表示层终止 TLS 的过程使应用能够更好地执行,因为应用不必自己处理加密和解密。这在传统架构中运行良好,因为进程间网络调用很少。但是在微服务架构中,许多服务都在生态系统中运行。根据安全标准,服务之间未加密的通信会带来严重的风险。因此,作为最佳实践,您需要加密整个集群中的所有网络通信。

服务授权是微服务架构中的另一个挑战。在微服务中,更多的请求是通过网络发出的。服务需要确定哪个客户端正在进行调用。这有助于在客户端服务出现故障时设置限制。把这些控制作为一个胭脂服务是必要的,并在系统中肆虐。身份可以通过多种方式建立。客户端可以传递不记名令牌,但是这个过程已经过时了。潜在的攻击者可以捕获和传递不记名令牌。作为最佳实践,您希望确保客户端仅使用不可移植的身份进行身份验证。因此,相互 TLS (mTLS)身份验证是推荐的做法。对于相互验证身份的服务,在建立连接之前,它们都需要提供对方信任的证书和密钥。客户端和服务器提供和验证证书的这一动作被称为相互 TLS。它确保强服务标识作为进程间通信的一部分得到实施和交换。因此,网关组件需要具有双重行为。

来自外界的流量的 TLS 终止

使用相互 TLS 调用不同服务的 TLS 身份

其他功能

网关组件执行反向代理和负载平衡器的双重职责。它必须为高级负载平衡技术提供支持。此外,该组件需要支持以下特性。

超时和重试次数

限速

断路

阴影和缓冲

基于内容的路由

特征列表是不受限制的。负载平衡器通常使用 IP 地址标记、识别和定位来实现各种安全功能,如身份验证和 DoS 缓解。网关组件也必须满足所有这些需求。

我们已经讨论了网关解决方案的高级行为。这些需求是 Apache、Nginx 和 HAProxy 等成熟市场产品的愿望清单。这些服务器提供了对一些特性的支持,但是有些特性必须使用变通方法来处理。总之,这些久经考验的解决方案没有对微服务架构的一流支持。这些产品在十年前就已经开发了它们的架构,当时需求列表是不同的。下一节将讨论 Traefik,这是一个为处理微服务部署需求而创建的开源产品。

Traefik

Traefik 是一个开源 API 网关。它旨在简化微服务操作的复杂性。Traefik 通过执行服务的自动配置来达到同样的目的。根据产品文档,开发人员应该负责开发和部署服务。Traefik 可以用合理的默认值自动配置自己,并向所述服务发送请求。

如今的微服务有着不断变化的需求。Traefik 通过遵循可插拔架构来支持所有这些需求。它支持每一种主要的集群技术,如 Kubernetes、Docker、Docker Swarm、AWS、Mesos 和 Marathon(见图 1-4 )。所有这些引擎都有自己的集成点,也称为提供者。不需要维护静态配置文件。提供者负责连接到编排引擎,并确定在其上运行的服务。然后,它将此信息传递回 Traefik 服务器,后者可以将此信息应用于其路由。Traefik 能够同时与多个提供商集成。

Traefik 微服务 API 网关教程(一)

图 1-4

Traefik

Traefik 是以 Unix 为中心开发的。它是在戈朗建造的。它提供了一个公平的表现。它遇到了一些内存问题。但是有一个很大的活跃开发人员社区在开发 Traefik。Traefik 提供的整体性能稍逊于 Nginx 等成熟的市场领导者,但它通过为所有微服务功能提供一流的支持弥补了这一点。

Note

Traefik 拥有超过 25K 个 GitHub stars(在撰写本文时),使其成为最受关注的项目之一。

装置

Traefik 经常被释放。这些版本的二进制工件可以在项目发布页面上获得( https://github.com/containous/traefik/releases )。该产品针对每种受支持的操作系统和架构发布。在撰写本文时,Traefik 2.2.0 是最新发布的版本(见图 1-5 )。

Traefik 微服务 API 网关教程(一)

图 1-5

trafik 发布页面

在本章的剩余部分,我们将使用 macOS 版本,但是您可以使用以下任何方法下载合适的版本。

打开 https://github.com/containous/traefik/releases ,点击释放。traefik_v2.2.0_darwin_amd64.tar.gz

对终端执行curl命令:curl -o https://github.com/containous/traefik/releases/download/v2.2.0/traefik_v2.2.0_darwin_amd64.tar.gz

解压存档:tar -zxvf traefik_v2.2.0_darwin_amd64.tar.gz

该文件夹应该包含traefik可执行文件,以及另外两个文件。

$ ls -al
total 150912
-rw-rw-r--@  1 rahulsharma  staff  551002   Mar 25 22:38 CHANGELOG.md
-rw-rw-r--@  1 rahulsharma  staff  1086     Mar 25 22:38 LICENSE.md
-rwxr-xr-x@  1 rahulsharma  staff  76706392 Mar 25 22:55 traefik


123456

单个二进制文件在跨不同平台工作时提供了简化的体验。现在让我们学习如何使用 Traefik。

trafik 命令行

Traefik 可以通过调用traefik命令来启动。该命令可以执行以下任何操作。

根据提供的配置配置 trafik

确定 trafik 版本

对 Traefik 执行运行状况检查

理解traefik命令如何支持这些行为是很重要的。在traefik命令中提供了几个参数。一旦我们到达相关的主题,你将与他们一起工作。首先,让我们通过执行以下命令来验证 Traefik 的版本。

$ ./traefik version
Version:      2.2.0
Codename:     chevrotin
Go version:   go1.14.1
Built:        2020-03-25T17:17:27Z
OS/Arch:      darwin/amd64


1234567

该输出不仅显示了 Traefik 版本,还显示了与平台相关的信息以及创建 Traefik 二进制文件的日期。一般来说,traefik命令的语法如下。

traefik [sub-command] [flags] [arguments]


12

在这个命令中,所有参数都是可选的。现在,您可以通过调用命令来配置 Traefik。请务必注意,Traefik 配置可以通过以下方式提供。

配置文件

用户指定的命令行标志

系统环境变量

它们按列出的顺序进行评估。如果未指定值,Traefik 将应用默认值。您可以在不传递这些值的情况下执行该命令。

$ ./traefik
INFO[0000] Configuration loaded from flags.


123

这个输出告诉您 Traefik 已经启动。它配置了基于标志的配置。该命令开始监听端口 80。现在让我们通过对 http://localhost/执行 cURL 来验证这一点。

$ curl -i http://localhost/
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
Date: Fri, 01 May 2020 16:16:32 GMT
Content-Length: 19

404 page not found


123456789

cURL 请求从服务器获得 404 响应。在下一章讨论入口点、路由器和服务时,我们将再次讨论配置细节。

Traefik API

Traefik 还提供了 REST API,它可以访问 Traefik 中所有可用的信息。表 1-1 描述了几个主要的终点。

表 1-1

trafik 中的 api 端点

|

端点

|

描述

|
| — | — |
| /API/版本 | 提供了有关 trafik 版本的信息 |
| /API/概述 | 提供有关 HTTP 和 TCP 的统计信息,以及启用的功能和提供程序 |
| /API/entry tips | 列出所有入口点信息。 |
| /API/http/服务 | 列出所有 HTTP 服务信息 |
| /API/http/路由器 | 列出所有 HTTP 路由器信息 |
| /API/http/中间件 | 列出所有 HTTP 中间件信息 |

api 的完整列表可在 traefik.io/v2.2/运营/API/#端点获得。默认情况下,API 是禁用的。需要通过传递适当的标志来启用它。您可以通过使用api.insecure标志启动 Traefik 来激活 API,这会将 REST API 部署为 Traefik 端点。

rahulsharma$ ./traefik -api.insecure true
INFO[0000] Configuration loaded from flags.


123

现在让我们在浏览器中查找http://localhost:8080/api/overview。输出显示从 API 返回的统计数据(见图 1-6 )。

Traefik 微服务 API 网关教程(一)

图 1-6

API 概述输出

该行为也可以通过使用TRAEFIK_API_INSECURE环境变量来实现。环境变量相当于api.insecure标志。让我们通过设置环境变量再次运行该命令。

rahulsharma$ export TRAEFIK_API_INSECURE=True
rahulsharma$ ./traefik
INFO[0000] Configuration loaded from environment variables.


1234

Note

不建议在生产系统上启用 API。API 可以公开完整的基础设施和服务细节,包括敏感信息。

前面的命令以不安全的模式部署了 Traefik API。不建议这样做。Traefik 应该通过身份验证和授权来保护。此外,API 端点应该只能在内部网络中访问,而不能暴露给公共网络。本书将在后续章节中介绍这些实践。

交通控制面板

Traefik API 开箱后带有一个仪表盘(参见图 1-7 )。仪表板仅供查看。它显示 Traefik 中配置的所有组件的状态。仪表板还显示每个部署的组件的执行情况。仪表板是一个直观的表示,运营团队可以使用它来进行监控。一旦你以一种不安全的方式启动了 Traefik,查一下http://localhost:8080/dashboard#/

Traefik 微服务 API 网关教程(一)

图 1-7

交通控制面板

仪表板显示 TCP 和 UDP 服务。基于 HTTP 的应用有两个监听端口。仪表板还捕获每个服务的错误率。

摘要

在本章中,您了解了微服务的采用如何改变了网关的要求。我们讨论了网关组件的各种预期行为。像 Nginx 和 HAProxy 这样的成熟市场产品已经尝试适应这些功能。但是这些产品已经无法提供所有需求的一流支持。Traefik 就是为了满足这些需求而构建的。有多种方法可以配置 Traefik。可以从文件、参数或环境变量传递配置。对于所有未指定的配置,它都有合理的默认值。最后,您了解了 Traefik 中可用的 API 和仪表板。既然我们已经部署了 Traefik,让我们在下一章中配置它来处理一些端点。

二、配置 Traefik

在上一章中,您了解了微服务的采用如何改变了对网关组件的行为要求。Traefik 就是为了满足所有这些需求而构建的。配置 Traefik 有多种方法;配置可以通过文件、参数或环境变量传递。对于所有未指定的配置,它都有合理的默认值。您还了解了 Traefik 中可用的 API 和仪表板。在本章中,让我们在您离开的地方继续深入研究配置 Traefik 以公开几个端点的各种方法。

本章涵盖了路由的基础知识。它讨论了路由中使用的各种组件。我们将介绍一个贯穿本章的小示例应用。Traefik 路由配置用于向外界公开该应用。在本章中,您将尝试手动配置 Traefik 来公开一个简单的服务。在后面的章节中,您可以在此基础上利用 Traefik 的自动配置功能。

配置主题

让我们介绍以下 Traefik 配置,以在 Traefik 网关上公开一个示例应用。

入口点

提供者

路由器

规则

中间件

服务

这些配置件之间的相互作用如图 2-1 所示。我们会在您前进的过程中详细描述每一项。

Traefik 微服务 API 网关教程(一)

图 2-1

trafik 配置架构

示例 Web 服务简介

在继续进行 Traefik 配置之前,让我们看一下要在 Traefik 中公开的示例应用。在本章中,我们使用这个简单的 web API 来通过 Traefik 提供流量服务。

这个简单的服务是用 Go 编写的(如清单 2-1 所示),它监听 HTTP 端口 9080。它在默认路径“/”上返回一个“Hello World”字符串。

main.go
package main

import (
"fmt"
"log"
"net/http"
)

func main() {
http.HandleFunc("/", handler)
log.Println("Server listening on port 9080...")
log.Fatal(http.ListenAndServe(":9080", nil))
}

func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World")
}

Listing 2-1Simple Web API Written in Go



Traefik 微服务 API 网关教程(一)123456789101112131415161718192021

Note

您需要在系统上安装 Go 1.1.3 来运行此示例。然而,除此之外,它不需要任何其他特殊要求。关于 Go 安装和执行的讨论超出了本书的范围;但是,官方的 Go 文档非常全面。

在上一章中,您看到了如何在机器上以独立模式安装和设置 Traefik。在这里,您使用 Traefik CLI。本章所有的例子都是在 macOS 上运行的。但是,如果您安装了 Go 和 Traefik CLI,您应该能够很容易地理解。

当您运行 Go 服务时,您会看到清单 2-2 中的控制台消息。

➜ hello-world-service> go run main.go
2020/05/02 20:34:26 Server listening on port 9080...

Listing 2-2Running the Go web API


12345

当您在浏览器中打开该 URL 时,您会看到以下内容(参见图 2-2 )。

Traefik 微服务 API 网关教程(一)

图 2-2

打开 URL http://localhost:9080/的浏览器截图

您会在命令行上看到下面的curl(参见清单 2-3 )。

➜ hello-world-service> curl localhost:9080
Hello, World

Listing 2-3Testing the API endpoint with curl


12345

在本章的其余部分,我们将运行这个示例应用并配置 Traefik 来公开这个应用的端点。在此过程中,我们将探索各种 Traefik 配置。

Traefik 微服务 API 网关教程(一)

图 2-3

在 Traefik 上公开“Hello World”Go 服务

Note

对于本章的其余部分,术语上游下游描述了与消息流相关的方向要求:所有消息从上游流向下游。术语入站出站描述了与请求路由相关的方向要求:入站意味着朝向原始服务器,而出站意味着朝向用户代理。这符合 HTTP 规范 RFC 7230 第 2.3 节( https://tools.ietf.org/html/rfc7230#section-2.3 )。

流量配置

Traefik 有两种方式提供配置:静态和动态(见图 2-4 )。

Traefik 微服务 API 网关教程(一)

图 2-4

Traefik 中的不同配置类型

静态配置在启动时通过以下机制提供。一旦 Traefik 启动,它就不会改变。

文件

硬币指示器 (coin-levelindicator 的缩写)命令行界面(Command Line Interface for batch scripting)

环境变量

对于静态配置,首先通过 CLI 配置 Traefik,然后是环境变量,最后是静态文件配置。

您可以在静态配置(文件或 CLI)中定义入口点。Entrypoints 是 Traefik 侦听传入 TCP/UDP 流量的端口的端口定义。

提供者是难题的另一部分,必须在静态启动配置中指定。提供商赋予 Traefik 强大的功能。动态配置(如路由器和服务)在运行时被更改和刷新,并通过提供者进行配置。Traefik 可以通过一组预配置的提供者与您的服务目录对话,而不必手动配置每个下游服务。有 Docker、Kubernetes 和 Consul 的提供者,也有诸如 files 之类的存储和诸如 etcd 之类的键值存储。这允许 Traefik 自动在边缘公开下游服务。在本章中,您将通过手动使用 FileProvider 来指定动态配置。在后面的章节中,您将深入了解 Traefik 如何与其他提供者集成,比如 Consul 和 Kubernetes。

入口点

Traefik 配置定义了一组侦听传入请求的入口点(或端口号)。这些入口点可以服务于 HTTP、TLS、gRPC 或 TCP 流量。您可以为希望通过 Traefik edge gateway 公开的每个后端服务定义一个入口点。入口点定义了地址、协议、报头、传输细节(如超时)和 TLS 细节的底层细节。

在开始定义入口点之前,让我们先回顾一下您希望如何运行 Traefik,并确定您如何在运行时观察已定义的配置。您可以从命令行启动 Traefik,无需任何其他配置。为了在后续步骤中观察配置的结果,您还可以通过传递'--api.dashboard=true'标志来启用 Traefik web 仪表板。

使用 cli 参数启动流量
➜  ~ ./traefik --api.dashboard=true --api.insecure=true
INFO[0000] Configuration loaded from flags.

Listing 2-4Start Traefik with command line arguments


12345

清单 2-4 在本地主机的端口 8080 上启动 Traefik,Traefik 仪表板以默认配置显示。仪表板位于/api/dashboard/ route 下。

默认情况下,Traefik 建议在安全模式下公开仪表板;因为您现在只想看到仪表板,而不需要太多的配置,所以您用'--api.insecure=true'标志在不安全模式下启动它。请注意,对于生产用例,不建议这样做。

正如您在图 2-5 中看到的,Traefik 仪表板有一组区域,允许您观察在 Traefik 中配置和启用的所有功能。目前,Traefik 实例中只公开了默认配置。

Traefik 微服务 API 网关教程(一)

图 2-5

http://localhost:8080/打开 Traefik 仪表板的屏幕截图

默认情况下定义了两个入口点。

端口 80 上侦听的默认 HTTP 入口点

一个名为 Traefik 的入口点侦听端口 8080,它提供对仪表板的访问

仪表板不通过任何特殊机制公开。Traefik 使用标准的入口点配置公开它。在入口点下面,您可以看到按协议(HTTP、TCP 和 UDP)分类的路由器、中间件和服务。随着您向前移动,您可以深入查看您在控制面板上看到的这些进一步的部分。

如您所见,Traefik 定义了许多入口点、路由器、中间件和服务。下一步是使用这些相同的机制公开下游服务。

如您所见,当您启用 web 仪表板时,默认情况下 Traefik 已经监听端口 80(默认 HTTP)和 8080(仪表板 HTTP)。

让我们定义自己的入口点来公开已经通过 Traefik 讨论过的“Hello World”Go 服务。

首先,您需要定义一个入口点。这是在静态配置中启动时使用以下方法之一完成的。

CLI 参数

环境变量

当前目录下的配置文件 traefik.yml

使用 cli 定义的入口点启动流量
➜ ~ ./traefik --api.dashboard=true --api.insecure=true  --entryPoints.web.address=:80
INFO[0000] Configuration loaded from flags.

Listing 2-5Traefik entrypoint defined through command line argument


12345

清单 2-5 定义了一个名为 web 的入口点,它监听端口 80。这将覆盖您之前在端口 80 上看到的默认 HTTP 入口点(参见图 2-6 )。

Traefik 微服务 API 网关教程(一)

图 2-6

Traefik 仪表板中的入口点于http://localhost:8080/打开

当您尝试从 cURL 访问本地主机上的这个端口时,您会看到清单 2-6 中的输出。Traefik 正在侦听此端口,但是后端还没有连接到此端口的服务。

➜ hello-world-service> curl localhost
404 page not found

Listing 2-6Testing the localhost 80 port with curl


12345

我们使用命令行参数定义静态配置,成功地公开了入口点。接下来,让我们尝试使用环境变量做同样的事情。

使用环境变量中定义的入口点启动 trafik

您在终端中执行以下命令来启动 Traefik,在端口 80 上公开一个名为 web 的入口点(参见清单 2-7 )。

➜ traefik-config> export TRAEFIK_API_DASHBOARD=true
➜ traefik-config> export TRAEFIK_API_INSECURE=true
➜ traefik-config> export TRAEFIK_ENTRYPOINTS_WEB_ADDRESS=":80"
➜ traefik-config> traefik
INFO[0000] Configuration loaded from environment variables.

Listing 2-7Starting Traefik with entrypoint configuration in environment variables


12345678

当您在浏览器中访问该端点时,您会看到与之前相同的结果(参见图 2-7 )。

Traefik 微服务 API 网关教程(一)

图 2-7

还没有后端服务连接到端口 80

命令行参数和环境变量可以随意使用;但是,对于本章的其余部分,您将通过文件提供所有配置。这是配置 Traefik 的推荐方式,因为文件配置简单,不容易出现打字错误和错误。在源代码控制中也可以很容易地跟踪它,支持更多的 GitOps 模型。接下来,让我们看看如何实现这一点。

用当前目录中的配置文件 Traefik.yml 定义的入口点

Traefik 静态配置文件可以通过多种方式提供。

当前目录中的 Traefik.yml 文件

Traefik.yml file in $HOME/.config

作为命令行参数传入 CLI 的文件的位置

--configFile=path/to/traefik-static-config.yml

为简单起见,在本章的剩余部分,我们将 Traefik 配置文件限制在当前目录中。

TOML 诉 YAML 案

在 Traefik 中有两种定义文件配置的竞争格式:TOML 和 YAML。

虽然 Traefik 团队更喜欢 TOML,但本章中的所有配置示例都在 YAML。TOML 是一种不太知名和晦涩的格式,而 YAML 在各种平台中得到广泛支持,并且是 Docker 和 Kubernetes 生态系统的默认声明性状态配置格式。不要学习定义简单配置的新格式,让我们坚持使用 YAML 来满足所有需求。在 Traefik 配置的所有问题上,YAML 与 TOML 拥有同等的功能。

当前目录下的 traefik.yml 文件指定了入口点,如清单 2-8 所示。您还可以在此文件中添加配置来启用仪表板,而不是在命令行中启用它。

# Entrypoints have to be defined as static configuration in traefik.yml
entryPoints:
  web:
   address: ":80"

api:
  insecure: true
  dashboard: true

Listing 2-8Traefik Static YAML Configuration


1234567891011

为了比较,在清单 2-9 中定义了 TOML 格式的相同配置。你不用这个;它只是被包括在内以供参考。

# Entrypoints have to be defined as static configuration in traefik.yml
[entryPoints]
  [entryPoints.web]
  address = ":80"

[api]
insecure = true
dashboard = true

Listing 2-9Traefik Static TOML Configuration


1234567891011

现在让我们用静态 YAML 配置启动 Traefik。

➜ traefik-config> ./traefik
INFO[0000] Configuration loaded from file: /Users/akshay/traefik-book/traefik-config/traefik.yml

Listing 2-10Startup Traefik with static file configuration


12345

当您启动 Traefik 时(参见清单 2-10 ,它会自动提取当前目录中的 traefik.yml 文件。这样做的结果与前两个小节中看到的结果相同。

路由器

对于 Traefik 公开的每个入口点,必须连接相应的路由器来进一步路由流量。路由器由两部分组成。

一套规则。入口点上的每个传入请求都与这组规则相匹配。

一套中间件。规则匹配的每个请求都可以使用相应的中间件进行转换。中间件是执行认证和速率限制的所有专用网关功能的地方。

既然入口点已经公开,那么使用路由器配置将后端 Go API 连接到入口点。让我们首先来看看 Traefik 仪表板中定义的默认路由器。

默认情况下定义了两个 HTTP 路由器。当您点击主页上路由器部分的“浏览->”时,您会看到如图 2-8 所示的内容。

Traefik 微服务 API 网关教程(一)

图 2-8

深入了解默认 HTTP 路由器。

在“/api”下定义的第一个路由是名为 api@internal 的默认父路由。

“/”下的第二条路线是名为“dashboard@internal”的仪表板路线。

您可以进一步深入这些路由器并检查它们的详细信息(参见图 2-9 和 2-10 )。这些路由分别服务于 API 和仪表板的流量。

Traefik 微服务 API 网关教程(一)

图 2-10

仪表板@内部 HTTP 路由器的详细视图

Traefik 微服务 API 网关教程(一)

图 2-9

api @内部 HTTP 路由器的详细视图

您必须定义 HTTP 路由器,以便在 Traefik 仪表板上显示类似的内容。从现在开始,您将利用 FileProvider 来指定动态配置。Traefik 可以通过支持的提供者与您平台的服务发现机制对话。对于这个简单的用例,您在一个文件中指定所有的配置,这很容易被 Traefik 支持。路由器、中间件和服务的所有配置都是通过动态配置指定的。有两种方法可以指定 FileProvider 配置。

通过文件名指定的单个文件

配置文件的整个目录,这是生产中推荐的方法,因为您可以将各种配置分成多个文件

在清单 2-11 中,您在存放所有动态配置的当前目录中指定了一个文件名。然后 Traefik 监视该文件是否有任何更改,并且在 Traefik 中自动刷新配置。

# Entrypoints have to be defined as static configuration in traefik.yml
entryPoints:
  web:
   address: ":80"

providers:
  file:
    filename: "traefik-dynamic-conf.yml"
    watch: true

api:
  insecure: true
  dashboard: true

Listing 2-11Dynamic configuration file name defined in static cofiguration



Traefik 微服务 API 网关教程(一)12345678910111213141516
路由器规则

在 traefik-dynamic-conf.yml 动态配置文件中,首先定义 HTTP 路由器及其路由规则(参见清单 2-12 )。

http:
  routers:
    router0:
      entryPoints:
      - web
      service: hello-world
      rule: Path(`/hello-world`)

Listing 2-12traefik-dynamic-conf.yml dynamic configuration file


12345678910

一旦所有的配置都设置好了,您就可以在同一个目录中运行 Traefik CLI(参见清单 2-13 )。

➜ traefik-config> ./traefik
INFO[0000] Configuration loaded from file: /Users/akshay/code/k8s/traefik-book/traefik-config/traefik.yml
ERRO[2020-05-13T09:22:17+05:30] the service "hello-world@file" does not exist entryPointName=web routerName=router0@file
ERRO[2020-05-13T09:22:18+05:30] the service "hello-world@file" does not exist entryPointName=web routerName=router0@file

Listing 2-13Running Traefik with router rule in dynamic configuration file


1234567

您定义了一个规则来将请求路径(/hello-world)匹配到一个尚未配置的后端服务,因此 Traefik 在启动时会抛出一个控制台错误。您会在仪表板中看到类似的错误(参见图 2-11 )。HTTP 路由器部分显示一个错误。同样有趣的是页面底部的 Providers 部分,它现在有一个 FileProvider 条目。

Traefik 微服务 API 网关教程(一)

图 2-11

带有 HTTP 路由器的仪表板视图

路由器的下一块要配置的应该是中间件;然而,我们将暂时跳过它,稍后再回来。首先,您配置服务后端并获得端到端的通信。

服务

服务定义了请求必须被路由到的实际目标。它们是您希望通过 Traefik 公开的实际 API 端点。请注意,服务类型必须与路由器类型匹配(例如,HTTP 路由器只能连接到 HTTP 服务)。在匹配和转换请求之后,路由器将它们转发到您希望公开的服务。

在定义服务之前,让我们看看 Traefik 仪表板中配置的默认服务。定义了三种 HTTP 服务。当你点击“服务”部分的“浏览->”时,你会看到如图 2-12 所示的内容。

Traefik 微服务 API 网关教程(一)

图 2-12

仪表板默认服务

您可以进一步深入这些服务。api@internal service 处理 Traefik API 请求(参见图 2-13 )。

Traefik 微服务 API 网关教程(一)

图 2-13

仪表板默认服务 api@internal

仪表板@内部服务(见图 2-14 )处理仪表板请求。当启用 API 和仪表板时,Traefik 会隐式注册这两个服务。

Traefik 微服务 API 网关教程(一)

图 2-15

仪表板默认服务 noop@internal

Traefik 微服务 API 网关教程(一)

图 2-14

仪表板默认服务仪表板@内部

还有一个 noop@internal(如图 2-15 所示)用于重定向。

清单 2-14 在 traefik-dynamic-conf.yml 中定义了一个后端服务,以满足上一节中设置的规则,将流量路由到 Go“Hello World”服务。请记住,该服务运行在本地主机端口 9080 上。

# Dynamic configuration
http:
  routers:
    router0:
      entryPoints:
      - web
      service: hello-world
      rule: Path(`/hello-world`)

  services:
    hello-world:
      loadBalancer:
        servers:
        - url: http://localhost:9080/

Listing 2-14Service configuration in dynamic configuration file



Traefik 微服务 API 网关教程(一)1234567891011121314151617

您现在启动 Traefik 并尝试在子路径’/hello-world ‘上的 Traefik 端口 80 上访问 Go 服务。当您使用 curl 时,您会看到清单 2-15 中的输出。

➜  traefik-config> curl localhost/hello-world
Hello, World

Listing 2-15Access service endpoint on localhost with curl


12345

现在,您已经成功地在 Traefik 的端口 80 上公开了后端服务。让我们看看 Traefik 仪表板中显示了什么。您可以在主仪表板页面上看到 HTTP 路由器、服务和中间件(参见图 2-16 )。

Traefik 微服务 API 网关教程(一)

图 2-16

路由器和服务已配置

您可以深入到 HTTP 服务页面,在这里您会看到 hello-world 服务的一个新条目(参见图 2-17 )。

Traefik 微服务 API 网关教程(一)

图 2-17

向下钻取到配置的 HTTP 服务。

然后,您可以深入到 hello-world 服务以查看其详细信息(参见图 2-18 )。这也显示了 Servers 部分中的后端服务 URL。

Traefik 微服务 API 网关教程(一)

图 2-18

细化到已配置的 Hello World 文件 HTTP 服务

然后导航回主仪表板页面(参见图 2-19 )。

Traefik 微服务 API 网关教程(一)

图 2-19

配置中间件之前的 trafik 仪表板

从这里,您可以深入到 HTTP 路由器(参见图 2-20 )。

Traefik 微服务 API 网关教程(一)

图 2-20

深入查看已配置的 HTTP 路由器

然后您可以深入到 HTTP 路由器,它将 hello-world 服务附加到 web 入口点(参见图 2-21 )。

Traefik 微服务 API 网关教程(一)

图 2-21

连接到 hello-world 服务的 HTTP 路由器

中间件

现在,您已经成功地在 Traefik 中公开了第一个服务,让我们回头向路由器添加一个中间件,以添加额外的 API 网关功能。

默认定义了两个 HTTP 中间件。当你点击中间件部分的“浏览->”时,你会看到如图 2-22 所示的内容。

Traefik 微服务 API 网关教程(一)

图 2-22

默认中间件

您可以轻松地向下导航,查看隐式定义的中间件的详细信息。它们与仪表板一起自动启用,对于 URL 模式的特殊处理非常有用(参见图 2-23 和 2-24 )。这样,即使内部 Traefik 服务也遵循与用户定义的服务相同的配置机制。

Traefik 微服务 API 网关教程(一)

图 2-24

默认 stripprefix 中间件

Traefik 微服务 API 网关教程(一)

图 2-23

默认仪表板重定向中间件

对于用例,您定义内置的基本身份验证中间件来保护 Hello World API。

让我们从使用htpasswd命令行工具生成用户名-密码对开始。这是 Traefik 文档中基本验证页面上推荐的方法。如果您的系统上没有此工具,您可以使用任何其他兼容的密码哈希实用程序。你用 admin 作为用户名,用 admin@123 作为密码。用户名可以指定为纯文本,但密码必须以 MD5、SH1 或 BCrypt 格式散列提供(参见清单 2-16 )。

➜  traefik-config> htpasswd -nb admin admin@123
admin:$apr1$JsindKAS$zCWAvabJOgQvI.Dd3zjtE.

Listing 2-16Generate username password pair for authentication


12345

您将这个值复制到 Traefik 动态配置中(参见清单 2-17 )。

# Dynamic configuration
http:
  routers:
    router0:
      entryPoints:
      - web
      middlewares:
      - basic-auth
      service: hello-world
      rule: Path(`/hello-world`)

  services:
    hello-world:
      loadBalancer:
        servers:
        - url: "http://localhost:9080/"

# Declaring the basic auth middleware with the user credentials
  middlewares:
    basic-auth:
      basicAuth:
        users:
          - "admin:$apr1$JsindKAS$zCWAvabJOgQvI.Dd3zjtE."

Listing 2-17Basic auth middleware configuration in dynamic configuration file



Traefik 微服务 API 网关教程(一)1234567891011121314151617181920212223242526

现在让我们试试浏览器中的/hello-world 端点。您会在浏览器中看到一个基本的授权提示,要求您输入用户名和密码(参见图 2-25 )。输入这些之后,你可以看到 hello-world 服务的响应(见图 2-26 )。

Traefik 微服务 API 网关教程(一)

图 2-26

最终认证 Hello World

Traefik 微服务 API 网关教程(一)

图 2-25

浏览器基本身份验证

让我们在命令行上用curl做同样的尝试(参见清单 2-18 )。

➜  traefik-config> curl localhost/hello-world
401 Unauthorized
➜  traefik-config> curl -u admin localhost/hello-world
Enter host password for user 'admin':
Hello, World

Listing 2-18Testing basic auth middleware applied on localhost endpoint


12345678

现在这已经可以工作了,让我们最后看一下 Traefik 仪表板中的配置。你可以看到主页上的 HTTP 中间件平铺显示了另一个中间件(见图 2-27 )。

Traefik 微服务 API 网关教程(一)

图 2-27

最终配置

您可以深入到中间件页面,在那里您可以查看已定义的basic-auth@file中间件。Traefik 会自动指定名称。你还可以看到其他隐式中间件(见图 2-28 )。

Traefik 微服务 API 网关教程(一)

图 2-28

向下钻取到已配置的 HTTP 中间件

然后进一步深入查看中间件的配置。您还可以看到您为认证定义的用户(参见图 2-29 )。

Traefik 微服务 API 网关教程(一)

图 2-29

已配置的基本身份验证中间件

在该页面中,您可以直接导航到该中间件的关联路由器并查看其详细信息(参见图 2-30 )。

Traefik 微服务 API 网关教程(一)

图 2-30

连接路由器、服务和中间件

摘要

在本章中,您了解了 Traefik 的基本配置,以及如何手动配置 Traefik 以在特定端口上公开 API,并将流量路由到相应的后端服务。您了解了配置 Traefik 的各种方法,并从文件、CLI 参数和环境变量传递了配置。您还深入研究了 Traefik 仪表板,以了解如何使用它来理解配置。

到目前为止,您只是简单地将流量路由到一个后备服务实例。在下一章中,您将深入了解 Traefik 针对 HTTP 和 TCP 流量的负载平衡器功能。

三、负载平衡

缩放是应用设计的一个重要原则。扩展不仅提供应用性能,而且,如果操作得当,扩展还提供应用可用性和容错能力。开发人员必须注意有效地扩展应用。不可能是后发展思想。之前,您已经了解到,通过向正在运行的实例分配更多资源,可以垂直扩展应用。单片应用遵循这一原则。第一章解释了这是一种无效的方法。

此外,为了提供可用性,我们通常选择热-冷部署模式。这导致效率低下,因为冷实例是备用实例。它仅在主应用实例关闭时激活。

另一方面,水平伸缩允许您同时运行应用的多个实例。这些实例中的每一个都可以在最低要求的硬件上运行,并为用户请求提供服务。这是在云环境中部署应用的首选机制。它通过使用热-热部署极大地提高了应用的可用性(参见图 3-1 )。

Traefik 微服务 API 网关教程(一)

图 3-1

部署类型

一旦一个应用有多个实例,就必须配置一个负载平衡器来有效地使用它们。像 Traefik 这样的负载平衡器应用可以在开放系统互连(OSI)模型的第 4 层和第 7 层运行。在第 4 层,它充当 TCP/UDP 代理。它基于主机和端口信息工作。在第 7 层,负载平衡器查看许多属性(例如,HTTP 负载平衡可以基于主机、端口、请求路径或请求头来完成)。因此,Traefik 可以在两层执行负载平衡。

在第二章中,我们在 Traefik 中配置了 HTTP 服务。在本章中,我们将配置 HTTP 服务的负载平衡。Traefik 还提供 TCP 和 UDP 功能。我们也和他们一起工作。

HTTP 负载平衡器

为了有效地使用水平伸缩,我们需要一个负载平衡器。负载平衡器配置有应用的所有实例。当负载平衡器收到请求时,它必须将请求委派给一个已配置的实例。一些负载平衡算法可以改变请求处理的行为。每种算法都有优点和缺点,在某些情况下比其他情况下效果更好。

在前一章中,我们使用文件类型提供程序配置了 Traefik。我们为端口 80 创建了一个入口点。我们还添加了routersservices来处理传入的请求。服务配置指向应用的位置。负载平衡算法也在服务级别进行管理。一些服务可以使用特定的算法,而其他服务可以使用不同的算法。当我们查看服务配置时,它由以下块组成。

服务:定义服务器的逻辑分组,以便可以应用公共属性

服务器:定义应用的实际位置

这两个模块中的任何一个都可以在 Traefik 中配置负载平衡。在下一节中,我们将配置不同的属性来学习完整的行为。

一系列

循环调度(RR)是最简单的负载分配算法之一。该算法将请求平均分配给每个可用的实例(见图 3-2 )。它以循环的方式执行操作,没有任何优先级或偏好的概念。当服务器具有大致相同的计算能力时,循环负载平衡效果最佳。

Traefik 微服务 API 网关教程(一)

图 3-2

请求分发

在图 3-2 中,应用中有四台服务器。该图描述了算法如何在它们之间分配传入的请求。更进一步,我们需要一个 HTTP 应用来配置循环调度。在剩下的部分中,我们将使用一个访问者日志记录应用。该应用具有以下行为。

添加客人姓名

列出最新的客人姓名

显示所有客人姓名

应用部署在多个机器上。每个应用实例都有一个名称,显示在 UI 中(见图 3-3 )。UI 帮助确定哪个实例服务于用户请求。

Traefik 微服务 API 网关教程(一)

图 3-3

访问者日志屏幕

Traefik 服务配置由一个service和一个server模块组成。使用server模块配置循环调度。

http :
  routers :
    guest-router :
      entryPoints :
      - web

      rule : Host(`localhost`)
      service : guestbook-service

  services :
    guestbook-service :
      loadBalancer :
        servers :
        - url  : "http://192.168.1.10:9090/"
        - url  : "http://192.168.1.11:9191/"



Traefik 微服务 API 网关教程(一)12345678910111213141516

下面是在前面的代码中配置的。

localhost域配置了请求路由。该规则匹配所有传入的请求。在前一章中,您看到了验证请求 URL 位置的路径规则。这里我们基于主机名而不是请求路径来验证请求。Traefik 使用guestbook-service配置来处理请求。

server部分列出了所有可用实例的 URL。它被配置为一个值列表。

让我们运行 Traefik 配置并在浏览器中访问 http://localhost(见图 3-4 )。服务配置也可在 Traefik 仪表板上获得(参见图 3-5 )。它显示服务的完整状态。

Traefik 微服务 API 网关教程(一)

图 3-5

循环赛的 trafik 仪表板

Traefik 微服务 API 网关教程(一)

图 3-4

访问者的多个实例

如果您刷新浏览器几次,您会看到它是由两个实例提供的。我们可以在应用中添加一些条目。这些数据保存在底层数据库中。随后在两种情况下都会显示数据。简而言之,应用没有保持任何状态。所有状态都保存在数据库中。当整个应用是无状态的,就像一个访问者日志时,经典的循环算法就足够了。

另一方面,应用可以是有状态的。这意味着每个应用都有一些本地数据。在 web 应用中,状态是使用 HTTP 会话来维护的。为每个用户创建一个会话。会话是内存中的存储。它仍然与用户相关联。会话中可以存储的内容没有限制。应用开发人员可以存储以用户为中心的数据,如 id、最新事务和 UI 样式。当请求从一个实例路由到另一个实例时,会话信息会丢失。

粘性会话

会话粘性确保会话期间来自用户的所有请求都被发送到同一个实例。负载平衡器通过将 cookies 保存在用户请求中来实现这一点。负载平衡器为第一个用户请求创建一个 cookie。然后,它为每个后续请求引用该 cookie。在 Traefik 中,cookie 是在loadBalancer级别配置的。

# Removed for Brevity

  services :
    guestbook-service :
      loadBalancer :
        sticky :
          cookie : {}
        servers :
        - url  : "http://192.168.1.10:9090/"
        - url  : "http://192.168.1.9:9191/"


1234567891011

在代码中,我们为已定义的guest-service loadBalancer添加了sticky属性。更改之后,请求不能再在两个应用实例之间切换。它仅由一个实例提供服务。我们可以通过在浏览器中查找 cookie 细节来验证实例细节(参见图 3-6 )。

Traefik 微服务 API 网关教程(一)

图 3-6

浏览器 cookie

配置添加了一个具有生成名称的 cookie。sticky记录提供了以下可选属性,这些属性可以配置生成的 cookie 的行为。

Name:指定 cookie 名称,而不是生成的名称。

HttpOnly:该标志通过客户端 JavaScript 减少 cookie 访问。

安全:该属性通过 HTTPS 连接发送 cookie。

SameSite:该属性限制相同站点上下文中的 cookies。上下文边界由属性的各种值定义。

Traefik 仪表板还显示更新后的配置(见图 3-7 )。

Traefik 微服务 API 网关教程(一)

图 3-7

粘性会话的流量仪表板

cookie 指向处理原始请求的服务器位置。必须配置 Traefik 来监控所有这些应用服务器。如果 cookie 中指定的服务器不可用,请求将被转发到新的服务器。Traefik 用新服务器的详细信息更新 cookie。这是通过为实例配置健康检查来实现的。

Note

使用经典循环路由时,Traefik 会保持不正常的服务器,直到配置了应用健康检查。

健康检查

为了有效地工作,负载平衡器应该确定哪些后端服务器运行良好。这是通过定期发送验证实例状态的请求来实现的。这些请求被称为健康检查。Traefik 仅将请求路由到健康的实例。它跟踪所有活动的实例。Traefik 在确定实例不正常时,会从活动实例池中删除该实例。它一直监视不健康的实例。实例恢复后,Traefik 会将其添加回活动实例池。只有对运行状况检查请求的响应才能控制实例的状态。除 2XX 和 3XX 之外的响应被视为错误(参见图 3-8 )。

Traefik 微服务 API 网关教程(一)

图 3-8

应用错误

Traefik 允许您使用服务的健康检查属性来配置服务器健康。

  services :
    guestbook-service :
        servers :
        - url  : "http://192.168.1.10:9090/"
        - url  : "http://192.168.1.11:9191/"
        healthCheck:
          path: /
          interval: "10s"
          timeout: "1s"


12345678910

关于前面的代码,可以说如下。

/路径是为运行状况查找而配置的。

每 10 秒执行一次查找。如果服务器改变其状态,最多 10 秒后就会知道。

超时配置 HTTP 请求超时的时间间隔

要测试配置,您可以停止其中一个服务器,或者从应用发出错误响应(5XX,4XX)。这些运行状况检查也可以在 Traefik 仪表板的服务选项卡下看到。(参见图 3-9 )

Traefik 微服务 API 网关教程(一)

图 3-9

具有应用运行状况的 trafik 仪表板

使用粘性会话时,如果服务器变得不可用,Traefik 会重置 cookie。然后,请求被路由到一个健康的服务器。Traefik 用新实例的详细信息更新 cookie。所有进一步的请求都被路由到新的服务器。

加权循环赛

加权循环法(WRR)考虑应用实例的资源容量(见图 3-10 )。硬件规格高于其他实例的实例可以处理更多的请求。这是通过给每个实例分配一个权重来实现的。没有确定权重的具体标准。这是留给系统管理员的。具有较高规格的节点被分配更多数量的请求。图 3-10 中的图表显示了 WRR 的请求分布。

Traefik 微服务 API 网关教程(一)

图 3-10

请求的加权分布

到目前为止,您已经了解了权重被分配给应用的不同实例。但是在 Traefik 中,这是在服务级别而不是服务器级别表示的。在上一节中,我们配置了loadbalancer类型的服务。该服务拥有每台服务器的位置。但是要使用 WRR,我们需要将服务器逻辑上划分为不同的负载能力。这些容量服务实例中的每一个都被分组到一个具有相关权重的weighted服务实例中(参见图 3-11 )。

Traefik 微服务 API 网关教程(一)

图 3-11

加权服务层次结构

# Removed for Brevity

   services :
    guestbook-service :
      weighted:
        services:
        - name: guestv1
          weight: 3
        - name: guestv2
          weight: 1

    guestv1 :
      loadBalancer :
        servers :
        - url  : "http://192.168.1.10:9090/"  -- host 1
        - url  : "http://192.168.1.11:9191/"  -- host 2

    guestv2 :
      loadBalancer :
        servers :
        - url  : "http://192.168.1.12:9292/"  -- Host 3



Traefik 微服务 API 网关教程(一)12345678910111213141516171819202122

关于前面的代码,可以说如下。

上述应用有三台主机。主机 1 和主机 2 组合在一起。

guestv1已定义的分组主机配置。guestv2为主机定义配置三个实例。

guestbook-service以 3:1 的比率配置两个逻辑组。Traefik 每隔四个请求就向 h3 发送一次,而其余的请求以循环方式在 host2 和 host3 之间分配。

您可以在图 3-12 所示的 Traefik 仪表板中看到加权分布。

Traefik 微服务 API 网关教程(一)

图 3-12

加权服务

加权服务没有运行状况检查。加权服务的健康状况取决于为底层服务配置的健康状况。

粘性会话

在上一节中,我们启用了粘性会话来将用户绑定到服务器。但是当处理加权服务时,向loadbalancer服务添加粘性属性是不够的。权重服务无法从 cookie 中识别实例详细信息。为此,我们必须在weighted服务级别配置一个 cookie。总之,会话粘性在服务层级的所有级别上都得到维护。因此,我们需要在加权服务级别和负载平衡器级别添加一个 cookie。

  services :
    guestbook-service :
      weighted:
        services:
        - name: guestv1
          weight: 3
        - name: guestv2
          weight: 1
        sticky:
          cookie:
            httpOnly: true

    guestv1 :
      loadBalancer :
        sticky:
          cookie:
            httpOnly: true
        servers :
        - url  : "http://192.168.1.10:9090/"
        - url  : "http://192.168.1.9:9191/"

    guestv2 :
      loadBalancer :
        servers :
        - url  : "http://192.168.1.11:9292/"



Traefik 微服务 API 网关教程(一)1234567891011121314151617181920212223242526

关于前面的代码,可以说如下。

它通过添加 sticky 属性为guestbook-service启用会话粘性。

它通过添加 sticky 属性为guestbookv1启用会话粘性。

配置添加了一个具有生成名称的 cookie。sticky记录具有可选属性,可以配置生成的 cookies 的行为。我们可以在浏览器 cookie 控制台中验证这些属性(参见图 3-13 )。配置的 cookie 细节也可以在 Traefik 仪表板上看到(参见图 3-14 )。

Traefik 微服务 API 网关教程(一)

图 3-14

加权服务的粘性会话

Traefik 微服务 API 网关教程(一)

图 3-13

所有服务的浏览器 cookies

Note

Traefik 还支持动态请求路由,其中对每个请求进行权重评估。但是该功能在 1 中可用。x 而不在 2.X 中。

反映

流量阴影或镜像是一种部署模式,其中生产流量被复制并发送到两个地方。原始的生产服务器获得实际的请求,并将其复制到测试环境中。这个过程有助于验证应用新版本中的回归问题。如果测试版本具有相同的请求 URL 和参数,那么镜像可以验证新版本是否尽可能接近无错误。

流量镜像通常是异步完成的。这确保了原始请求处理不会受到任何影响。此外,所有镜像请求都是一次性的。总之,来自镜像的响应被忽略。在任何情况下,它都不会传播回客户端。

按照惯例,我们不会将所有请求复制到镜像服务。如果这样做,它将需要一个可与生产相媲美的测试基础设施。因此,只有一定比例的请求被复制到镜像服务。Traefik 将镜像服务配置为不同类型的服务。它并不限制你只有一个镜像服务。我们可以根据需要添加任意多的镜像服务。我们只需要像在 WRR 那样建立一个服务体系。

services :
    guestbook-service :
      mirroring:
        service: guestv1
        mirrors:
        - name: guestv2
          percent: 10

    guestv1 :
      loadBalancer :
        sticky:
          cookie:
        servers :
        - url  : "http://localhost:9090/"
        healthCheck:
          scheme : http
          path: /
          interval: "10s"
          timeout: "1s"

    guestv2 :
      loadBalancer :
        servers :
        - url  : "http://localhost:9191/"
        healthCheck:
          scheme : http
          path: /
          interval: "10s"
          timeout: "1s"



Traefik 微服务 API 网关教程(一)123456789101112131415161718192021222324252627282930

在代码中,我们做了以下工作来为guest-service创建一个镜像。

顶级服务(来宾服务)被定义为由两个不同的服务组成的复合服务。

mirroring属性表明当前服务是镜像服务。我们只添加了一个镜像服务。

guestv2形容镜子。它只收到原始请求的 10%。

接下来,我们定义两个loadBalancer服务。

最后,我们为每个应用添加了healthCheck。但是服务的健康来自底层的原始生产服务。镜像的运行状况对原始服务的运行状况没有影响。配置的镜像服务也显示在 Traefik 仪表板的服务视图上(见图 3-15 )。

Traefik 微服务 API 网关教程(一)

图 3-15

镜像服务

除了发送请求的子集,我们通常不希望发送大的请求。同样,这里的限制也是基于镜像可用的基础架构。这是通过设置 maxBodySize 属性来实现的。

  services :
    guestbook-service :
      mirroring:
        service: guestv1
        maxBodySize : 1024
        mirrors:
        - name: guestv2
          percent: 10

   # Removed for brevity


1234567891011

该法规将最大身体尺寸限定为 1024。对于镜像服务,此发送请求的大小小于 1024。

TCP 服务

Traefik 可以对 TCP 请求进行负载平衡。TCP 是许多流行应用(如 LDAP、MySQL 和 Mongo)之间的通信协议。该协议创建一个套接字连接。所有通信都是以请求-响应的方式进行的。在下一节中,我们加载 balance MongoDB 服务器。MongoDB 通过 TCP 协议进行通信。MongoDB 服务器的安装超出了本书的范围。请参考 MongoDB 文档。

在继续之前,我们需要在静态配置中为 TCP 创建一个入口点。入口点将所有传入的 TCP 请求发送到 mongo 服务器。入口点的声明方式与第二章中 HTTP 服务的声明方式相同。

entryPoints :
  mongo :
    address : ":80"

providers :
  file :

    directory : /Users/rahulsharma/traefik/ch03/code
    watch : true
    filename : config

api :
  insecure : true
  dashboard : true


123456789101112131415

一系列

我们在上一节中讨论了循环算法。该算法在列出的服务器之间平均分配请求。Traefik 允许您使用循环算法对 TCP 服务进行负载平衡。作为先决条件,您需要在两台服务器上运行 MongoDB。

tcp :
  routers :
    mongo-router :
      entryPoints :
      - mongo
      rule : HostSNI(`*`)
      service : mongo-tcp-service

  services :
    mongo-tcp-service:
      loadBalancer :
        servers :
        - address  : "192.168.1.10:27017"
        - address  : "192.168.1.11:27017"


123456789101112131415

关于前面的代码,可以说如下。

它描述了将请求路由到mongo-tcp-servicemongo-router

TCP 路由器只有一个HostSNI规则。这使您能够在同一个端口上运行 TCP 和 HTTP 服务。当 TLS 支持启用时,您会看到它。

mongo-tcp-service具有与 HTTP 服务相同的声明。它由一个loadBalancer模块组成。

loadBalancer块包含一个地址列表,不像 HTTP 服务,它的位置是一个 URL。在 TCP 中,这是 IP 和端口的组合。

配置的 TCP 服务显示在 Traefik 仪表板的 TCP 服务视图中(见图 3-16 )。

以下命令使用 Mongo shell 连接到 Mongo 服务器。您可以使用db.hostInfo命令确定连接了哪台服务器。

$traefik:/# mongo -u root -p example --host localhost --port 80
MongoDB shell version v4.2.6
connecting to: mongodb:// localhost:80/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("6cc39569-0bc3-4602-b582-566afaac0382") }
MongoDB server version: 4.2.6
Server has startup warnings:
2020-05-23T13:41:25.742+0000 I  STORAGE  [initandlisten]
2020-05-23T13:41:25.742+0000 I  STORAGE  [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2020-05-23T13:41:25.742+0000 I  STORAGE  [initandlisten] **        See http://dochub.mongodb.org/core/prodnotes-filesystem
---
>  db.hostInfo()


123456789101112

Traefik 微服务 API 网关教程(一)

图 3-16

循环 TCP 服务

终端延迟

TCP 客户端只建立一次连接。然后,它通过打开的连接发送所有请求。这与 HTTP 协议相反,在 HTTP 协议中,每个请求都在新的连接上路由。但这也带来了另一个挑战。连接可以从任一侧关闭。由于各种原因,如业务验证和服务重启,可以从服务器关闭它。它也可以从客户端关闭。由于 TCP 在双工模式下工作,每个连接关闭事件都必须得到双方的确认。如果另一端不关闭连接,连接将保持半开状态。打开的连接将锁定 Traefik 资源。

可以通过配置终止延迟来改进连接关闭处理。延迟定义了一个超时间隔,在此期间 Traefik 等待来自两端的连接关闭。延迟后,Traefik 终止连接并重新收集分配的资源。当任一方发送关闭事件时,设置延迟时钟。

# removed for Brevity

services :
    mongo-tcp-service:
      terminationDelay: 50
      loadBalancer :
        servers :
        - address  : "192.168.1.10:27017"
        - address  : "192.168.1.11:27017"


12345678910

延迟是在服务级别配置的。它适用于该服务下的所有服务器。延迟有一个正值,以毫秒为单位指定时间间隔。负值表示连接一直保持到双方都关闭为止。

Note

在 TCP 协议中没有状态代码或等同的代码。因此,TCP 服务没有可用的健康检查。

加权循环赛

在上一节中,我们讨论了加权循环算法。该算法允许您根据指定的权重比率分发传入的 TCP 请求。如 HTTP 服务示例所示,weighted服务是比loadBalancer服务更高级的服务。它对 TCP 服务也有相同的行为。继续上一节的 MongoDB 服务器,让我们看看加权配置。

# Removed for Brevity

  services :
    mongo-tcp-service :
      weighted:
        services:
        - name: mongo-1-service
          weight: 3
        - name: mongo-2-service
          weight: 1

    mongo-1-service:
      terminationDelay: 42
      loadBalancer :
        servers :
        - address  : "192.168.1.10:27017"
        - address  : "192.168.1.11:27017"

    mongo-2-service:
      terminationDelay: 42
      loadBalancer :
        servers :
        - address  : "192.168.1.12:27017"



Traefik 微服务 API 网关教程(一)123456789101112131415161718192021222324

关于前面的代码,可以说如下。

上述应用有三台主机。192.168.1.10 和 192.168.1.11 组合在一起。

mongo-1-service已定义的分组主机配置。mongo-2-service为 host3 实例定义的配置。

Mongo-tcp-service以 3:1 的比率配置两个逻辑组。Traefik 每隔四个连接请求发送一次到 192.168.1.12,而其余请求以循环方式分布在 192.168.1.10 和 192.168.1.11 中。

我们可以在 Traefik 仪表板中看到加权分布。(参见图 3-17 )

Traefik 微服务 API 网关教程(一)

图 3-17

加权循环 TCP 服务

UDP 服务

Traefik 可以对 UDP 请求进行负载平衡。UDP 是许多流行应用(如 IMAP、DNS、TFTP 和 Memcache)之间的通信协议。UDP 使用无连接的通信模型,具有最少的协议机制。没有握手,也没有保证送达。因此,该协议没有开销成本。一些应用需要这些属性,比如时间敏感的应用。

在下一节中,我们将对 TFTP 服务器进行负载平衡。TFTP 通过 UDP 协议进行通信。TFTP 服务器的安装超出了本书的范围。有关更多信息,请参考 TFTP/Unix 文档。

在我们继续之前,我们需要在静态配置中为 UDP 创建一个entrypoint,。入口点将所有传入的 UDP 流量发送到 TFTP 服务器。入口点的声明方式与第二章的中 HTTP 的声明方式相同。

entryPoints :
  tftp :
    address : ":69/udp"

providers :
  file :

    directory : /Users/rahulsharma/Projects/traefik-book/ch03/code
    watch : true
    filename : config

api :
  insecure : true
  dashboard : true


123456789101112131415

一系列

我们在前面的章节中讨论了循环算法。该算法在列出的服务器之间平均分配请求。Traefik 允许您使用循环算法对 UDP 服务进行负载平衡。作为先决条件,您需要在两台服务器上运行 TFTP。

udp :
  routers :
    tftp-router :
      entryPoints :
      - tftp
      service : tftp-service

  services:
    tftp-service:
      loadBalancer :
        servers :
        - address  : "192.168.1.10:69"
        - address  : "192.168.1.11:69"


1234567891011121314

关于前面的代码,可以说如下。

我们描述了tftp-router将请求路由到tftp-service

UDP 路由器没有任何规则。它不能执行主机名查找。它只能使用端口来执行。

tftp-service具有与 HTTP 服务相同的声明。它由一个loadBalancer模块组成。

loadBalancer块包含一个地址列表,不像 HTTP 服务,它的位置是一个 URL。在 UDP 中,它是 IP 和端口的组合。

Traefik dashboard 还提供 UDP 服务视图来显示已配置的 UDP 服务。(参见图 3-18 )

Traefik 微服务 API 网关教程(一)

图 3-18

循环中的 UDP 服务

Note

UDP 服务没有可用的运行状况检查。

以下命令通过使用tftp命令连接到 TFTP 服务器。您可以传输我们在服务器上提供的示例文件。

traefik $ tftp 192.168.1.4
tftp> verbose
Verbose mode on.
tftp> get sample.md
getting from 192.168.1.4:sample.md to sample.md [netascii]
Received 682 bytes in 0.0 seconds [inf bits/sec]


1234567

加权循环赛

前面几节讨论了加权循环算法。该算法允许您根据规定的权重比率分发传入的 UDP 消息。如 HTTP 服务示例所示,weighted服务是比loadBalancer服务更高级的服务。它对 UDP 服务也有相同的行为。继续上一节的 TFTP 服务器,让我们看看加权配置。

关于前面的代码,可以说如下。

上述应用有三台主机。192.168.1.10 和 192.168.1.11 组合在一起。

tftp-1-service定义分组主机的配置。tftp-2-service定义 host3 实例的配置。

tftp-service以 3:1 的比率配置两个逻辑组。Traefik 每隔四个连接请求发送一次到 192.168.1.12,而其余请求以循环方式分布在 192.168.1.10 和 192.168.1.11 中。

我们可以在 Traefik 仪表板中看到加权分布。(参见图 3-19 )

Traefik 微服务 API 网关教程(一)

图 3-19

加权 UDP 服务

摘要

在本章中,您看到了 Traefik 中不同的负载平衡功能。我们为 HTTP、TCP 和 UDP 通信配置了经典循环法和加权循环法。您还处理了 HTTP 通信的 stick 会话和健康检查。最后,您看到了用于 canary 部署的镜像功能。在下一章中,您将看到 Traefik 中可用的 TLS 功能。

四、配置 TLS

前几章介绍了如何通过 HTTP、TCP 和 UDP 连接使用 Traefik 公开服务。他们还深入了解了 Traefik 提供的特殊交通管理功能。到目前为止,您只处理过普通的未加密流量——HTTP 或 TCP。但是,对于任何严肃的生产用途,您都需要通过 TLS 安全地公开端点。在本章中,您将了解 Traefik 为加密和解密网络流量提供的功能。

涵盖了以下两种情况。

带 trafik 的 tls 终端

TLS 转发到后端服务

对于 Traefik 的 TLS 终止,我们使用 Let’s Encrypt 为公共云中运行的服务自动提供 TLS 证书。Traefik 和 Let’s Encrypt 一起让这个复杂的过程变得相当琐碎。

TLS 快速概述

TLS 加密的常见用例是保护 HTTP 流量。这意味着所有 API 和 web 流量都可以抵御中间人攻击和其他形式的网络窥探。我们不是公开普通的 HTTP 流量,而是通过 HTTPS 路由数据包。这意味着传输数据包的底层通道是加密的。

这种安全性的主要需求是保护敏感数据,从您可以用来验证对受保护资源的访问的用户名/密码开始。你不应该在普通的 HTTP 连接上传输任何秘密,因为它很容易被网络嗅探软件截获。

TLS 流量在离开源端时被加密,然后在目的端被解密。解密部分就是我们所说的 TLS 终止。这种加密和解密通常在应用层(OSI 或 TCP/IP 术语)之下执行。

除了指定适当的配置之外,大多数应用层代码从不需要担心 TLS 的细节。因为实现加密协议不适合胆小的人,也不应该掉以轻心,所以大多数编程语言和平台都带有标准库,这些库已经过实战测试,并由密码学专家实现。

Note

尽管我们触及了在 Traefik 中使用 TLS 的许多部分,但对 TLS 的深入讨论超出了本书的范围。它的核心是基于标准的密码原语,特别是公钥密码学,这是一个专门的领域。本演练涵盖使用 TLS 的实际方面,包括从证书颁发机构获取有效的 TLS 证书,并在客户端-服务器配置中使用它们。我们不涉及高级网络安全实践或 DNS,尽管我们确实对它们有所涉猎。我们鼓励您更深入地研究这些领域,根据它们的用例来微调配置。

一般来说,连接到启用了 TLS 的服务器的客户端可以验证其真实性。它们通过向证书颁发机构(或 CA)验证服务器的 TLS 证书来实现这一点,证书颁发机构签署并颁发服务器的证书。该服务器证书包含服务器的公钥,该公钥在客户端和服务器之间建立加密通道。这有助于防范中间人和其他攻击。CA 通常是受信任的第三方公共机构,大多数浏览器已经自动配置了这些。大型专用企业网络通常有一个专用 CA 来为内部 Intranet 站点颁发证书,并且该专用 CA 在企业管理的设备上自动受到信任。

这种机制有一个扩展,可以向服务器验证客户端的身份;这是通过通常由同一个 CA 颁发的客户端证书来实现的,并在服务器端进行验证。虽然 Traefik 支持这种方法,但我们并不在本章中讨论这种方法。

通常,HTTP 流量的默认端口是 80,HTTPS 是 443,尽管各种平台和应用在它们选择的任何端口上提供 TCP 和 HTTP/HTTPS 流量。例如,端口 8080 和 8443 分别是公开 HTTP 和 HTTPS 流量的非常流行的备选方案。(它们是非限制性端口,但是这方面的讨论超出了本书的范围。)然而,大多数面向互联网的服务器都公开标准端口 80 和 443。到目前为止,我们主要公开了 8080、80 或其他 HTTP 和 TCP 自定义端口上的 Traefik 入口点。Traefik 仪表板通过 HTTP 8080 或 80 以未经身份验证的不安全模式公开,不建议在生产环境中使用。

虽然 TLS 广泛保护 web 上的 HTTP 流量,但我们使用它来保护普通的 TCP 连接。我们可以很容易地将 HTTPS 暴露给前几章中介绍的一个 HTTP APIs 示例。我们认为 TLS 比简单 TCP 更好地展示了 Traefik 的高级 TLS 功能。作为通过 TLS 公开 TCP 端口的一部分,我们还包括一些 HTTPS 流量。

在 Traefik 终止 TLS

前一章介绍了如何使用 Traefik 公开和负载平衡 MongoDB TCP 服务。本地使用有一个简单的连接是好的;然而,对于任何一种严肃的生产用例,您都需要使用 TLS 加密到 MongoDB 的连接。您可以通过两种方式实现这一点。

在 MongoDB 服务器上启用 TLS,这样 TLS 在 MongoDB 服务器级别终止。这要求 Traefik 传递加密的流量。或者,

MongoDB 仍然服务于普通的 TCP 流量;但是,我们在 Traefik 入口点上启用 TLS 来公开 MongoDB 连接。然后,TLS 在 Traefik 入口点终止,该入口点将解密的流量传递到后端 MongoDB 端口。

虽然第一种选择似乎更有利和安全,但这在实践中通常不是可行的方法。由于 Traefik 通常充当负载平衡器或反向代理,因此它通常会在多个后端实例之间对您的请求进行负载平衡。这在上一章中已经讲过了。

通常,您有多个集群节点或服务实例(分别用于数据库和 API)暴露在一个路由后面。在这种情况下,任何客户端都希望将一个一致的端点暴露给它们所连接的任何服务。出于安全原因,TLS 证书与部署它们的服务器域主机紧密耦合。如果我们在单个实例级别终止 TLS,那么我们需要额外的证书,或者在每个复制副本实例上重复使用相同的证书。对于消费者来说,很明显客户端每次都连接到不同的主机。这是不太可取的。

在实际生产中,我们总是使用 Traefik 进行 TLS 终止,然后通过简单的 TCP 连接将数据包从 Traefik 路由到后端(在当前示例中是 MongoDB)。这并没有看起来那么大的安全风险,因为内部流量是在一个封闭的网络中,通常是您自己的 VPC/VLAN。对于共享基础设施的场景,总是有一种高级的做法,即启动一个从边缘网关到后端服务的新的内部 TLS 连接;我们不报道这个。

在 TLS 上公开 MongoDB 路由

本节通过公共云提供商在云 VM 上运行 MongoDB 实例。您可以使用托管数据库产品。如果您调整了正确的端口并为该数据库使用了合适的客户机,那么您可以自由地使用任何其他数据库。为了简单起见,我们在同一个云 VM 上运行 MongoDB 实例和 Traefik,这样 Traefik 可以安全地连接到在本地主机上运行的 MongoDB,而没有任何其他复杂性。

对于这个例子,我们正在运行一个运行 Ubuntu 18 的 DigitalOcean droplet(或 VM)。然而,这些概念对于任何其他云 VM 都是相同的,比如 AWS EC2 实例。设置 DigitalOcean 或 AWS 实例超出了本书的范围;然而,这很容易做到。一旦 VM 设置完成,Traefik 可以使用第一章中的说明轻松安装。

默认情况下,不允许 Ubuntu Traefik CLI 监听端口 80 或 443。因此,如果这些端口被定义为入口点,Traefik 会在启动时抛出一个错误。我们需要运行清单 4-1 中的命令来允许 Traefik 绑定到这些端口。

ubuntu-blr1-01:~$ wget https://github.com/containous/traefik/releases/download/v2.2.1/traefik_v2.2.1_linux_amd64.tar.gz
ubuntu-blr1-01:~$ tar -zxvf traefik_v2.2.1_linux_amd64.tar.gz
ubuntu-blr1-01:~$ sudo setcap 'cap_net_bind_service=+ep' traefik
ubuntu-blr1-01:~$ ./traefik  --entryPoints.web.address=:80

Listing 4-1Install and Set Permissions for Traefik


1234567

您可能想知道我们为什么选择云部署。原因是我们需要一个公共 DNS 名称,Traefik 才能获得有效的 TLS 证书。我们建立了一个单独的子域来指向 DigitalOcean droplet,并在 DNS 提供程序中添加了一个 A 记录来指向它的 IP 地址(同样,这个讨论也超出了本书的范围)。您可以在本地尝试 Traefik 的 TLS 支持,但您需要手动提供或自签名的证书。你也会错过 Traefik 让整个过程变得多么简单。手动获取的证书的 TLS 配置很简单;我们在此提供它以供参考。这对于有效的公共域证书和本地自签名测试证书都是一样的。

清单 4-2 用一个tls: {}键定义了一个 TCP 路由。这足以在此路由上启用 TLS。

# traefik.yml with only 443 entrypoint
entryPoints:
  websecure:
    address: ":443"
# Also enable DEBUG log
log:
  level: DEBUG
providers:
  file:
    filename: "traefik-tls-conf.yml"
    watch: true

# traefik-tls-conf.yml
tcp :
  routers :
    mongo-router :
      entryPoints :
      - websecure
      rule : "HostSNI(`localhost`) || HostSNI(`127.0.0.1`)"
      service : mongo-tcp-service
      tls: {} #This block will enable TLS for this route
#We also need to provide the TLS certificates
tls:
  certificates:
    - certFile: localhost+1.pem
      keyFile: localhost+1-key.pem

Listing 4-2Route Configuration for MongoDB TCP over TLS: Manual Certificates



Traefik 微服务 API 网关教程(一)1234567891011121314151617181920212223242526272829

我们还在单独的部分提供了证书路径。这是一个动态配置,这意味着我们可以在运行时添加新的证书。这些只能通过 FileProvider 定义。根据匹配的域,在运行时使用正确的证书。如果您没有提供自己的证书,或者没有为匹配的域提供证书,Traefik 会生成并使用其默认的自签名证书。也可以覆盖这个默认证书。手动生成证书超出了本章的范围。对于本地测试,像 https://mkcert.dev/ 这样的工具会很有用。在前面的配置中,您可以通过安全的 TCP+TLS 连接连接到 MongoDB。

MongoDB 的安装在书外;然而,它基本上是默认安装,只是增加了一点——为了基本的安全性,我们设置了一个 DB 用户和密码。为了简单起见,我们只使用一个后端 MongoDB 实例,而不是跨多个实例进行负载平衡。配置看起来如清单 4-3 所示。

#tls-config.yaml dynamic config
tcp :
  routers :
    mongo-router :
      entryPoints :
      - mongo
      rule : "HostSNI(`tlstraefik.rahulsharma.page`)"
      service : mongo-tcp-service
      tls:
        certResolver: "letsencrypt"
        domains:
          - main: "tlstraefik.rahulsharma.page"

  services :
    mongo-tcp-service :
      loadBalancer :
        servers :
        - address  : "localhost:27017"

Listing 4-3Route Configuration for MongoDB TCP over TLS



Traefik 微服务 API 网关教程(一)123456789101112131415161718192021

这些作品中的大部分已经为我们所知。我们查看了HostSNI属性。在前面的例子中,我们将其设置为匹配所有可能的主机名(*)。虽然这种方法对于未加密的流量可能没问题,但对于 TLS 是不可行的。它与运行服务的实际域名相匹配,并且服务器证书也验证了这一点。tlstraefik.rahulsharma.page是指向 DigitalOcean droplet 的 IP 地址的公共 DNS 名称。还有一个设置为letsencrypt ,certresolver属性,它自动提供一个 TLS 证书,从第一次请求时加密到这个端点。

让我们加密自动证书供应

获取 TLS 证书通常是一个多步骤的过程。所有平台上都有很好的实用程序,可以帮助你生成必要的片段。对于无处不在的 TLS 证书,证书生成是一个复杂的过程,需要设置许多属性,如果某些配置是错误的,您需要重新开始。通常的步骤是为服务器证书生成证书签名请求(CSR ),并将其提交给 CA 进行签名。CA 签署并返回可以使用的有效证书。不同的 ca 有不同的定价模式,证书功能和网站可以自由选择他们想要的。传统上,这是一个手动过程,其中包含一些自动化部分。

这个领域的大颠覆是由一个叫做“让我们加密”( https://letsencrypt.org )的非营利组织带来的。Let’s Encrypt 已经为超过 2.25 亿个网站颁发了免费的 TLS 证书(超过 10 亿份)。它通过编程 API 自动完成整个过程,因此不需要人工干预。

让我们加密几个官方和第三方客户端,使最终用户的证书提供过程变得简单。它通过利用 ACME 标准( https://tools.ietf.org/html/rfc8555 )来实现这种自动化,ACME 标准代表自动证书管理环境。我们不会深入研究这个问题,但是它完全自动化了从 ACME 兼容的 CA 获取和管理证书的工作。最重要的是,你必须做的就是启动你的 HTTPS 服务器,剩下的就交给你了。如果有人正在考虑建立一个网站,需要 TLS 证书,让我们加密是正确的做法。

Note

让我们只加密面向 Internet 的公共站点的设置证书。这意味着您的端点需要可以通过公共域名访问,以便我们加密来提供 TLS 证书。对于私有或内部 API,需要从其他 ca 提供证书。这对示例有影响,到目前为止,这些示例一直在本地系统上运行。

为公共 TCP 端点设置 TLS 证书

为了自动提供来自 Let’s Encrypt 的 TLS 证书,我们需要在公共互联网上公开 MongoDB 端口。

显然,作为一种实践,您永远不应该在互联网上公开您的数据库端口。有许多新闻报道称,不安全的 MongoDB 连接暴露在开放的互联网上,并成为黑客的目标,导致数据受损。对于这个例子,我们暂时使用一个空白数据库,所以应该没问题。我们还使用适当的访问凭证来保护 MongoDB,该端口只能通过 Traefik 访问。这里需要注意的一点是,我们还在虚拟机上设置了云防火墙规则,只允许端口 80、443 和 4445 上的入站流量。来自 Internet 的所有其他入站流量都被阻止。

如清单 4-2 所示,我们在tlstraefik.rahulsharma.page域上公开了 Mongo TCP 端点。tlstraefik这里是 TLS 路由匹配的子域。Let’s Encrypt 颁发的证书是为同一个子域颁发的。支持额外的域条目,这些条目请求额外的 SNI(服务器名称指示)主机名,这些主机名支持同一 IP 和端口上的多个域和 TLS 证书。我们不打算深究此事。

Traefik 首先检查域条目,然后检查 HostSNI 值,以确定自动请求 TLS 证书的域。这里两者都不需要;我们把它们包括进来只是为了参考。这对于通配符证书更有用,这里不讨论。

引用了certresolver属性。它与入口点一起在静态配置中定义。我们需要定义一个 TLS 入口点和证书解析器,目前主要是加密。

在清单 4-4 中,有两个感兴趣的条目。首先是要指定的caServer URL 属性。通常,默认情况下,这是让我们加密生产 API 端点。然而,这个终点有严格的(尽管是宽松的)速率限制。

#traefik.yaml static config
entryPoints:
  mongo:
    address: ':4445'
  https:
    address: ':443'
providers:
  file:
    watch: true
    filename: tls-config.yml
certificatesResolvers:
  letsencrypt:
    # ACME support via Let's Encrypt
    acme:
      # Email address required for certificate registration
      email: "<email address>"

      # File or key required for certificates storage.
      storage: "acme.json"

      # CA server URL
      caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"

      tlsChallenge: {}

Listing 4-4Entrypoint and Certificate Resolver



Traefik 微服务 API 网关教程(一)123456789101112131415161718192021222324252627

如果您是第一次使用 Let’s Encrypt 并在测试环境中试验配置来弄清楚您的 TLS 设置,那么使用 Let’s Encrypt staging 端点的 URL 更有意义,它在清单 4-4 中使用。这不提供可用的 TLS 证书。签署证书的 CA 是假的,大多数浏览器拒绝由此产生的证书。Let’s Encrypt 允许您下载虚拟 CA 证书(fakelerootx1.pem ),并根据它验证您生成的服务器证书。这允许您在使用有效证书进入生产环境之前测试整体集成。

其次,tlsChallenge属性是我们感兴趣的。为了验证请求服务器证书的第三方拥有主机的所有权,让我们加密支持各种自动化挑战。标准的挑战是 HTTP-01 挑战和 DNS-01 挑战。两者都适合不同类型的用例。然而,TLS 终止反向代理有一个特殊的挑战,这就是 Traefik 在这里扮演的角色,称为 TLS-ALPN-01 挑战。更多的信息超出了本书的范围。在 Traefik 中配置这种质询类型很简单,所以在这里使用它。

有一个警告:这个挑战需要 Traefik 访问端口 443;因此,我们在端口 443 上暴露了一个额外的入口点。这没什么大不了的,因为我们无论如何都会在下一节中使用这个端口。对于基于云的安装,有必要在入站流量防火墙规则中打开端口 443。当您在 Traefik 仪表板上查看时,您会看到两个入口点(参见图 4-1 )。

Traefik 微服务 API 网关教程(一)

图 4-1

TLS entry points-TLS 输入类型

如果您使用这个 Traefik 配置来公开与 Traefik 实例运行在同一服务器上的 MongoDB 实例,您可以在主机名 tlstraefik.rahulsharma.page *、*上访问端口 4445 上的 MongoDB,但只能使用 TLS 连接。您可以用 Mongo 客户端 CLI 来尝试一下(参见清单 4-5 )。

ch04 % mongo --port 4445 --host tlstraefik.rahulsharma.page
MongoDB shell version v4.2.7
connecting to: mongodb:// tlstraefik.rahulsharma.page:4445/?compressors=disabled&gssapiServiceName=mongodb

Listing 4-5Mongo Client Simple Connection


123456

这并不连接到 Mongo 实例,也不工作。为了让它工作,我们需要传递一个--tls选项(参见清单 4-6 )。

ch04 % mongo --port 4445 --host tlstraefik.rahulsharma.page --tls
MongoDB shell version v4.2.7
connecting to: mongodb:// tlstraefik.rahulsharma.page:4445/?compressors=disabled&gssapiServiceName=mongodb
2020-07-05T17:44:26.901+0530 E  NETWORK  [js] SSL peer certificate validation failed: Certificate trust failure: CSSMERR_TP_NOT_TRUSTED; connection rejected
2020-07-05T17:44:26.901+0530 E  QUERY    [js] Error: couldn't connect to server tlstraefik.rahulsharma.page:4445, connection attempt failed: SSLHandshakeFailed: SSL peer certificate validation failed: Certificate trust failure: CSSMERR_TP_NOT_TRUSTED; connection rejected :
connect@src/mongo/shell/mongo.js:341:17
@(connect):2:6
2020-07-05T17:44:26.904+0530 F  -   [main] exception: connect failed
2020-07-05T17:44:26.904+0530 E  -   [main] exiting with code 1

Listing 4-6Mongo Client TLS Connection


123456789101112

这也不行;如果您使用了“让我们加密”的临时 CA URL,则无法验证生成的服务器证书。要用这个证书连接到 MongoDB,您需要传递一个–tlsAllowInvalidCertificates标志或--tlsCAFile选项(参见清单 4-7 )。

ch04 % mongo --port 4445 --host tlstraefik.rahulsharma.page –tls --tlsCAFile fakelerootx1.pem
MongoDB shell version v4.2.7
connecting to: mongodb:// tlstraefik.rahulsharma.page:4445/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("0b2ccc38-f8bd-4346-a08a-3da0ef9793b0") }
MongoDB server version: 3.6.3
> use admin
switched to db admin
> db.auth("akshay", "password");
1
> db.version()
3.6.3

Listing 4-7Mongo Client TLS Connection


1234567891011121314

如果您简单地省略清单 4-4 中的caServer URL 属性,Traefik 会自动连接到 Let’s Encrypt production URL 并获取一个有效的证书。然后,清单 4-8 中的命令开始工作。

ch04 % mongo --port 4445 --host tlstraefik.rahulsharma.page –tls
MongoDB shell version v4.2.7
connecting to: mongodb:// tlstraefik.rahulsharma.page:4445/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("0b2ccc38-f8bd-4346-a08a-3da0ef9793b0") }
MongoDB server version: 3.6.3
>

Listing 4-8Mongo Client Valid TLS Certificate


123456789

这里有两点需要注意。首先,默认情况下,Traefik 将获得的证书保存在一个名为 acme.json 的文件中。您可以在清单 4-4 中看到这个文件名。如果需要,我们可以添加自定义文件名或位置。如果从临时 URL 切换到生产 URL,您还需要删除此文件或使用其他位置。否则,Traefik 默认使用已经保存的证书。

其次,虽然 TLS 终端可能与入口点端口(本例中为 4445)紧密相关,但 TLS 配置是由动态路由器配置驱动的。归根结底,Traefik 不会向 Let’s Encrypt 发送证书生成请求,直到它为特定的路由进行了配置。因此,为同一个入口点生成不同的证书来服务不同的路由是完全可行的。

我们可以在 Traefik 仪表板中看到下面的 TCP 路由器,其中提到了 TLS 细节(参见图 4-2 和图 4-3 )。

Traefik 微服务 API 网关教程(一)

图 4-3

带有 TLS 详细信息的 TCP 路由器

Traefik 微服务 API 网关教程(一)

图 4-2

启用 TLS 的 TCP 路由器

通过 tls 保护流量仪表板

到目前为止,我们已经在不安全的模式下公开了 Traefik 仪表板,以检查 UI 上的配置。但是,在公共云上,您希望控制面板受到身份认证和 TLS 的保护。作为其中的一部分,我们在同一台主机上的 entrypoint 443 上公开 Traefik 仪表板,并在显式仪表板路由上应用身份验证中间件。该路由在同一个主机名上公开,尽管我们可以为带有 DNS 条目和 TLS 证书的仪表板指定不同的主机名。这方面的配置见清单 4-9 。我们还将端口 80 上的所有 HTTP 流量重定向到端口 443 上的 HTTPS。

#traefik.yaml static config
entryPoints:
  https:
    address: ':443'
  http:
    address: :80
    http:
      redirections:
        entryPoint:
          to: https
          scheme: https
providers:
  file:
    watch: true
    filename: tls-config.yml
api:
  dashboard: true
#tls-config.yaml dynamic config
http:
  routers:
    dashboard:
      entryPoints:
        - https
      rule: "Host(`tlstraefik.rahulsharma.page`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
      service: api@internal
      tls:{}
      middlewares:
        - auth
  middlewares:
    auth:
      basicAuth:
        users:
          - "admin:$apr1$JsindKAS$zCWAvabJOgQvI.Dd3zjtE."

Listing 4-9Entrypoint and Route Config for Secure Dashboard



Traefik 微服务 API 网关教程(一)123456789101112131415161718192021222324252627282930313233343536

在应用这种配置时,您可能会观察到两种不同的结果。如果您已经执行了前面几节中为 MongoDB 配置 TLS 的步骤,那么 Traefik 将重用服务器为 MongoDB 路由获得的相同证书,因为它们共享相同的主机条目。但是,如果忽略 MongoDB TLS 配置,Traefik 会返回生成一个默认的自签名 TLS 证书。您在浏览器中观察到类似图 4-4 所示的情况,它抱怨证书问题,并且不让您继续。这是因为我们没有为仪表板路线指定任何certResolver值。

Traefik 微服务 API 网关教程(一)

图 4-4

自签名 Traefik 证书错误

如果我们检查证书,我们可以看到细节(见图 4-5 )。

Traefik 微服务 API 网关教程(一)

图 4-5

自签名 Traefik 证书详细信息

您也可以为仪表板路线使用一个certResolver属性。在配置中甚至可以有两个certResolver属性:一个指向让我们加密暂存,另一个指向生产。在清单 4-10 中可以看到一个例子,我们为仪表板定义了一个不同的域(它仍然必须是一个有效的公共域)和一个 staging certResolver

#traefik.yaml has both staging and prod LE config
# only relevant config for brevity
certificatesResolvers:
  letsencrypt:
    acme:
      email: "<email address>"
      storage: "acme.json"
      tlsChallenge: {}
  letsencrypt-staging:
    acme:
      email: "<email address>"
      storage: "acme-staging.json"
      # CA server to use.
      caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
      tlsChallenge: {}
#tls-config.yaml dynamic config
http:
  routers:
    dashboard:
      entryPoints:
        - https
      rule: "Host(`dashboard.rahulsharma.page`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
      service: api@internal
      tls:
        certResolver: "letsencrypt-staging"
# Rest of config omitted for brevity

Listing 4-10Multiple Lets Encrypt Resolvers



Traefik 微服务 API 网关教程(一)1234567891011121314151617181920212223242526272829

在这种配置下,您会在浏览器中看到以下错误(参见图 4-6 ),并且不允许您继续操作。

Traefik 微服务 API 网关教程(一)

图 4-6

让我们加密临时证书的详细信息

一旦我们修复了配置并从 Let’s Encrypt 获得了正确的生产证书,我们就可以在浏览器中检查证书的详细信息(参见图 4-7 )。我们还被要求提供仪表板的基本认证凭证(见图 4-8 )。

Traefik 微服务 API 网关教程(一)

图 4-8

仪表板的基本身份验证

Traefik 微服务 API 网关教程(一)

图 4-7

让我们加密有效的证书细节

tls 转发的流量

在某些罕见的情况下,您的目标服务或数据库可能需要自己管理 TLS 终止,而不需要在其间使用反向代理。这意味着 Traefik 需要在不解密或终止的情况下转发 TLS 流量。令人高兴的是,Traefik 通过passthrough选项很容易支持这一点。我们需要在启用服务器 TLS 的情况下运行 MongoDB,并使用有效的 TLS 证书来证明这种支持。配置超出了本书的范围;然而,通过遵循 MongoDB 文档,这应该很容易做到。MongoDB 配置可能会看起来像清单 4-11 所示。

net:
  port: 27017
  bindIp: 127.0.0.1,tlstraefik.rahulsharma.page
   tls:
      mode: requireTLS
      certificateKeyFile: /etc/ssl/mongodb.pem

Listing 4-11Sample MongoDB TLS Configuration in /etc/mongod.conf


123456789

和以前一样,您可以自由选择任何其他目标,例如另一个云管理的数据库,连接的过程是不同的。您也可以在本地尝试这种方法;您需要自签名服务器证书和您自己的 CA 证书。对此的深入讨论超出了本节的范围;然而,OpenSSL 是一个很好的实用程序,可以在所有主流平台上生成 TLS 证书。

本节的 Traefik 设置与之前运行在同一云 VM 主机上的 Traefik 实例相同,防火墙上暴露了必要的 Traefik 端口。然而,这次我们没有为mongo-router路由定义一个certResolver,而是添加了一个不同的属性,如清单 4-12 所示。

#tls-config.yaml dynamic config
tcp :
  routers :
    mongo-router :
      entryPoints :
      - mongo
      rule : "HostSNI(`tlstraefik.rahulsharma.page`)"
      service : mongo-tcp-service
      tls:
        passthrough: true

# Rest omitted for brevity

Listing 4-12Route Configuration for TLS Forwarding


123456789101112131415

当我们试图在这个主机/端口上访问 MongoDB 时,Traefik 会将 TLS 连接不加解密地转发到运行在同一个 VM 上的 MongoDB 服务器,在那里发生实际的 TLS 终止,如清单 4-13 所示。

code % mongo --tls --host tlstraefik.rahulsharma.page --port 4445
MongoDB shell version v4.2.8
connecting to: mongodb://tlstraefik.rahulsharma.page:4445/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("88df0a97-6ff8-4764-897b-82746b621598") }
MongoDB server version: 4.2.8
> use admin
switched to db admin
> db.auth("akshay", "password");
1

Listing 4-13Connect Mongo over TLS


123456789101112

如果您在 Traefik 仪表板上检查此配置,您会看到 passthrough 属性设置为 true(参见图 4-9 )。

Traefik 微服务 API 网关教程(一)

图 4-9

带 tls 穿透的 trafik 路由器

对于客户端应用,行为没有真正的改变。至此,我们结束了这一节和这一章。为了进一步深入,我们鼓励您深入研究 Traefik 文档中提供的不同 TLS 配置选项。

摘要

在这一章中,您快速地、表面地了解了设置 TLS 证书来保护您的网络流量的深层领域。我们理解,你们中的一些人可能会对我们快速浏览的所有主题感到不知所措。我们仅仅触及了 TLS 证书生态系统的表面。然而,我们认为我们已经展示了 Traefik 与 Let’s Encrypt 结合使用是多么容易,特别是对于公共 DNS 域。事实上,您可能会发现,从 Let’s Encrypt 为 Traefik 端点提供有效的 TLS 证书比生成自签名或有效的 TLS 证书更容易。如果你对 TLS 更感兴趣,我们鼓励你去探索它。

为了安全起见,我们没有提到通过 Let’s Encrypt 获得的证书每 90 天更新一次。在传统的 IT 环境中,证书续订是一个繁琐的手动过程,必须由人来跟踪。因此,随着长期运行的 TLS 证书的使用,这样做的频率降低了。有了 Traefik/Let’s Encrypt 集成,这是自动处理的,不需要任何手动干预。Let’s Encrypt 会在您注册时使用的电子邮件地址上自动发送提前提醒。

在下一章中,您将深入了解 Traefik 中针对操作问题提供的大量简单选项。Traefik 使收集运行时指标变得非常容易,并与许多标准监控框架集成。

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...