赢得自定义新的遗物弹球机!只需将数据书呆子提交以注册Futureestack。 现在注册

在运营领域,库存管理是一项乏味但必不可少的任务,它回答了一些基本问题:哪些机器属于哪些团队?哪些机器在使用中?他们在那里多久了?然而,获得这些问题的有用答案可能是一件困难的事情——特别是当团队在动态和快速扩展的环境中运行时。

这正是New Relic的容器编排团队(内部称为container fabric)最近面临的情况。我们的解决方案,利用了Kubernetes API服务器和支持自定义资源的定义,为我们提供更强大和可扩展的方式来处理库存管理 - 并且正如我们解释的那样,同样的功能对于许多其他应用程序也很有用。

一定要检查我们的视频回放下“Kubernetes数据库”的KubeCon + CloudNativeCon 2018会议上发言从这篇文章被改编的。

挑战:保持领先于扩展面料

New Relic Container Fabric团队构建并维护公司内部平台,用于部署和维护容器化服务。我们的开发人员将他们的笔记本电脑中的代码放入容器中,然后我们在我们的平台上运行这些容器。

按照现代企业标准,这个团队管理的环境并不庞大,但它庞大且增长迅速。我们目前管理着大约1000台机器,其中大部分运行在物理硬件上,分布在三个基础设施提供商之间,包括我们自己的裸金属数据中心。此外,我们最近扩大了我们的基础设施专用欧洲地区这是增加复杂性的必要举措。

由于集装箱布平台的发展,我们目前的做法,以库存管理是可能产生业务瓶颈。在多个地区工作,例如,增加了安全的网络连接我们的业务流程服务必须经过数。

要创建真理为我们编排服务的单一来源,我们使用了Kubernetes API服务器的自定义对象定义,功能,设计出一种新的库存管理解决方案。这是更有效和更具扩展性,允许集装箱面料与New Relic的其余一起成长。更妙的是,该解决方案基于熟悉的技术,而且我们已经找到方法来利用相同的技术用于其它应用。

大规模库存的问题

Container Fabric软件环境目前正在运行中间层DC /操作系统:一个开源的、分布式的操作系统Apache Mesos.,使用马拉松提供容器编排服务。

在Kubernetes出现在主流之前开发了集装箱织物。我们在我们需要的最稳定可靠的选择时选择了DC / OS,它为我们提供了适合运行服务的服务。然而,管理DC / OS本身并没有那么容易。因此,集装箱结构团队计划迁移到Kubernetes。

我们以前的做法,以库存管理使用Ansible.起程拓殖要定义,枚举,配置和管理我们的基础架构。设置新计算机涉及Terraform运行,从我们的基础架构提供商中请求提供。一旦提供商创建了我们所要求的机器,我们再次使用ANSIble询问提供商互联网通信相同我们刚刚向Terraform要求的资源;然后我们请主人把它投入使用。

这个过程需要整个组件的网络连接。例如,处理编排的Ansible实例通过VPN连接到基础设施提供商,并使用相同的VPN与新机器通信,以使它们工作。

最后,正如指出的那样,我们去年增加了一个新的欧洲区域.这增加了一组新的网络需求——包括另一个vpn——因此又增加了一层复杂性。随着Container Fabric继续跨多区域架构扩展,我们尤其关注日益复杂的网络需求。


一个非常复杂的未来愿景——除非我们找到一种方法来简化跟踪和管理我们的容器Fabric基础设施的过程。

然而,我们很快意识到,Container Fabric面临的真正挑战与其说是连接问题,不如说是库存问题。我们需要的是关于机器的当前数据——名称、位置、状态——以保持“在我们的基础设施中”正在发生的事情的最新情况。然后,如果需要,业务编制可以使适当的VPN连接访问区域和集群,以更新机器配置。知道发生了什么,发生在哪里,是我们成长过程中减少劳动的关键。

搜索解决方案亚博直播平台

在这一点上,我们开始寻找解决库存问题的办法。亚博直播平台在我们看来,前三个选项存在致命的缺陷。

选项1:使用Terraform状态数据创建解决方案。大多数Terraform用户都很熟悉在“terraform.tfstate”文件:自定义JavaScript对象符号(JSON)格式文件,该文件记录了从模板中的Terraform资源到这些资源在现实世界中的表示的映射。我们评估了这种Terraform状态情报作为分布式和可扩展的库存管理解决方案的基础,但我们发现了这种方法至少有两个破坏交易的缺点。

  1. 首先,文件本身仅响应按需事件(例如Terraform Plan或Refresh命令)更新。这不是基础设施的实时反映。
  2. 第二,因为我们正在处理一个简单的,静态的文本文件,每一次更新,不管多么小,将需要的文件全部重写。这增加了多个客户端可以在对方试图执行更新时踩的风险。

选项2:购买一个商业的DCIM解决方案。我们评估了几种数据中心基础架构管理(DCIM)解决方案,例如亚博直播平台Device42..这些是针对运行自己的数据中心的组织 - 当然,我们适合目标市场。

DCIM产品在回答问题,基本上,“我的东西在哪里?特定机器在哪里?它是什么机架?什么是pdus?你手边有多少个硬盘?“然而,这种产品效果较低,但是,在定义和管理我们需要在库存管理解决方案中所需的更高级别抽象(例如集群和区域)。

选项3:采用DC/OS解决库存管理问题。最后,我们看着DC / OS本身,以确定任何可能有用的功能,我们可以利用的库存解决方案。不幸的是,DC / OS还没有为这种类型的工作Mesos,该技术在它的中心的建成,是架构一个更敏感的图案。Mesos不会在集群中保持机器一个“理想状态”,甚至一台机器上的服务。

值得注意的是DC/OS包括Apache zookeeper.,分布式信息服务,ettd.,一个分布式键值存储,作为其默认安装的一部分。我们考虑使用这些服务来实现我们正在寻找的功能。然而,最终的解决方案不能用于更高级别的抽象,而且它也不能提供我们无法从部署自己的这些服务安装中获得的好处。

取得的重要经验

尽管我们最初的搜索未能找到一个可接受的库存管理解决方案,但它确实帮助我们定义了所需的需求和功能:

  • 信息的单一来源的库存管理。再也我们需要拆分基于基础设施提供商的代码路径。
  • 从任何地方更新的能力而无需建立VPN连接。这个要求对所有数据中心都是必要的。
  • 与Ansible动态库存的兼容性。这是必要的,因为我们正在寻找一个不同的库存管理解决方案,但我们也希望我们的现行做法保持到编排不变暂时。
  • 生产性能。这是一个明显的需求,如果我们打算扩展解决方案,监控等功能以外的库存管理。
  • 本地有意义和可扩展的对象表示。具体来说,我们需要能够处理更高层次的抽象,而不是“我的东西在哪里?”这些问题通常是DCIM解决方案的强项。亚博直播平台

第四次是魅力:登陆Kubernetes API服务器

我们已经非常熟悉Kubernetes,这是New Relic的首选容器编排平台。真正把Kubernetes在我们的雷达作为一种库存管理的选择是我们的实现,它有一些DC / OS不为积分,集中配置的服务。

kube-apiserver是Kubernetes集群的核心组件之一;它包含代表群集行为的所有对象的声明性状态。它与一个旨在简化此过程的预定义对象库,包括部署,有状态集,服务等的表示。但是,Kube-Apiserver也支持自定义资源.这些资源主要用于促进更复杂的应用程序部署。但没有理由说它们不能发挥其他功能。

事实上,我们意识到,KUBE-API服务器能够满足全部我们的库存管理要求。但首先,我们必须创建三个额外的组件:

  1. 一个基本的对象结构,实际上,是一个yaml.-为kube-apiserver定义自定义资源。这将在服务器内部创建自定义资源定义(CRD)对象(我们称之为宿主对象)。
  2. 服务每一个基础设施供应商的内部运行枚举我们已经在那里运行的主机并发送列表返回KUBE-API服务器。这会在KUBE-API服务器主机对象代表在一个特定的供应商运行的个人计算机。
  3. 动态库存脚本,让Ansible与KUBE-API服务器和使用主机对象进行通信。主机对象将通过什么,我们称其为“提取器” - 一个服务实例进行填充,从在我们新的库存系统使用特定供应商检索所需的主机数据。

实现我们的kube-apiserver解决方案

我们的实现过程很简单,而且比典型的Kubernetes部署简单得多。我们并没有按照传统的方式部署Kubernetes;我们只使用kube-apiserver,以及kube-controller-manager(用于cert管理)和etcd3(用于对象存储)。在这个过程中,我们没有部署任何豆荚或任何工作负载,我们也没有做任何豆荚网络。可做的事越来越少,过程出错的途径也越来越少。


我们的部署,这依赖于选择Kubenetes概述组件 - 尤其是,KUBE-API服务器,而不涉及全面Kubernetes集群部署的复杂性。

这意味着我们的第一步是遵循Kubernetes硬盘的方式但在第8步 - 或者停止自举Kubernetes控制平面.这给了我们一个正在运行的kube-apiserver实例,我们可以使用它工作。有了它,我们在现有的Terraform和Ansible工具链中编写了编排,以构建更多的kube-apiserver实例,用于登台和生产。

接下来,我们创建了顶层要求我们的主机对象作为YAML文件,我们使用kubectl申请在Kube-Apiserver中创建它们。

然后,我们准备把一些去的代码从我们的提供者获取主机数据并使用数据填充这些主机对象。这涉及:

  1. 写作去结构作为要在客户机代码中使用的宿主crd的表示。
  2. 使用Kubernetes代码生成器要创建可以在这些CRD对象上执行创建,读取,更新和删除(CRUD)操作的GO客户端代码。
  3. 最后,编写的提取程序代码块为每个基础设施供应商,可以自己机器的表示形式转换到我们的主机。

fetcher的服务循环是这样的:

  1. 取出器查询提供的API为所有我们希望把我们的库存,通常由标签过滤主机。
  2. 提供商的API服务器与我们的主机列表响应。我们转换这种反应成细末结构与主机CRD兼容。
  3. 我们使用生成的客户机库来使用来自提供者的更新数据在kube-apiserver上更新或创建主机对象。

“fetcher”的服务循环,该服务从特定提供商中检索所需的主机数据以用于我们的新库存系统

CRD和Go结构代码示例

这是YAML中我们主持人CRD的缩短视图:

这是我们的主机看起来像Go struct的形式,我们用于内部开发工作:

ObjectMeta存储CRD本身的注释和标签。规格表示主机对象的期望状态,并且状态表示当前状态。

标签和注释对于搜索和过滤等任务很有用;例如,您可以使用命令行或API请求查看在特定提供者的基础设施上作为日志机运行的所有主机。我们还使用注释来存储关于主机的数据,以便在下游配置脚本中使用。

与解决方案合作

完整的解决方案创建具有无限扩展能力的基础设施库存数据库。

当然,数据库要有用,需要客户端,对于这个项目来说,这意味着Ansible动态库存脚本。我们的是Python,并为kube-apiserver客户端使用Kubernetes pip包。

Kubernetes Python库从kube-apiserver返回一个大的主机对象字典,我们将其转换为适合Ansible的JSON输出。然后,我们像以前一样将Ansible用于编制服务。

kube-apiserver在规模上表现出色的两个原因

将kube-apiserver用作库存管理数据库对我们的操作能力有重大影响。我们能够为我们的集群定义声明性的所需状态,并以分解的方式构建集群服务—kube-apiserver的客户端不需要了解彼此,即使在同时处理对象时也是如此。

因此,我们不再与逐步的,手动和高度迭代的过程相关联,并具有很多前后交换。我们现在更好地准备在规模上运营,并充满信心地进入多个区域的未来。

kubernetes,特别是kube-apiserver,有几个额外的原因很适合这个角色:

  1. Kubernetes支持使用TLS相互认证。这让我们摆脱了vpn和相关的网络连接要求,这些要求在规模上增加了比我们准备接受的更多的复杂性。
  2. 该KUBE-API服务器手柄一致性排序。如果一个客户端试图向一个对象发出更新请求,但另一个服务器已经处理了该更改,kube-apiserver将通知该客户端。这使得我们更容易进行动态配置更改——例如,在新主机配置时将监控逻辑部署到新主机上——这在以前需要我们依赖于git和Ansible的一些繁重工作。

一个为未来做好准备的解决方案

如前所述,很容易为基于Kube-Apiserver的库存管理解决方案设想其他应用程序。事实上,我们已经建立了一个用于从我们的库存产生监控配置的轮询系统。作为我们舰队更改的主机,我们需要动态构建或销毁每个主机的监控。这用于要求git commit添加主机名每一个在舰队中的一个主持人改变了。现在,我们甚至没有考虑它 - 我们的监视服务器订阅主机对象中的更改,并自己生成警报配置。

我们甚至采取了这一点,并建立了一个更改的Orchestration系统,用于运行Ansible。从每个主机上监视其自己的主机CRD记录的守护进程开始,我们可以开始将字段放入每个主机的规格节,守护程序可以响应:触发自己的ansible运行,移动主机进出维护,或升级操作系统。拥有一个有权威的普遍访问的位置的所需主机状态是我们需要从根本上改变我们的日常运营与软件所需的立足点。

这种方法也是我们的长期计划迁移到Kubernetes的长期计划的一个很好的起点 - 许多其他运营团队正在计划的旅程。

一定要查看我们的Kubecon 2018年会议视频,“Kubernetes数据库,“赖以这篇文章是基于: