Docker生态系统系列之三:服务发现和分布式配置存储


【编者的话】本文介绍了服务发现与全局可读配置存储两部分内容,不仅介绍了工作原理和工作方式,也介绍了与之相关的故障检测、重配置和安全问题,最后还介绍了常用的服务发现项目。整篇文章将这个知识点介绍的很全面细致,让读者能够对服务发现和全局可读配置存储有一个全面的认识,值得学习。

介绍

容器给寻找大规模设计与部署应用的需求提供了一个优雅的解决方案。在Docker提供实际容器技术的同时,许多其他的项目也在协助开发在部署环境中所需要的引导和沟通的工具。

多种Docker环境依赖的核心技术之一是服务发现。服务发现可以让一个应用或者组件发现其运行环境以及其它应用或组件的信息。它通常采用的是分布式key-value的存储方式,而且它还用来作为一般查询配置细节信息的地方。用户配置一个服务发现工具就可以将实际容器跟运行配置分离开,这样用户就可以在多个环境中复用同一个镜像。

在这篇向导中,我们将讨论在一个Docker集群环境中服务发现工具带来的好处。主要关注常规概念,在需要的地方会用详细的例子来描述。

服务发现与全局可读配置存储

服务发现的基本思想是任何一个应用的实例能够以编程的方式获取当前环境的细节。这是为了让新的实例可以嵌入到现有的应用环境而不需要人工干预。服务发现工具通常是用全局可访问的存储信息注册表来实现,它存储了当前正在运行的实例或者服务的信息。大多数情况下,为了使这个配置具有容错与扩展能力,这个工具分布式地存储在基础设施中的多个宿主机上。

虽然服务发现平台的初衷是提供连接信息来连接不同组件的,但是它们更普遍地是用来存储任何类型的配置信息。许多部署工具通过写入它们的配置信息给发现工具来实现这个特性。如果容器配置了这些,它们就可以去查询这些预配置信息,并根据这些信息来调整自身行为。

服务发现是怎么工作呢?

每一个服务发现工具都会提供一套API,使得组件可以用其来设置或搜索数据。正是如此,对于每一个组件,服务发现的地址要么强制编码到程序或容器内部,要么在运行时以参数形式提供。通常来说,发现服务用键值对形式实现,采用标准http协议交互。

服务发现门户的工作方式是:当每一个服务启动上线之后,他们通过发现工具来注册自身信息。它记录了一个相关组件若想使用某服务时的全部必要信息。例如,一个MySQL数据库服务会在这注册它运行的ip和端口,如有必要,登录时的用户名和密码也会留下。

当一个服务的消费者上线时,它能够在预设的终端查询该服务的相关信息。然后它就可以基于查到的信息与其需要的组件进行交互。负载均衡就是一个很好的例子,它可以通过查询服务发现得到各个后端节点承受的流量数,然后根据这个信息来调整配置。

这可将配置信息从容器内拿出。一个好处是可以让组件容器更加灵活,并不受限于特定的配置信息。另一个好处是使得组件与一个新的相关服务实例交互时变得简单,可以动态进行调整配置。

配置存储是如何关联起来的?

全局分布式服务发现系统的一个主要优势是它可以存储任何类型的组件运行时所需的配置信息。这就意味着可以从容器内将更多的配置信息抽取出去,并放入更大的运行环境中。

通常来说,为了让这个过程更有效率,应用在设计时应该赋上合理的默认值,并且在运行时可以通过查询配置存储来覆盖这些值。这使得运用配置存储跟在执行命令行标记时的工作方式类似。区别在于,通过一个全局配置存储,可以不做额外工作就能够对所有组件的实例进行同样的配置操作。

配置存储如何帮助集群的管理?

在Docker部署中,存储于其中且最初可能不太明显的分布式键值的一个功能是对集群成员的存储和管理。配置存储是追踪宿主机成员变更和管理工具的最好环境。

一些可能会存在分布式键值的存储个人宿主机的信息是:
  • 宿主机IP
  • 宿主机自身的链接信息
  • 跟调度信息有关的标签或元数据信息
  • 集群中的角色(如果是采用了主从模式的集群)


在正常情况下,使用一个服务发现平台时,这些细节可能不是你需要考虑的。但是他们为管理工具提供了一个可以查询或修改集群自身信息的地方。

故障检测怎么实现?

故障检测的实现方式也有很多种。需要考虑的是如果一个组件出现故障,服务发现能否更新状态指出该组件不能再提供服务。这种信息是至关重要的,关系到将应用或服务故障可能性降到最低。

许多服务发现平台允许赋值时带一个可配置的超时时间。组件可以设置一个超时时间,并能定期去请求服务发现来重置超时时间。如果该组件出现故障,超时时间达到设定值,那么这个组件的连接信息就会从服务发现的存储中被去掉。超时时间长度在很大程度上是快速应用程序对组件故障的函数。

这也可以通过将一个基本的“助手”容器与每一个组件相连来实现,而它们唯一的责任是定期的健康检查组件以及组件出现故障时更新注册表。这种类型的架构值得担忧的是,如果辅助容器出现故障,将导致不正确的信息在存储中。一些系统解决这个问题的方法是在服务发现的工具中定义健康检查。这样,发现平台本身就可以定期检查已注册组件是否仍然可用。

当细节变化时,配置服务会如何?

对于基本的服务发现模型来说,一个关键的改进就是动态重新配置。普通服务发现工具允许用户通过检查在启动时的信息来影响组件的初始配置,而动态重新配置涉及配置组件来反映配置存储中的新信息。例如,当你在运行一个负载均衡,后端服务器上的健康检查可能会提示集群中的某一个成员出现故障了。运行中的成员机器需要知道这个信息,并调整配置信息和重新加载它的负载。

这个有多种方式来实现。由于负载均衡的例子是这个功能的主要应用场景之一,许多现有的项目专注在当配置变动时重新配置负载均衡。常见的是HAProxy配置调整,这要归结于在负载均衡领域内它的普遍性。

某些项目更加灵活,它们可在任何类型的软件中被用来触发变更。这些工具周期性的去请求服务发现工具,并且当变更被发现时,利用模板系统和服务发现工具中的值来生成新配置文件。当配置文件生成结束,相应的服务将被重新加载。

这种类型的动态配置在构建过程中需要更多的规划和配置,因为这些所有的策略都需要存在于组件容器之中。这使得组件容器负责调整自身的配置。找出需要存在服务发现工具中的必要参数值并设计一个适当的数据结构以便使用,这是该系统的另一个技术挑战,但是它可以带来可观的效益和灵活性。

安全方面如何?

许多人初次接触全局配置存储时担心的一个问题是访问的安全性。将连接信息存储在全局可访问的存储中真的合适么?

这个问题的答案很大程度上依赖于你准备在存储中存放的内容以及保护你的数据需要多少层的安全等级。几乎所有的服务发现工具可以采用SSL/TLS加密链接。对于一些服务,隐私性可能不是最重要的,而发现服务放在内网中也可能让人满意。但是,大多数的应用会从它额外的安全性上获益。

有许多不同的方法来解决这个问题,同时各种项目也都提供他们自己的解决方案。一个项目的解决方案是继续允许开放发现服务平台本身,但是对于写入数据进行加密,使用者使用的信息必须用相应的密钥解码从服务发现中获取。其他组件不可以获取到未加密的数据。

还有不同的方法,一些服务发现工具实现了访问控制列表,将不同的键值切分到不同的分组中。他们可以根据访的问需要来制定不同的秘钥从而访问相应的分组。这种简单的方式既保证了能够给特定组件提供信息又保证了对其他组件的不可访问性。每个组件都可以被配置为只允许访问它所需要的连接信息。

有哪些常见的服务发现工具?

既然我们已经讨论了一些服务发现工具和全局分布式键值存储的一般特点和功能,下面我们来介绍几个与这些概念有关的项目。

一些常见的服务发现工具:
  • etcd:这是CoreOS的创建者提供的工具,面向容器和宿主机提供服务发现和全局配置存储功能。它在每个宿主机上有基于http协议的API和命令行的客户端。
  • consul:这个服务发现平台有很多高级的特性,使得它脱颖而出,例如:配置健康检查、ACL功能、HAProxy配置等等。
  • zookeeper:这个工具较上面两个都比较老,提供一个更加成熟的平台和一些新特性。


一些基本服务发现工具的扩展项目:
  • crypt:Crypt允许组件通过采用公钥加密的方式来保护它们的信息。需要读取数据的组件会被分配密钥,而其他组件则不能读取数据。
  • confd:Confd项目旨在基于服务发现的变化,而动态重新配置任意应用程序。该系统包含了一个工具来监测节点中的变化、一个模板系统来根据获取到的值来生成配置文件,并能够重新加载受影响的应用。
  • vulcand:Vulcand在组件中作为负载均衡使用。它使用etcd作为后端,并基于监测变更来调整它的配置。
  • marathon:虽然marathon主要是调度器(后续介绍),它也实现了一个基本的重新加载HAProxy的功能,当发现变更时它来协调可用的服务。
  • frontrunner:这个项目嵌入在marathon中对HAProxy的更新提供一个更稳定的解决方案。
  • synapse:这个项目引入了嵌入式的HAProxy组件,它能够发送流量给各个组件。
  • nerve:它被用来与synapse结合在一起来为各个组件提供健康检查,如果组件不可用,nerve将更新synapse并将该组件移除出去。


总结

服务发现工具和全局配置存储使得Docker容器可以适应它们当前所处环境并嵌入现有的组件。这是实现提供方便、容易扩展和部署的功能的一个重要的先决条件,该功能通过允许组件跟踪和应对他们所在环境变化来实现。

在下一个指南中,我们将探讨Docker容器和宿主机之间用自定义的网络配置进行通信。

本系列的其他文章

Docker已经为开发者和管理员提供一个简单的平台来创建和部署可扩展的应用。在这个系列中,我们将探索Docker如何与其他组件整合在一起,并用它们提供的工具集来便捷地提供高可用性的分布式系统。
  1. 常用组件介绍(已翻译)
  2. 容器化的综述(已翻译)
  3. 服务发现和分布式配置存储(本文)
  4. 网络与通信(翻译完毕)
  5. 调度与编排(翻译完毕)


原文:The Docker Ecosystem: Service Discovery and Distributed Configuration Stores (译者:陈杰 校对:田浩浩)

===============================================
译者介绍
陈杰,北京理工大学计算机学院在读博士,研究方向是自然语言处理在企业网络信誉评价方面的应用,平时也乐于去实现一些突发的想法。在疲于配置系统环境时发现了Docker,跟大家一起学习、使用和研究Docker。

2 个评论

这是篇好文章,居然没人回复。整个系列都很不错。一些基本服务发现工具的扩展项目:应该还少了 Bamboo 和 Netflix 的 Eureka。Netflix 的解决方案似乎是自成一体,是去LB的服务发现机制。其中没有 LB,而是每个模块从配置服务器中(在 Netflix 中是 Eureka,其它的多是 Zookeeper 或者 Etcd)找到服务地址,然后去访问。但 Netflix 服务治理的细节我并不好说,可能是一种混合的方式。
学习中

要回复文章请先登录注册