使用Mesos/Marathon连接Docker容器

20

到目前为止,我已经成功使用Mesos、Marathon和Docker来管理一组服务器以及我在这些服务器上部署的容器。但是,我现在想进一步开始做一些事情,比如自动将haproxy容器与每个启动的主docker服务进行链接,或者提供其他基于守护程序和容器化的服务,并将它们链接起来,仅对单个父容器可用。

通常情况下,我会先启动帮助程序服务并为其命名,然后当我启动真实服务时,我会将其链接到这个帮助程序,并且一切都很好。但是这种模型如何适应Marathon和Mesos呢?目前看来,容器化似乎假定只有一个容器。

我有一个想法是首先在任何可以找到的主机上启动帮助程序服务,然后为真实服务添加一个约束条件,即主机名=帮助程序服务的主机名,但这似乎会导致资源提供和资源竞争方面出现问题。

我也考虑过向Docker或启动Docker容器的执行脚本提供“嵌入”或“深度链接”功能。

在我走下任何这些道路之前,我想找出是否有人已经解决了这个问题,或者我只是太过于思考了。

谢谢!

1个回答

26

你正在未知的领域中徘徊! ☺

这里有多种方法,但没有一种是完美的,不过在将来的 Docker 版本中情况会得到改善,这要归功于编排钩子。

其中一种方法是使用传统的服务发现和注册。例如,当服务启动时,它将找出其公开可用的地址,并在 Zookeeper、Etcd 或甚至 Redis 中注册自己。由于服务要找出其公开可用的地址并不容易(除非您采用某些约定,例如始终映射端口 X:X 而不是让 Docker 分配随机端口),因此您可能希望从外部进行注册。这意味着您的编排层(在这种情况下为 Mesos)将启动容器,然后找出主机和端口,并将其放入您的服务发现系统中。我对 Marathon 不是特别熟悉,但您应该能够为其注册钩子。然后,其他容器只需在服务发现注册表中查找端点地址即可,简单明了。

您还可以查看 Skydock,它会自动向 Skydns 注册您的容器的 DNS 名称。但是,目前它只支持单个主机,因此如果您喜欢这个想法,您需要扩展它以支持多个主机,或者可能需要 SRV 记录。

另一种方法是使用“众所周知的入口点”。实际上,这是服务发现的简化情况。这意味着您将确保您的服务始终在预设的主机和端口上运行,以便可以静态地使用这些地址。当然,这很糟糕(因为当您想要为测试/演示目的再现环境时,它会使您的生活更加困难),但如果您完全不了解服务发现,那么这可能是一个开始。

您还可以使用 Pipework 创建跨越多个主机的一个(或多个)虚拟网络,并将您的容器绑定在一起。Pipework 将允许您手动分配 IP 地址,或通过 DHCP 自动分配。虽然这种方法不建议使用,但如果您还想将容器插入到现有的网络架构中(例如 VLAN...)则非常适合。

无论您选择哪种解决方案,我强烈建议“假装”您正在使用链接。即,不要将您的应用程序配置硬编码连接到(随机示例)my-postgresql-db:5432,而是使用环境变量DB_PORT_5432_TCP_ADDRDB_PORT_5432_TCP_PORT(就像它是一个链接),并在启动容器时设置这些变量。这样,如果您将容器折叠到一个没有服务发现等复杂特性的环境中,您可以轻松地回退到链接,而无需努力。

2
所以对我来说很重要的一件事是容器的本地性。我可以相对容易地进行某种发现以找到其他容器,但我正在寻找一种超越此的优化,它会强制马拉松启动一组容器(例如nginx + rails +凭据守护程序),每个容器都在自己的容器中。显然,我需要提交一个补丁,我应该看看Marathon而不是docker吗? - William Thurston
只是为了确保我理解正确——你的意思是“...这将强制马拉松启动一组容器(...)每个容器都在自己的主机上”吗?也就是说,强制容器位于不同的主机上? - jpetazzo
抱歉,我想在单个主机上进行分组,例如每个服务附加一个本地haproxy。 我认为这里的正确路径是使用自定义Mesos执行程序,它知道如何从Marathon获取附加参数,分叉自身,并管理子代,确保如果任何一个部分停止运行,则整个组都会重新启动。 - William Thurston
明白了。说实话,我对马拉松/Mesos并不是很了解。我不知道现有的作业是否可以用作资源,这样您就可以说“这个后端服务算作提供一种类型为后端的资源单位;现在请在某个地方启动一个 haproxy 服务,知道它需要一种类型为后端的单位才能运行(还需要 X 和 Y 单位的 RAM 和 CPU)"。 - jpetazzo
为什么不将这两个应用程序分组,第二个应该依赖于第一个才能正常运行,然后使用Consul(+ consul-marathon)服务发现将它们链接起来。在第二个应用程序中,您只需指定app1.service.consul即可。 - ady8531

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接