背景
我们维护一个运行我们生产应用程序的 Ubuntu 主机“集群”。主机运行各种各样的 docker 容器,例如
- 用于容器监控和 prometheus 服务发现的 consul
- 具有多个logstash和kibana的elasticsearch集群
- 普罗米修斯
- 格拉法纳
- 内部开发的应用程序(下图中的服务 A 到 K)
每个主机也运行
- 文件节拍
- nginx
- 保活
- docker覆盖网络的领事
图片信息
- 主机 consul 在 2xxx 而不是标准的 8xxx 中公开端口
- 并非所有 docker 容器都暴露给外界,例如
elasticsearch-slave1
没有暴露的端口,但内部使用的端口显示为:9200
- docker consul 使用覆盖网络进行所有通信,并且只有
consul-master
Host1 上的端口8500
对外暴露。
配置
其中一些信息可能与问题完全无关。
主机:Ubuntu 16.04.3 LTS
主机服务
| Application | Version |
| ----------- | ---------- |
| docker | 18.03.1-ce |
| consul | v1.0.2 |
Docker 服务
| Application | Version |
| ------------- | ------- |
| consul | v1.0.2 |
| elasticsearch | 5.6.4 |
| logstash | 5.6.4 |
| kibana | 5.6.4 |
| prometheus | 2.0.0 |
码头工人服务
每台主机上的 Docker 配置如下:
[Service]
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-advertise ${THIS_MACHINES_IP}:2375 --cluster-store consul://${THIS_MACHINES_IP}:2500 --label com.domain.hostname=host05.domain.com
问题
当我们第一次部署这个配置时,它运行得非常好。但随着时间的推移,docker 覆盖网络变得越来越不可靠。HostX 上的容器将无法使用覆盖网络与 HostY 上的其他容器通信。
例如,prometheus
在 Host5service A
上从 Host1 上抓取信息,但会频繁报告“ no route to host
”或“ context deadline exceeded
”。如果我docker exec
进入prometheus
容器并尝试 ping 或 curl service A
,我只会收到超时。但是,如果我docker exec
进入service A
并尝试 ping 和 curlprometheus
数据包通过,这似乎“唤醒”了网络。现在prometheus
可以再次看到服务。
多个服务之间会出现同样的问题 - 这经常导致logstash
无法发布elasticsearch
或elasticsearch-master
无法联系slaves
破坏集群的服务。
因为这个设置在我们的生产环境中被积极使用,所以我们无法承受这样的网络停机时间。我已经实现了一组计划的作业,这些作业在各种服务之间进行 curl/ping 以保持网络活跃。这显然不是一个好的长期解决方案!
更糟糕的是,有时网络变得如此糟糕,以至于 curl/ping 作业无济于事,并且重新启动主机或 docker 也没有任何效果。我找到的唯一解决方案是
- 创建一个新
temporary overlay
网络 - 从 断开每个容器
primary overlay
并将它们连接到temporary overlay
- 删除
primary overlay
- 创建一个新的
primary overlay
- 从 断开每个容器
temporary overlay
并将它们连接到primary overlay
- 删除
temporary overlay
这种方法是迄今为止我找到的完全恢复网络的最佳解决方案。然后它将运行良好一段时间,然后再次跌倒。
问题
对我来说最紧迫的问题是如何调试这个问题并找到根本原因?
有一些人遇到过这个问题,但它通常是在小型设置中,并且与上面的规模不同。目前感觉就像我在运行薛定谔的网络......
其次 -有没有更好的方法来实现覆盖网络?
我已经开始尝试,weave
但Open vSwitch
都不是当前网络的一个很好的替代品。
Weave需要重新部署所有容器(这是可能的),但它为每个容器添加了一个辅助网络接口,并且该ethwe
接口不是导致问题consul
并prometheus
绑定到特定接口/地址的主要接口。
Open vSwitch似乎是一个替代品,但我无法让它与 LTS 版本 (2.5.x) 一起工作,不得不从源代码构建 2.10.x。这似乎最初有效,但elasticsearch
不是集群,consul
似乎真的很难通过网络进行通信。prometheus
由于某种原因也无法查询consul
。我假设交换机丢弃了一些数据包,这可能只是配置问题。
编辑 - 28/09/2018
自从发布这个问题以来,我一直在测试使用 Docker Swarm 来管理覆盖网络。
到目前为止,它运行良好,网络并没有像使用 consul 集群存储时那样随机停止工作。但是,存在一些关键差异和一些常见故障。例如:
docker network inspect <my overlay network>
在主机上执行只会显示在该主机上运行的容器。当使用 Consul 作为集群存储时,您可以从任何主机查看整个网络。- 仍然有可能使网络进入容器无法看到彼此的不良状态。这可以通过相对快速地停止、删除和重新创建容器(与以前的名称相同)来实现。在这种情况下,现有容器继续使用旧的DNS 条目并且无法连接。