0

我有 3 个容器在 3 台机器上运行。一种叫做石墨,一种叫做背面,一种叫做正面。前面的容器需要其他两个运行,所以我像这样分别链接它们:

[Unit]
Description=front hystrix


[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill front
ExecStartPre=-/usr/bin/docker rm -v front
ExecStartPre=/usr/bin/docker pull blurio/hystrixfront
ExecStart=/usr/bin/docker run  --name front --link graphite:graphite --link back:back -p 8080:8080 blurio/hystrixfront
ExecStop=/usr/bin/docker stop front

我启动了其他两个容器,等到它们启动并运行,然后用fleetctl启动这个容器,它立即失败并显示以下消息:

fleetctl status front.service
? front.service - front hystrix
   Loaded: loaded (/run/fleet/units/front.service; linked-runtime; vendor preset: disabled)
   Active: failed (Result: exit-code) since Tue 2015-05-12 13:46:08 UTC; 24s ago
  Process: 922 ExecStop=/usr/bin/docker stop front (code=exited, status=0/SUCCESS)
  Process: 912 ExecStart=/usr/bin/docker run --name front --link graphite:graphite --link back:back -p 8080:8080 blurio/hystrixfront (code=exited, status=1/FAILURE)
  Process: 902 ExecStartPre=/usr/bin/docker pull blurio/hystrixfront (code=exited, status=0/SUCCESS)
  Process: 892 ExecStartPre=/usr/bin/docker rm -v front (code=exited, status=1/FAILURE)
  Process: 885 ExecStartPre=/usr/bin/docker kill front (code=exited, status=1/FAILURE)
 Main PID: 912 (code=exited, status=1/FAILURE)

May 12 13:46:08 core-04 docker[902]: 8b9853c10955: Download complete
May 12 13:46:08 core-04 docker[902]: 0dc7a355f916: Download complete
May 12 13:46:08 core-04 docker[902]: 0dc7a355f916: Download complete
May 12 13:46:08 core-04 docker[902]: Status: Image is up to date for blurio/hystrixfront:latest
May 12 13:46:08 core-04 systemd[1]: Started front hystrix.
May 12 13:46:08 core-04 docker[912]: time="2015-05-12T13:46:08Z" level="fatal" msg="Error response from daemon: Could not get container for graphite"
May 12 13:46:08 core-04 systemd[1]: front.service: main process exited, code=exited, status=1/FAILURE
May 12 13:46:08 core-04 docker[922]: front
May 12 13:46:08 core-04 systemd[1]: Unit front.service entered failed state.
May 12 13:46:08 core-04 systemd[1]: front.service failed.

我还想包括fleetctl list-units 输出,您可以在其中看到其他两个运行没有问题。

 fleetctl list-units
UNIT                    MACHINE                         ACTIVE  SUB
back.service            0ff08b11.../172.17.8.103        active  running
front.service           69ab2600.../172.17.8.104        failed  failed
graphite.service        2886cedd.../172.17.8.101        active  running
4

1 回答 1

0

这里有几个问题。首先,您不能对 docker 使用 --link 参数。这是一个特定于 docker 的指令,用于在同一个 docker 引擎上将一个容器链接到另一个容器。在您的示例中,您有多个引擎,因此此技术不起作用。如果您想使用该技术,您将需要使用大使模式:coreos Ambassador,您可以使用 X-Fleet 指令 MachineOf: 使所有 docker 容器在同一台机器上运行,但是,我认为那会破坏你的目标。

通常使用云服务,一项服务需要另一项服务,就像您的情况一样。如果其他服务(还没有)运行,那么需要它的服务应该表现良好,要么退出,要么等待所需的服务准备好。因此,必须发现所需的服务。发现阶段和等待阶段有很多技术。例如,您可以在每个容器中编写一个“包装器”脚本。该包装器可以完成这些职责。在您的情况下,您可以在 back.service 和graphite.service 中有一个脚本,它将信息写入 etcd 数据库,例如:

ExecStartPre=/usr/bin/env etcdctl set /graphite/status ready }'

然后在前面的启动脚本中,您可以执行 etcdctl get /graphite/status 以查看容器何时准备就绪(直到准备就绪才继续)。如果您愿意,可以将 IP 地址和端口存储在石墨脚本中,以便前端脚本可以选择要连接的位置。

另一种发现技术是使用registrator。这是一个超级方便的 docker 容器,每次容器进出时都会更新 etcd 中的目录结构。这使得使用我上面列出的发现技术变得更容易,而无需每个容器都必须宣布自己,它变得自动。你仍然需要'front' 容器有一个启动脚本来等待服务出现在 etcd 数据库中。我通常在 coreos 启动时启动 registrator。事实上,我启动了两份副本,一份用于发现内部地址(法兰绒地址),一份用于外部(在我的容器之外可用的服务)。这是我的机器上管理的数据库注册器的示例:

core@fo1 ~/prs $ etcdctl ls --recursive /skydns /skydns/net /skydns/net/tacodata /skydns/net/tacodata/services /skydns/net/tacodata/services/cadvisor-4194 /skydns/net/tacodata /services/cadvisor-4194/fo2:cadvisor:4194 /skydns/net/tacodata/services/cadvisor-4194/fo1:cadvisor:4194 /skydns/net/tacodata/services/cadvisor-4194/fo3:cadvisor:4194 /skydns /net/tacodata/services/internal /skydns/net/tacodata/services/internal/cadvisor-4194 /skydns/net/tacodata/services/internal/cadvisor-4194/fo2:cadvisor:4194 /skydns/net/tacodata/services /internal/cadvisor-4194/fo1:cadvisor:4194 /skydns/net/tacodata/services/internal/cadvisor-4194/fo3:cadvisor:4194 /skydns/net/tacodata/services/internal/cadvisor-8080 /skydns/net /tacodata/services/internal/cadvisor-8080/fo2:cadvisor:8080 /skydns/net/tacodata/services/internal/cadvisor-8080/fo1:cadvisor:8080 /skydns/net/tacodata/services/internal/cadvisor-8080/fo3:cadvisor:8080

您可以看到 cadvisor 的内部和外部可用端口。如果我得到其中一条记录:

etcdctl get /skydns/net/tacodata/services/internal/cadvisor-4194/fo2:cadvisor:4194
{"host":"10.1.88.3","port":4194}

您获得了在内部连接到该容器所需的一切。当与skydns结合使用时,这种技术真正开始大放异彩。Skydns 使用注册者提供的信息提供 dns 服务。所以,长话短说,我可以简单地让我的应用程序使用主机名(主机名默认为 docker 映像的名称,但可以更改)。所以在这个例子中,我的应用程序可以连接到 cadvisor-8080,并且 dns 会给它它拥有的 3 个 IP 地址之一(它在 3 台机器上)。dns 还支持 srv 记录,因此,如果您没有使用众所周知的端口,则 srv 记录可以为您提供端口号。

使用 coreos 和fleet 很难不让容器本身参与发布/发现/等待游戏。至少这是我的经验。

-G

于 2015-05-12T15:29:25.987 回答