本文已发布一年多。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已不正确。

Weave 如何使用 Kubernetes 构建 Scope 的多部署解决方案

今年早些时候,我们在 Weaveworks 推出了 Weave Scope,这是一个用于可视化和监控容器化应用和服务的开源解决方案。最近,我们在一个 早期访问计划中发布了托管的 Scope 服务。今天,我们想向您介绍我们最初如何原型化该服务,以及我们最终如何选择和部署 Kubernetes 作为我们的平台。

云原生架构

Scope 在数据收集和用户交互之间已经有清晰的内部分界线,因此很容易在该分界线上拆分应用程序,将探针分发给客户,并将前端托管在云中。我们根据 12 要素模型 构建了一小组微服务,其中包括

  • 一个用户服务,用于管理和验证用户帐户
  • 一个配置服务,用于管理客户 Scope 实例的生命周期
  • 一个 UI 服务,用于托管所有精美的 HTML 和 JavaScript 内容
  • 一个前端服务,用于根据其属性路由请求
  • 一个监控服务,用于内省系统的其余部分

所有服务都构建为 Docker 镜像,尽可能 从 scratch 构建。我们知道我们希望提供至少 3 个部署环境,这些环境应该尽可能接近相同。

  • 每个开发人员笔记本电脑上的“飞行模式”本地环境
  • 与托管生产环境相同的基础设施上的开发或暂存环境,具有不同的用户凭据
  • 生产环境本身

这些是我们的应用程序不变量。接下来,我们必须选择我们的平台和部署模型。

我们的第一个原型

似乎有无数种选择,以及无数种可能的组合。在 2015 年年中对情况进行调查后,我们决定使用以下内容制作一个原型:

  • Amazon EC2 作为我们的云平台,包括用于持久性的 RDS
  • Docker Swarm 作为我们的“调度器”
  • Consul 用于引导 Swarm 时的服务发现
  • Weave Net 用于我们应用程序的网络和服务发现
  • Terraform 作为我们的配置器

此设置定义快速且部署快速,因此是验证我们想法可行性的好方法。但是我们很快就遇到了问题。

  • Terraform 对 Docker 作为配置器 的支持非常基础,我们在尝试使用它来驱动 Swarm 时发现了一些 错误
  • 主要由于上述原因,使用 Terraform 管理 Docker 容器的零停机部署非常困难。
  • Swarm 的存在理由是抽象多节点容器调度的特殊性,使其隐藏在熟悉的 Docker CLI/API 命令之后。但我们得出的结论是,该 API 对于在生产中大规模运行所必需的操作来说表达能力不足。
  • 在节点故障的情况下,Swarm 不提供任何容错。

我们在设计工作流程时也犯了一些错误。

  • 我们在构建时使用其目标环境标记每个容器,这简化了我们的 Terraform 定义,但实际上迫使我们通过镜像存储库管理我们的版本。该责任应属于调度器,而不是工件存储。
  • 因此,每次部署都需要将工件推送到所有主机。这使得部署速度缓慢,回滚令人难以忍受。
  • Terraform 旨在配置基础设施,而不是云应用程序。该过程比我们希望的更慢、更深思熟虑。将新版本的东西运送到生产环境需要大约 30 分钟。

当很明显该服务具有潜力时,我们重新评估了部署模型,着眼于长期发展。

基于 Kubernetes 重构

仅仅几个月的时间,情况就发生了很大的变化。

  • HashiCorp 发布了 Nomad
  • Kubernetes 达到了 1.0 版本
  • Swarm 即将达到 1.0 版本

虽然我们的许多问题可以在不进行根本性架构更改的情况下解决,但我们希望通过加入现有生态系统并利用其贡献者的经验和辛勤工作来利用行业进步。

经过一些内部讨论,我们对 Nomad 和 Kubernetes 进行了小规模的试用。我们非常喜欢 Nomad,但觉得现在信任它来处理我们的生产服务还为时过早。此外,我们发现 Kubernetes 开发人员对 GitHub 上的问题响应最快。因此,我们决定使用 Kubernetes。

本地 Kubernetes

首先,我们将使用 Kubernetes 复制我们的飞行模式本地环境。由于我们的开发人员同时使用 Mac 和 Linux 笔记本电脑,因此本地环境的容器化非常重要。因此,我们希望 Kubernetes 组件本身(kubelet、API 服务器等)在容器中运行。

我们遇到了两个主要问题。首先,最广泛地来说,从头开始创建 Kubernetes 集群非常困难,因为它需要深入了解 Kubernetes 的工作原理,并且需要相当多的时间才能使各个部分协同工作。local-cluster-up.sh 看起来像是一个 Kubernetes 开发人员的工具,没有利用容器,而且我们找到的第三方解决方案(如 Kubernetes Solo)需要专用的 VM 或特定于平台。

其次,容器化的 Kubernetes 仍然缺少几个重要部分。按照 官方 Kubernetes Docker 指南,会产生一个没有证书或服务发现的裸机集群。我们还遇到了一些可用性问题(#16586#17157),我们通过 提交补丁 并从 master 构建我们自己的 hyperkube 镜像 来解决了这些问题。

最后,我们通过创建我们自己的配置脚本使事情正常工作。它需要执行诸如 生成 PKI 密钥和证书 以及 配置 DNS 附加组件 之类的操作,这需要几次尝试才能正确。我们还了解到有一个 提交将证书生成添加到 Docker 构建中,因此在不久的将来情况可能会变得更容易。

AWS 上的 Kubernetes

接下来,我们将 Kubernetes 部署到 AWS,并将其与其他 AWS 组件连接起来。我们希望快速在生产中启动该服务,并且我们只需要支持 Amazon,因此我们决定在不使用 Weave Net 的情况下执行此操作,并使用预先存在的配置解决方案。但是我们肯定会在不久的将来重新考虑此决定,通过 Kubernetes 插件利用 Weave Net。

理想情况下,我们会使用 Terraform 资源,并且我们找到了几个:kraken(使用 Ansible),kubestack(与 GCE 耦合),kubernetes-coreos-terraform(过时的 Kubernetes)和 coreos-kubernetes。但是它们都构建在 CoreOS 之上,这是我们一开始想避免的额外移动部分。(在我们的下一次迭代中,我们可能会试用 CoreOS。)如果您使用 Ansible,则主存储库中有 可用的 playbook。还有社区驱动的 Chef cookbooksPuppet 模块。我预计这个社区会在这里快速发展。

唯一其他可行的选择似乎是 kube-up,它是一组脚本,用于在各种云提供商上配置 Kubernetes。默认情况下,kube-up 在 AWS 上会将主节点和工作节点放置在它们自己的 VPC(虚拟私有云)中。但是,我们的 RDS 实例是在区域默认 VPC 中配置的,这意味着从 Kubernetes 工作节点到数据库的通信只能通过 VPC 对等连接或手动打开 RDS VPC 的防火墙规则来实现。

为了让流量穿过 VPC 对等链路,你的目标 IP 需要在目标 VPC 的私有地址范围内。但是,事实证明,从同一 VPC 之外的任何地方解析 RDS 实例的主机名都会产生公共 IP。执行解析很重要,因为 RDS 保留更改 IP 以进行维护的权利。这在之前的架构中从来不是问题,因为我们的 Terraform 脚本只是将所有内容都放在同一个 VPC 中。所以我认为我也应该在 Kubernetes 中尝试相同的做法;kube-up 脚本表面上支持通过指定 VPC_ID 环境变量安装到现有的 VPC 中,所以我尝试将 Kubernetes 安装到 RDS VPC 中。kube-up 似乎成功了,但是通过 ELB 的服务集成中断了,并且通过 kube-down 进行的拆除也停止工作了。经过一段时间后,我们认为最好让 kube-up 保留其默认设置,并在 RDS VPC 中打了一个洞。

这只是我们遇到的几个小问题之一。每个问题都可以单独解决,但使用 shell 脚本来配置远程状态的内在脆弱性似乎是实际的根本原因。我们完全期望 Terraform、Ansible、Chef、Puppet 等软件包会继续成熟,并希望尽快切换。

除了配置之外,Kubernetes/AWS 集成还有很多优点。例如,正确类型的 Kubernetes 服务会自动生成 ELB,并且 Kubernetes 在此处的生命周期管理方面做得很好。此外,Kubernetes 的领域模型——服务、Pod复制控制器标签和选择器模型等等——是连贯的,并且似乎为用户提供了适当的表达能力,尽管定义文件确实倾向于不必要地停顿。kubectl 工具很好,尽管乍一看令人望而生畏。特别是滚动更新命令非常出色:完全符合我期望的此类系统的语义和行为。实际上,一旦 Kubernetes 启动并运行,它就能正常工作,并且完全符合我的预期。这是一件非常重要的事情。

结论 

在与机器搏斗了几个星期后,我们能够解决所有集成问题,并已在生产环境中推出一个相当健壮的基于 Kubernetes 的系统。

  • 配置 Kubernetes 很困难,因为它具有复杂的架构和不成熟的配置方式。这种情况显示出改进的迹象。 
  • Kubernetes 的非可选 安全模型需要时间才能正确掌握。 
  • Kubernetes 的 领域语言与问题域非常匹配。 
  • 我们在操作我们的应用程序方面更有信心(而且速度也快了很多)。 
  • 我们很高兴成为不断增长的 Kubernetes 用户群的一部分,尽我们所能贡献问题和补丁,并从驱动当今最激动人心的软件的开源开发的良性循环中受益。 

Weave Scope 是一个开源解决方案,用于可视化和监控容器化应用程序和服务。对于托管的 Scope 服务,请在 scope.weave.works 请求加入早期访问计划。