kubeCDN:一个基于 Kubernetes 的自托管 CDN

阅读数:9443 2019 年 4 月 24 日 17:15

kubeCDN:一个基于Kubernetes的自托管CDN

在本篇博文中,作者主要讨论了 kubeCDN 的设计和实现,这个工具旨在简化 Kubernetes 集群的跨地域复制,以便在全球范围内部署高可用的 CDN(内容分发网络)服务。

用户越多,问题越多

互联网的出现让全世界的人们改变了交流和分享信息的方式。但是,这种改变方式依然存在不少问题。由于互联网已经变成了人们获取信息的首选途径,互联网中阻碍我们快速获取信息的任何障碍都会令人不爽。坐在电脑前等待文档或视频缓冲,相信大家都经历过,这种时候对我们来说几分钟甚至几秒钟都是一种煎熬。考虑到当今互联网的普及程度,我们生活中的方方面面都非常依赖它,而且我们也不得不花费更多的时间来面对下图中的情形。这种经历极大地破坏了用户体验,但凡存在可替代方案,相信用户都会趋之若鹜。没有企业想因为这种方式失去客户,但解决这类问题会涉及一些技术上的挑战。
kubeCDN:一个基于Kubernetes的自托管CDN

缓冲中,请等待。。。(图片摘自:  https://i.gifer.com/7Pzx.gif

服务器远离用户是造成服务延迟的主要原因。假设你的服务器正在提供全球客户服务,那么位于世界另一端的用户势必会感受到更多的服务延迟。这种延迟减缓了数据获取、导致了更多的动画缓冲,用户体验也变得非常糟糕。

kubeCDN:一个基于Kubernetes的自托管CDN
远离服务器的用户会感受到更多的延迟(图片来源

将服务器部署到离用户尽可能近的地方可以减少这种延迟,但这种方法却非常具有挑战性,毕竟并不是每个公司都有能力在全球范围部署基础设施,这需要非常大的资本和人力投入。

当前解决方案:CDN 服务供应商

我们可以借助第三方 CDN 供应商来避免这种问题。一家公司完全可以只在一个地区部署基础设施,然后利用 Akamai CloudFlare Fastly 等 CDN 供应商将服务分发到全世界。

CDN 供应商在全球范围内有很多 PoPs(Points of Presensce - 入网点),节点通常由一些边缘服务器组成,服务器则缓存了像图片这样的静态资源。当用户请求资源时,边缘服务器可以直接提供缓存内容;如果没有找到请求的资源,边缘服务器将尝试从客户服务器或附近的边缘服务器获取该资源。这种设置大大降低了网络延迟以及数据包的丢失,极大地改善了跨地域用户的使用体验。

更多关于 CDN 的内容请参考此处

使用 CDN 供应商的问题

使用 CDN 供应商的确是一个便捷的解决方案,但这种方案也存在一些问题。

第一个问题是,在使用第三方 CDN 服务的同时,我们也失去了对基础设施的控制权。我们只能依赖外部实体来确保用户能够获得最佳体验。这里还有一个更重要的因素,那就是用户数据的安全性。第三方 CDN 供应商系统中的错误,例如 2017 年的个错误,就可能对用户的安全和隐私产生严重影响。

第二个问题则是,CDN 供应商可能并不会把你的利益摆在第一位。毕竟你可能不是他们唯一的客户,而且作为一个独立企业,他们也需要优先考虑自身的利益。

最后也是最重要的问题,CDN 供应商能够监视你的业务数据。CDN 供应商可以确定你的客户的位置、客户使用服务的时间以及客户所使用的设备类型。这样的业务数据对你的竞争对手来说非常有价值,如果这类信息泄露给第三方可能会让你的客户流失,从而让你的业务蒙受重大损失。

对于许多团队来说,这些问题的潜在危害可能已经远远超过了其所带来的便利性。因此,像 Netflix LinkedIn 这样的顶级工程团队都已经自主解决了这个问题。如果你也想构建自己的 CDN,不妨尝试一下 kubeCDN。

kubeCDN

上述问题也是作者决定设计 kubeCDN 的根本原因。它是一个基于 Kubernetes 的自托管 CDN 方案,自托管也就意味着我们可以完全控制自己的基础设施。通过 kubeCDN,我们不再需要第三方的内容分发网络,重新控制了从服务器到用户设备的数据流。

架构设计

kubeCDN 使用 Terraform 在选定的区域部署 EKS 和其他 AWS 基础设施组件。 Route53 是 AWS 提供的云域名系统(DNS),用于多区域用户间的路由; ExternalDNS 用于在部署新服务时自动创建 DNS 记录。

下图演示了如何使通过 Terraform 来部署 kubeCDN。

kubeCDN:一个基于Kubernetes的自托管CDN
Terraform 用于在选定的区域部署 EKS 基础设施

Terraform 用于部署 kubeCDN 所必需的基础设施,而 Route53 用于将用户流量路由到特定区域。为了演示 kubeCDN,作者在两个 AWS 区域(us-east-1 和 us-west-2)中分别部署了一个视频服务器,然后在 Route53 上设置了一个托管区域,并为集群的每个区域都设置了 A 记录。作者采用了基于延迟的路由策略,从而将用户路由到能够为他们提供最低延迟的区域。在此演示中,用户总是被路由到地理上最接近的区域。然而,实际情况可能并非总是如此。因特网上的延迟可以随着时间而改变,当采用基于延迟的路由策略时,Route53 可以利用这些监测数据来确定如何路由用户。更多信息参考此处

kubeCDN:一个基于Kubernetes的自托管CDN
kubeCDN 使用 Route53 将用户流量路由到延迟较低的区域

上图演示了 Route53 如何通过两个区域中的集群来路由用户流量。旧金山的用户被路由到 us-west-2 中的集群,因为该区域提供了更低的延迟。

kubeCDN 还可以使用 Route53 中一些别的路由策略,从而满足不同应用程序的需求,详情参阅这里

解决方案

kubeCDN 让我们在几分钟内就可以把服务和应用程序扩展到全球范围。我们只需要 15 分钟就能够完成上述基础设施的部署,与使用 AWS 控制台的手动部署相比,这是一个显著的改进。

除了易于扩展之外,kubeCDN 还可以通过关闭一些低用户活跃度的地区来优化基础设施成本。在预算紧张或为了保证最大利润的时候,这种类型的成本优化就显得尤为重要。

开发挑战

作者在开发 kubeCDN 时遇到了一系列的问题。它们大多数都是一些小问题,容易解决,但其中也不乏比较棘手的问题,下面着重分析其中的两个。

Terraform 代码重构

Terraform 原本是 HashiCorp 公司为其网络研讨会项目创建的代码,作者在该项目中对其进行了二次开发。虽然 Terraform 的代码非常清晰,并附有详细的说明,但它还不能支持多区域部署。目标区域是通过代码写死的,因此我们需要为每一个区域都复制一个代码库。这是一个非常繁琐的手动过程,非常容易因为人为因素而配置错误。这也会导致管理结构上的混乱,使基础设施监控和成本优化变得非常困难。

重构 Terraform 代码是解决这个问题的一种方法,然而,难点在于如何重构。在查阅了相关文档以及一个类似的开源项目之后,作者决定采用下面的结构来组织项目现阶段的基础设施部署。

复制代码
├── terraform (Dir containing all infrastructure code)
├── cluster (EKS cluster components)
│ ├── main.tf
│ ├── outputs.tf
│ ├── rbac.yaml
│ └── variables.tf
├── main.tf (Main .tf file where regions are specified)
└── variables.tf
(Some files have been removed for brevity)

在上面所示的目录结构中,main.tf 用来指定所有期望区域的位置。具体配置方式参照以下代码段:

复制代码
module "<name-for-region-deployment>" {
source = "cluster"
region = "<AWS-region>"
}

这样我们就可以通过一个配置文件来轻松地定义新区域,而且这也很容易管理。

ExternalDNS 的问题

ExternalDNS 是一个通过 Kubernetes 资源来动态配置 DNS 记录的工具。该工具可以与 Route53 和一些其它的 DNS 供应商对接。在将新服务(如 web 服务器)部署到 Kubernetes 集群时,ExternalDNS 会为其创建 DNS 记录,这样用户就可以通过公共 DNS 服务器解析到新部署的 web 服务器。

对于 kubeCDN,作者使用 ExternalDNS 为不同的区域自动创建 DNS 记录,并将 Route53 配置为基于延迟的路由策略,从而将用户路由到延迟最低的区域。作者在实现过程中遇到了一些问题,而这些问题使作者无法完全自动化实现 ExternalDNS 的动态配置。

作者原本设置了两个 A 记录,分别对应不同区域的域名,然后与 Route53 中基于延迟的路由策略相结合,从而将用户引导到提供最低延迟的 AWS 区域。这样,一个 A 记录会指向东海岸基础设施的域名,而另一个则指向西海岸基础设施的域名。作者将 ExternalDNS 合并到 kubeCDN 中,并配置视频测试服务去使用该工具,最后在部署时设置了一个 DNS 记录。

即使域名的 IP 地址不同,ExternalDNS 仍然会覆盖相同域名的 A 记录。这似乎是 AWS 在 ExternalDNS 中的一个临时限制。考虑到 ExternalDNS 是一个新工具,仍然处于项目孵化阶段,我们需要临时手动解决这个问题。该项目在 Github 中有个非常类似的问题,但是在提交了一个拉取请求后,这个问题就被关闭了。至今,这个请求仍然没有合并到 ExternalDNS 的主分支。

正如文中所指出的(撰写本文时 Github 上尚未有解决方案),AWS 在 ExternalDNS 中的另一个局限性则是无法在 Route53 上设置基于延迟的路由策略,我们只能通过在 AWS 控制台来手动设置这个路由策略。

以上都是针对 ExternalDNS 和 AWS 的问题,对于新版本的 ExternalDNS 或者其他云供应商可能就不存在这样的问题。随着项目的发展和更多功能的实现,相信将来这些问题都会得到改善。

kubeCDN 扩展

考虑到 kubeCDN 只是一个为期三周的短项目,它仍然有很多需要改进的地方,下面是作者的一些想法。

多云支持

目前,kubeCDN 仅支持 AWS。这主要是因为 Insight 的研究员能够在项目中使用 AWS。只使用一个云供应商会在服务中断时造成问题,添加对多云供应商(如 GCP&Azure)的支持,可以在服务中断时提供必要的故障转移。

考虑到 kubeCDN 是基于 Kubernetes 的实现,这的确提出了一些挑战。目前,kubeCDN 使用 AWS 提供的 EKS 来管理的 Kubernetes 服务。添加对其他云供应商的支持,至少需要满足下面的一个条件:

  • 整合所有云供应商提供的管理服务。虽然这将简化部署,但是将不同的托管服务合并到 kubeCDN 将非常具有挑战性。
  • 使用自定义的 Kubernetes 部署。在选定供应商提供的基础设施后,这里需要使用 kops 来安装自定义的 Kubernetes 集群。它可以统一管理位于不同供应商的基础设施上的集群,并可以灵活部署一些比较特殊的场景。除此之外,在需要消除第三方依赖的时候,kops 也可以让团队在本地设备上部署 kubeCDN。

虽然从长期来看,kops 似乎是这个项目的最佳选择,但这依然非常困难,仍需要大量的开发工作。即便如此,采用 kops 还是会给项目带来巨大的好处。

区域自动伸缩

虽然在全球范围内扩展基础设施可以极大地改善用户体验,但也没有必要在世界各处同时全天候运行服务。有时候,从利润的角度来看,关闭某些只有少量用户的区域的基础设施反而是更好的做法。从财务角度来看,这种对基础设施成本的优化是非常有益的。

为了实现这一点,我们需要一个监控解决方案来提供区域选择的度量。当某个区域的指标达到预定义的阈值时,我们就可以关闭该区域的基础设施。而如果来自特定区域的用户数量出现激增,并超过了某个类似的阈值时,我们也可以在预先定义的区域中自动启动新的基础设施。

预定义区域列表

当前版本的 kubeCDN 可以很容易得将 EKS 集群部署到新区域。目前,我们需要手动复制代码到每个区域来实现部署,但是我们可以通过一个文件来配置所需的区域,部署过程也会变得更加清晰。

这个特性还可以与前面提到的区域自动伸缩特性很好地结合起来。我们可以向 kubeCDN 提供两个区域列表,一个是需要连续运行基础设施的区域,另一个是可用于基础设施自动扩展的区域,这极大地简化了基础设施的管理。

使用 Kubernetes 的集群联邦( Federation

Kubernetes 联邦可以很容易地管理多个集群。联邦所提供的特性列表可参阅这里,虽然里面的每一个特性都有利于 kubeCDN,但其中跨集群同步资源的能力尤为突出。跨集群资源同步提出了一个巨大的管理挑战,而联邦则极大地简化了这个挑战。但是,联邦目前还不是 Kubernetes 的一个成熟特征,仍存在很多问题,Kubernetes 开发团队也正在努力解决中。

结语

当前的 kubeCDN 简化了 Kubernetes 集群的跨地域配置,并允许简单的扩展。鉴于 kubeCDN 的自托管属性,它可以满足自定义的基础设施需求,并为基础设施的管理提供巨大的灵活性。

当然,kubeCDN 也存在很多问题,但这些问题只会促使 kubeCDN 变的更加健壮。我们前面已经讨论过了其中的一些问题,相信后续会有更多。另一方面,Kubernetes 自身的改进也会影响到 kubeCDN 的未来发展。随着 Kubernetes 联邦特性的成熟,相信 kubeCDN 也会变得更加强大。

查看英文原文 https://blog.insightdatascience.com/how-to-build-your-own-cdn-with-kubernetes-5cab00d5c258

收藏

评论

微博

用户头像
发表评论

注册/登录 InfoQ 发表评论