CoreOS Fleet не может получить контейнер

У меня есть 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

1 ответ

Здесь есть пара вопросов. во-первых, вы не можете использовать аргумент --link для 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-адрес и порт в графитовом скрипте, чтобы фронтальный скрипт мог подобрать место для подключения.

Другой метод обнаружения - использование регистратора. Это очень удобный докер-контейнер, который обновляет структуру каталогов в etcd каждый раз, когда контейнер приходит и уходит. Это облегчает использование техники обнаружения, как я перечислил выше, без необходимости объявлять каждый контейнер, это становится автоматическим. Вам все еще нужен "передний" контейнер, чтобы иметь сценарий запуска, который ожидает появления службы в базе данных etcd. Я обычно запускаю регистратор при загрузке coreos. На самом деле, я запускаю две копии, одну для обнаружения внутренних адресов (фланелевые) и одну для внешних (сервисы, доступные вне моих контейнеров). Вот пример управления регистратором базы данных на моих машинах:

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/ внутренняя / skydns / net / tacodata / services / внутренняя / cadvisor-4194 / skydns / net / tacodata / services / внутренняя /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/ внутренний /cadvisor-8080 /skydns/net/tacodata/services/internal/cadvisor-8080/fo2:cadvisor:8080 /skydns/net/tacodata/services/ внутренний /cadvisor-8080/fo1:cadvisor:8080 /skydns/net/tacodata/services/ внутренний / 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, используя информацию, предоставленную регистратором. Короче говоря, я могу просто заставить свое приложение использовать имя хоста (имя хоста по умолчанию является именем образа докера, но его можно изменить). Таким образом, в этом примере мое приложение может подключиться к cadvisor-8080, и dns предоставит ему один из 3 IP-адресов, которые он имеет (он находится на 3 машинах). DNS также поддерживает записи srv, поэтому, если вы не используете хорошо известный порт, запись srv может дать вам номер порта.

При использовании coreos и флота сложно не вовлечь сами контейнеры в игру "публикация / обнаружение / ожидание". По крайней мере, это был мой опыт.

Другие вопросы по тегам