Обнаружение контейнера Docker по именам хостов не работает

Я использую следующий файл компоновки докеров, расположенный по адресу /tmp/compose.yml, для развертывания стека докеров:

version: "3.6"

services:
  service-A:
    image: service-A
    networks:
      - net
    hostname: "service-A-{{.Task.Slot}}"
    deploy:
      replicas: 2

  service-B:
    image: service-B
    networks:
      - net
    hostname: "service-B-{{.Task.Slot}}"
    deploy:
      replicas: 2

networks:

  net:

Выполнить команды:

docker network create -d overlay net
docker stack deploy -c /tmp/compose.yml my

Я ожидал, что service-A отдельные контейнеры смогут обнаруживать service-B контейнеров по предопределенным именам хостов контейнеров: service-B-1, service-B-2. Однако ping service-B-1 из любого контейнера service-A не работает.

Состояние документов:

hostname Задает имя хоста, под которым контейнер знает себя. Это записывается в /etc/hostname, в /etc/hosts как имя IP-адреса контейнера, обращенного к хосту, и это имя, которое /bin/bash внутри контейнера будет отображаться в его приглашении. Но имя хоста нелегко увидеть снаружи контейнера. Он не появится ни в docker ps, ни в файле /etc/hosts любого другого контейнера.

Как добиться, чтобы контейнер службы роя докеров обслуживал связь контейнера с помощью предварительно определенных имен хостов контейнера?

Единственный способ, который работает, — это добавить такие записи, как:

[service_B_container_1_virtual_ip] service-B-1
[service_B_container_2_virtual_ip] service-B-2

до /etc/hosts из service-A контейнеров.

Также интересно, что если hostname не задано в файле docker-composes, а сгенерировано докером, ping [container_id] преуспевает даже в рое многоузловых докеров.

Я ожидал такого же поведения для предопределенных имен хостов.


person rok    schedule 26.11.2019    source источник


Ответы (1)


Я не думаю, что есть какой-то простой способ сделать это. И чем больше я об этом думаю, тем больше становится понятно, что не должно быть способа сделать то, что вы просите, преднамеренно.

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

Что вы можете сделать внутри сети Docker, так это сослаться на сервисный объект, используя имя сервиса. Итак, в вашем примере ping Service-A должен работать из любого контейнера в стеке, как и ping Service-B.

Имена отдельных контейнеров в службе выглядят примерно так:

my_stack_redis.1.y1pwzeg8239yb6n6ynefs78br
my_stack_webserver.1.d6cxx8nlg7db9m2poy9wfjdyd

Если вам абсолютно необходимо получить доступ к этим именам из контейнера, единственный способ, который я могу придумать, — это открыть /var/run/docker.sock внутри контейнера через монтирование привязки при запуске. Затем chmod 750 в сокете как часть сценария CMD / ENTRYPOINT, чтобы пользователь без полномочий root мог его прочитать. Теперь вы сможете установить интерфейс командной строки Docker и использовать docker network inspect для обнаружения имен реальных членов службы и jq для их разбора (вам, вероятно, потребуется добавить оба пакета в образ). Но в этот момент лучшим вариантом, вероятно, было бы разделить эти невзаимозаменяемые контейнеры на свои собственные сервисные группы.

person Z4-tier    schedule 27.11.2019