Как связать службы Docker между хостами?

115

Docker позволяет серверам из нескольких контейнеров подключаться друг к другу через ссылки и обнаружение служб . Однако из того, что я вижу, это обнаружение службы является локальным для хоста. Я хотел бы реализовать службу, которая использует другие службы, размещенные на другом компьютере.

В Docker было несколько подходов к решению этой проблемы, таких как CoreOSjumpers , локальные службы хоста, которые, по сути, прокси-серверы для другой машины, и целая куча проектов github для управления развертываниями Docker, которые, по-видимому, пытались поддерживать этот вариант использования. ,

Учитывая темпы развития, сложно следовать текущим передовым практикам. Поэтому мой вопрос по существу:

  1. Что (если есть) является текущим преобладающим методом связывания между хостами в Docker, и
  2. Есть ли планы по поддержке этой функциональности непосредственно в системе Docker?
lyschoening
источник

Ответы:

58

Обновить

Docker недавно анонсировал новый инструмент под названием Swarm for Docker orchestration.

роиться позволяет вам «присоединиться» к нескольким демонам-докерам: вы сначала создаете рой, запускаете менеджер роя на одной машине и заставляете демонов-докеров «присоединяться» к диспетчеру роя, используя идентификатор роя. Докер-клиент подключается к диспетчеру роя, как если бы это был обычный докер-сервер.

Когда контейнер запускается с Swarm, он автоматически назначается свободному узлу, отвечающему всем определенным ограничениям. Следующий пример взят из сообщения в блоге:

$ docker run -d -P -e constraint:storage=ssd mysql

Одно из поддерживаемых ограничений - это "node"то, что вы можете привязать контейнер к определенному имени хоста. Рой также разрешает связи между узлами.

Во время тестирования у меня создалось впечатление, что Swarm еще не очень хорошо работает с томами в фиксированном месте (или, по крайней мере, процесс их связывания не очень интуитивно понятен), так что об этом следует помнить.

Swarm сейчас находится в стадии бета-тестирования.


До недавнего времени шаблон Ambassador был единственным встроенным в Docker подходом к обнаружению служб удаленного хоста. Этот шаблон все еще можно использовать, и он не требует каких-либо магических действий, кроме простого Docker, поскольку он состоит из одного или нескольких дополнительных контейнеров, которые действуют как прокси.

Кроме того, есть несколько сторонних расширений, которые делают Docker-совместимым с кластером. Сторонние решения включают:

  • Подключение сетевых мостов Docker на двух хостах, легкие и различные решения существуют, но, как правило, с некоторыми оговорками
  • Обнаружение на основе DNS, например, с помощью Skydock и SkyDNS
  • Инструменты управления Docker, такие как Shipyard и инструменты оркестрации Docker. Подробный список см. В этом вопросе: Как масштабировать контейнеры Docker в производственной среде
lyschoening
источник
2
Таким образом, в принципе, по-прежнему нет способа связать контейнеры между хостами, который не использует шаблон ambasador или обход докера и напрямую разговаривает с lxc?
user3012759
@ user3012759 Ambassador Pattern - единственный установленный собственный способ, но Swarm (в альфа-версии) - еще один собственный способ, который работает путем замены планировщика Docker. Извините за поздний ответ.
lyschoening
SkyDock (пока: 03/2015) не включает поддержку нескольких хостов . Регистратор (простой проект, который может работать со SkyDNS) работает, но настройка выполняется вручную (службы должны иметь порты, сопоставленные с портами хоста).
turtlemonvh
6
Мое беглое исследование роя предполагает, что он сосредоточен на управлении кластером, а не на межузловом соединении. Этот недостаток четко обозначен собственной демонстрацией
Докера
1
@lyschoening Docker объявила о появлении нативной сети с несколькими хостами, вы, возможно, захотите обновить свой ответ
Thomasleveil,
15

ОБНОВЛЕНИЕ 3

Libswarm был переименован в swarm и теперь представляет собой отдельное приложение.

Вот демонстрация страницы github, которую можно использовать в качестве отправной точки:

# create a cluster
$ swarm create
6856663cdefdec325839a4b7e1de38e8

# on each of your nodes, start the swarm agent
#  <node_ip> doesn't have to be public (eg. 192.168.0.X),
#  as long as the other nodes can reach it, it is fine.
$ swarm join --token=6856663cdefdec325839a4b7e1de38e8 --addr=<node_ip:2375>

# start the manager on any machine or your laptop
$ swarm manage --token=6856663cdefdec325839a4b7e1de38e8 --addr=<swarm_ip:swarm_port>

# use the regular docker cli
$ docker -H <swarm_ip:swarm_port> info
$ docker -H <swarm_ip:swarm_port> run ... 
$ docker -H <swarm_ip:swarm_port> ps 
$ docker -H <swarm_ip:swarm_port> logs ...
...

# list nodes in your cluster
$ swarm list --token=6856663cdefdec325839a4b7e1de38e8
http://<node_ip:2375>

ОБНОВЛЕНИЕ 2

Официальный подход теперь заключается в использовании libswarm см. Демонстрацию здесь

ОБНОВИТЬ

Есть хорошая идея для связи хостов openvswitch в докере с использованием того же подхода.

Чтобы разрешить обнаружение сервисов, существует интересный подход, основанный на DNS, который называется skydock .

Также есть скринкаст .


Это также хорошая статья, в которой используются те же кусочки головоломки, но с добавлением вланов сверху:

http://fbevmware.blogspot.it/2013/12/coupling-docker-and-open-vswitch.html

Исправление не имеет ничего общего с надежностью решения. На самом деле Docker - это лишь разновидность DSL для контейнеров Linux, и оба решения в этих статьях просто обходят некоторые автоматические настройки Docker и возвращаются непосредственно к контейнерам Linux.

Таким образом, вы можете безопасно использовать решения и подождать, чтобы сделать это более простым способом, когда Docker его реализует.

tommasop
источник
2
В последнее время в libswarm не было большой активности. Интересно, движется ли команда докеров в другом направлении?
Raman
12

Weave - это новая технология виртуальной сети Docker, которая действует как виртуальный коммутатор Ethernet через TCP / UDP - все, что вам нужно, это контейнер Docker, на котором работает Weave на вашем хосте.

Что здесь интересно

  • Вместо ссылок используйте статические IP-адреса / имена хостов в вашей виртуальной сети.
  • Хостам не требуется полное подключение, сетка формируется на основе доступных одноранговых узлов, а пакеты будут маршрутизироваться в несколько переходов туда, где им нужно.

Это приводит к интересным сценариям вроде

  • Создайте виртуальную сеть через WAN, ни один из контейнеров Docker не будет знать и не заботиться о том, в какой реальной сети они находятся.
  • Переместите свои контейнеры на разные физические хосты докеров, Weave соответствующим образом обнаружит однорангового узла.

Например, есть пример руководства по созданию многоузлового кластера Cassandra на вашем ноутбуке и нескольких облачных (EC2) хостах с двумя командами для каждого хоста. Я запустил кластер CoreOS с AWS CloudFormation, установил Weave на каждом в / home / core, а также виртуальную машину vagrant docker на моем ноутбуке и собрал кластер менее чем за час. Мой ноутбук защищен брандмауэром, но Weave, похоже, не возражал против этого, он просто подключается к своим узлам EC2.

Стюарт Чарльтон
источник
Насколько я понимаю, weave - это сетевой оверлей, который работает внутри контейнеров для подключения сервисов, а swarm - это технология кластеризации, которая расширяет интерфейс командной строки docker для оркестрации инфраструктуры. Инфракрасное соединение должно быть выполнено вне роя (например, с использованием обычных коммутаторов), а оркестровка сервисов вне плетения (например, с использованием Mesos / Kubernetes). Это соответствует вашему представлению о том, как это работает?
Хенрик
Вот как я бы посмотрел на это: docker compose - это связывание и оркестровка контейнеров, docker swarm - это запуск докера на многих хостах докеров, socketplane (теперь принадлежит docker) и weave - это оверлейные сети. Socketplane основан на openvswitch, который обычно используется для оверлеев в виртуальных машинах (например, openstack); С другой стороны, Weave работает только в докере. Из всего этого Mesos / Kubernetes / Lattice заменяют docker swarm с несколько иным пользовательским интерфейсом и уровнями масштабируемости, чем docker CLI.
Стюарт Чарльтон
7

Обновить

Docker 1.12 содержит так называемый режим роя, а также добавляет serviceабстракцию. Вероятно, они недостаточно зрелы для каждого случая использования, но я предлагаю вам держать их под наблюдением. Режим роя, по крайней мере, помогает в настройке с несколькими хостами, что не обязательно упрощает связывание. Внутренний DNS-сервер Docker (начиная с 1.11) должен помочь вам получить доступ к именам контейнеров, если они хорошо известны, а это означает, что сгенерированные имена в контексте Swarm не будут так легко обрабатывать.


С выпуском Docker 1.9 вы получите встроенную сеть с несколькими хостами . Они также предоставляют пример сценария для простой подготовки рабочего кластера.

Вам понадобится хранилище K / V (например, Consul), которое позволяет обмениваться состоянием между различными механизмами Docker на каждом хосте. Каждый механизм Docker необходимо настроить с этим хранилищем K / V, и затем вы можете использовать Swarm для подключения своих хостов.

Затем вы создаете новую оверлейную сеть следующим образом:

$ docker network create --driver overlay my-network

Теперь контейнеры можно запускать с сетевым именем в качестве параметра запуска:

$ docker run -itd --net=my-network busybox

Они также могут быть подключены к сети, когда они уже запущены:

$ docker network connect my-network my-container

Более подробная информация доступна в документации .

gesellix
источник
6

В следующей статье хорошо описано, как подключать контейнеры докеров на нескольких хостах: http://goldmann.pl/blog/2014/01/21/connecting-docker-containers-on-multiple-hosts/

paweloque
источник
1
Это действительно очень хорошее решение; Я тоже с этим сталкивался. Меня беспокоит то, что статья была опубликована только вчера и требует исправления для Docker. (Учитывая, как недавно он был опубликован, я бы немного подождал, чтобы посмотреть, объединят ли они этот патч с Docker).
lyschoening
Docker находится на ранней стадии разработки, возможно, еще не все требования ясны, а определенные требования не все реализованы. Следовательно, исправление необходимо.
paweloque
2
Это не ответ. Скопируйте ответ из связанной статьи. Это стандарт SO.
Bruno Bronosky
6

Можно соединить несколько подсетей Docker вместе с помощью Open vSwitch или Tinc. Я подготовил Gists, чтобы показать, как это сделать:

Преимущество, которое я вижу в использовании этого решения вместо --linkопции и шаблона посла, состоит в том, что я считаю его более прозрачным: нет необходимости в дополнительных контейнерах и, что более важно, нет необходимости открывать порты на хосте. На самом деле я думаю о --linkварианте временного взлома, прежде чем Docker получит более приятную историю о настройках с несколькими хостами (или несколькими демонами).

Примечание: я знаю, что есть еще один ответ, указывающий на мой первый Gist, но у меня недостаточно кармы, чтобы редактировать или комментировать этот ответ.

noteed
источник
Как бы вы сделали обнаружение услуг? Скажите, если у меня есть Redis на одном компьютере и клиентское приложение на другом, как клиентское приложение получит IP-адрес службы Redis?
lyschoening
Таким же образом вы бы сделали это на одном хосте: предоставив себе IP / порт для вновь запущенных сервисов, или используя хранилище ключей / значений (например, etcd), или используя DNS, который сервисы могут запрашивать. Мне нравится использовать DNS, потому что многие существующие службы могут использовать его без изменений.
отмечено
1

Как упоминалось выше, Weave определенно является жизнеспособным решением для связывания контейнеров Docker между хостами. Основываясь на моем собственном опыте работы с ним, его довольно просто настроить. Теперь у него также есть служба DNS, к которой вы можете обращаться к контейнеру по его именам DNS.

С другой стороны, есть Flannel от CoreOS и Opencontrail от Juniper для подключения контейнеров к хостам.

user2661697
источник
1

Похоже, что docker swarm 1.14позволяет:

  • присвоение имени хоста контейнеру с использованием --hostnameтега, но я не смог заставить его работать, контейнеры не могут пинговать друг друга по назначенным именам хостов.

  • назначение услуг машине с помощью --constraint 'node.hostname == <host>'

saikek
источник