Docker CoreOS舰队无法获取容器

Docker CoreOS舰队无法获取容器,docker,coreos,fleetctl,cadvisor,Docker,Coreos,Fleetctl,Cadvisor,我有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

我有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列表单元输出,在这里您可以看到其他两个单元运行没有问题

 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

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

通常使用云服务时,一种服务需要另一种服务,就像您的情况一样。如果另一个服务尚未运行,那么需要它的服务应该表现良好,要么退出,要么等待所需的服务准备就绪。因此,必须发现所需的服务。在发现阶段和等待阶段有许多技术。例如,您可以在每个容器中编写“包装器”脚本。那个包装工可以做这些工作。在您的情况下,back.service和graphite.service中可以有一个脚本,用于将信息写入etcd数据库,如:

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

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

core@fo1~/prs$etcdctl ls—递归/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使用注册者提供的信息提供dns服务。因此,长话短说,我可以简单地让我的应用程序使用主机名(主机名默认为docker映像的名称,但可以更改)。因此,在本例中,我的应用程序可以连接到cadvisor-8080,dns将为其提供3个ip地址中的一个(位于3台机器上)。dns还支持srv记录,因此,如果您没有使用众所周知的端口,srv记录可以为您提供端口号

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

-g