Pull to refresh

Comments 31

А почему вы не рассматривали вариант с macvlan интерфейсом в качестве основного на хост-системе? А на eth0 даже адрес не навешивать. Заодно и пакеты перестанут ходить через свитч.
В статье я сделал оговорку по этому поводу, также в ней содержится и ответ:
Внимательный читатель задаст вопрос: «А зачем адрес на основной интерфейс и на MACVLAN-интерфейс, если можно адрес основного интерфейса отдать виртуальному?» В таком случае мы оставим нашу систему без адресов на реальных интерфейсах, а на такой шаг я пойти пока не готов.

Для того, чтобы пакеты перестали ходить через свитч мы также высадили nginx в контейнер, который использует нужную нам сеть.
Видите, читатель оказался недостаточно внимательным :)

Опасаетесь остаться без control flow? Тогда, как вариант — отдельные запасные адреса на eth0 интерфейсе, чтобы было куда придти, если совсем всё плохо стало. в целом же macvlan не выглядит менее надёжным, чем бридж, а его активно используют и навешивают адреса именно на него.
Вариант с таким или подобным развитием мы вполне рассматриваем, но внедрять пока не стали. Скорее всего мы ждем момента, когда накопится достаточный эксплуатационный опыт с тем, что есть, а уж если он будет положительным…
А почему вы не рассмотрели получение маршрутов от DHCP в зависимости от хостнейма? И огород городить бы не пришлось с Linux capabilities. Да и логика микросервисов ломается, хотя все её ломают кроме меня. За то что я идейный меня уже пожурили на работе.
Исторически у нас всё несколько иначе – hostname в зависимости от адреса. Для данной задачи изначально делали VLAN, в котором даже нет DHCP хелпера. Если посмотреть под другим углом, то может быть и предложенная вами реализация оказалась бы уместна.
По поводу идей и логики микросервисов это все, конечно, хорошо, но не под все условия подходит. С моей точки зрения очень часто получается так, что идею микросервисов предлагают, а о том, будет ли с таким подходом хорошо и удобно – забывают.
В данном случае мы можем рассматривать Docker как и любой другой инструмент для выполнения тех или иных задач, а решение о том, как выполнять эти задачи остается за нами. Такой подход мне ближе.
Также в данном случае, я не считаю, что получился «огород», так как данная схема для нас вполне привычная.
В любом случае по моему проще добавить DHCP в этот отдельный VLAN, а условие отдачи маршрутов натянуть через типовой ключ(hostname или ip адрес, да любой который подходит). Ну а про докеры я просто поплакался.
UFO just landed and posted this here
О том, почему маршруты внутри контейнера я попытался объяснить в теле статьи. Если это не до конца понятно – могу попробовать еще раз.
Простота решения – это мера сильно субъективная. Если вы хотите, то давайте я по каждому пункту, который кажется не простым, отвечу почему я считаю его простым. Осталось только обозначить пункты.
Как я сказал в комментарии выше – есть технология, а то как ее применять и использовать – это уже дело личное. Можно рассматривать предложенное решение не в формате «так нужно делать», а в формате «можно сделать вот так вот».
А какие фишки docker'а являются важными для вас и какие из них я потерял?
UFO just landed and posted this here
Не обращать внимания – неправильно, дискуссия – всегда отлично!
Давайте попробуем посмотреть на «docker run» с той точки зрения, что вы готовы указать порт для приложения:
docker run -d \ 
// здесь мы выбираем тип сети для контейнера, выдаем ему ip-адрес:
--net=c_services --ip=1.1.2.17 \  
// указываем имя, т.к. просто удобнее смотреть потом на docker ps. Можно не указывать.
--name=SERVICE-INSTANCE16 \ 
// это опять же приятнее рандомайза, т.е. дело эстетики. Можно не указывать.
-h SERVICE-INSTANCE16.local \ 
// да, тут чуть сложнее и мне это нужно:
--cap-add=NET_ADMIN \ 
// добавить запись в /etc/hosts. Можно сделать иначе, но так оно прозрачнее.
--add-host='nginx.localhost:1.1.1.17' \ 
// переменные окружения. То, что вы говорили про порт для приложения:
-e SERVICETYPE=INSTANCE16_eu1 -e HOST_IP=1.1.1.17 \ 
// чтобы не указывать вереницу служебных директорий, которые нам нужны в определенных контейнерах. 
--volumes-from=badoo_loop \ 
// имя образа:
dockerio.badoo.com/cteam/SERVICE:2.30.0_994 


docker pull также можно не делать, run сделает его за вас :)

Итого в сухом остатке мы получаем, что сложность команды заключается в:
  • --cap-add
  • --add-host


А если учитывать то, что руками мы это не выполняем, то вывод напрашивается сам собой.
UFO just landed and posted this here
вот от pipework и ручных телодвижений в случае поднятия контейнера я стараюсь держаться дальше, т.к. есть вероятность, что кто-то из коллег или, например, службы мониторинга не осилит определенные действия без понимая картины в целом.
«opencontrail или calico» – не смотрели. Особенности у нас только такие, о которых я написал в статье: есть всего 2 варианта :)
UFO just landed and posted this here
спасибо, я обязательно посмотрю на вышеназванные решения.
UFO just landed and posted this here
мне если честно, то совсем не хочется зарываться в сторону софтовой маршрутизации. Как минимум на данный момент у нас есть отдел сетевых инженеров, которым по вопросам сети я доверяю больше, чем себе.
В данном примере я делаю какие-то телодвижения в рамках одного хоста, а гейтвеи и условия балансировки, а также маршруты до них я не меняю/не нарушаю. Это важно как минимум и потому, что не все сервисы в контейнерах. Т.е. решения так или иначе связанные с маршрутами и завязанные на docker и его экосистему на данный момент для внедрения сильно не рассматриваются.
UFO just landed and posted this here
лень других – двигатель прогресса первых! =)
UFO just landed and posted this here
Вот такое
docker run -d \
// здесь мы выбираем тип сети для контейнера, выдаем ему ip-адрес:
// Этого можно было бы не делать будь у вас DHCP
--net=c_services --ip=1.1.2.17 \
// указываем имя, т.к. просто удобнее смотреть потом на docker ps. Можно не указывать.
// Это необходимо для создания фильтрации в централизованном лог сервере
--name=$VARIABLE \
// это опять же приятнее рандомайза, т.е. дело эстетики. Можно не указывать.
// Это необходимо для системы мониторинга, но можно через dhcp проставлять
-h $VARIABLE.local \
// да, тут чуть сложнее и мне это нужно:
// это так же решается dhcp сервером
--cap-add=NET_ADMIN \
// добавить запись в /etc/hosts. Можно сделать иначе, но так оно прозрачнее.
// если у нас есть dhcp значит и dns можно поставить и управлять этим можно будет централизованно
--add-host='nginx.localhost:1.1.1.17' \
// переменные окружения. То, что вы говорили про порт для приложения:
// этого тоже можно избежать забирая $VARIABLE из хостнейма и присвоенный адрес из системы
-e SERVICETYPE=INSTANCE16_eu1 -e HOST_IP=1.1.1.17 \
// чтобы не указывать вереницу служебных директорий, которые нам нужны в определенных контейнерах.
// Это сугубо специфичное и должно указываться в dockerfile
--volumes-from=badoo_loop \
// имя образа:
dockerio.badoo.com/cteam/$VARIABLE:2.30.0_994


Можно с лёгкостью уменьшить до
VARIABLE=SERVICE;docker run -d \
// Это необходимо для создания фильтрации в централизованном лог сервере, можно наверно не указывать
--name=$VARIABLE \
// имя образа:
cteam/$VARIABLE:2.30.0_994

Итого наш контейнер запускается и работает независимо от ключей, требуется только указать имя образа в registry. Разве не это есть упрощение?
контейнер работает(если повезет), а из сервиса получили тыкву.
Можно с лёгкостью уменьшить до
VARIABLE=SERVICE;docker run -d \
// Это необходимо для создания фильтрации в централизованном лог сервере, можно наверно не указывать
--name=$VARIABLE \
// имя образа:
cteam/$VARIABLE:2.30.0_994

если SERVICE == 'ubuntu', а версия == 'latest'(кстате, почему вы ее в переменную не вынесли?), то конструкция:
VARIABLE=ubuntu;docker run -d --name=$VARIABLE cteam/$VARIABLE:latest

работать не будет.
Если говорить серьезно, то все, что вы сочли лишним и решили не указывать – нам важно и нужно. Например через --volumes-from мы добавим или не добавим интерпретатор php, если он по какой-то причине нужен внутри контейнера. Мы также прокинем в контейнер служебные директории, откуда потом будем собирать статистику – да это все про работу одного сервиса.
В данном случае мы не рассматриваем один сервис, как один *nix сервис. Сервис в данном случае – это некоторое приложение, которое должно выдавать ожидаемый нами результат. Да, часто получается так, что для работы данного сервиса может потребоваться более одного *nix сервиса.
Через -e мы передаем параметры, на основании которых мы должны сделать вывод о том, какой тип данного сервиса мы хотим запускать… Опять же – это не указывать нельзя.
Я каждый убранный пункт прокомментировал, всё что мы не указали подтягивается либо из дефолтных настроек докера, либо из dhcp, либо из dns. Так как у вас в любом случае есть свои dns и dhcp сервера и выносить с них этот функционал не было никакого смысла. Что же касается дефолтных настроек докера то у вас физические машины и сами контейнеры управляются через оркестрацию вашу. Так что я просто использовал то что у вас есть для упрощения нового.
Хорошо, вот ваш самый первый комментарий:
docker run -d \
// здесь мы выбираем тип сети для контейнера, выдаем ему ip-адрес:
// Этого можно было бы не делать будь у вас DHCP
--net=c_services --ip=1.1.2.17 \

Неважно есть у нас dhcp или нет, но указать тип сети для контейнера мы должны, а иначе мы используем default bridge, так? Изначально я говорю о том, что нам нужен и мы используем MACVLAN.
Идем дальше. Можно не указывать --ip=. Можно, но тогда нам либо pool адресов при создании macvlan сети для docker нужно как-то обозначить, либо как-то блеклистить те адреса, которые мы не хотим получить в своем контейнере, так?
// это опять же приятнее рандомайза, т.е. дело эстетики. Можно не указывать.
// Это необходимо для системы мониторинга, но можно через dhcp проставлять
-h $VARIABLE.local \

Для какой системы мониторинга?
// да, тут чуть сложнее и мне это нужно:
// это так же решается dhcp сервером
--cap-add=NET_ADMIN \

мы меняем default gw, который мы проставляли при создании MACVLAN сети на .254, что сделать без NET_ADMIN не получится(да, можно через pipework, но мне не нравится такой вариант)
// добавить запись в /etc/hosts. Можно сделать иначе, но так оно прозрачнее.
// если у нас есть dhcp значит и dns можно поставить и управлять этим можно будет централизованно
--add-host='nginx.localhost:1.1.1.17' \

эта запись будет разной, в зависимости от хоста, на котором запускам контейнер. Да, тоже самое значение я передаю позже в -e HOST_IP=1.1.1.17, его можно использовать. Но т.к. сущности разные, то и указываю отдельно там и там.
// этого тоже можно избежать забирая $VARIABLE из хостнейма и присвоенный адрес из системы
-e SERVICETYPE=INSTANCE16_eu1 -e HOST_IP=1.1.1.17 \

можно завязаться на hostname, но т.к. мы обеспечиваем работу сервиса, то сущностью «сервис» оперировать логичнее.
// Это сугубо специфичное и должно указываться в dockerfile
--volumes-from=badoo_loop \

нет, нельзя это указывать в Dockerfile, т.к. там мы можем указать какие директории будем экспортировать, а нам нужен еще и импорт.
а иначе мы используем default bridge, так?

Нет, мы через оркестрацию задаём всем физическим машинам настройки докера. А именно удаляем все имеющиеся сети и добавляем macvlan. И к контейнеру привязывается единственная наша сеть через macvlan.
Для какой системы мониторинга?

Вы в badoo используете заббикс с LLD на основе хостнеймов. Читал с митапа заббикса ваш доклад.
мы меняем default gw, который мы проставляли при создании MACVLAN сети на .254, что сделать без NET_ADMIN не получится
Через dhcp вы так же можете получить маршруты, в том числе и default gw.
эта запись будет разной, в зависимости от хоста, на котором запускам контейнер. Да, тоже самое значение я передаю позже в -e HOST_IP=1.1.1.17, его можно использовать. Но т.к. сущности разные, то и указываю отдельно там и там.
это я не совсем понимаю, плодить сущности конечно не хорошо, но если это обход Ограничения технологии by design: доступность контейнера с хоста и доступность хоста из контейнера отсутствует. То думаю это самое простое решение.
нет, нельзя это указывать в Dockerfile, т.к. там мы можем указать какие директории будем экспортировать, а нам нужен еще и импорт.
Здесь я наверно не прав.
Вы можете показать практически работающее решение, на основании того, как вы его описываете? А именно:
  • задать docker демону работу через macvlan сеть by default
  • чтобы контейнеры(пусть все, хотя не всегда это нужно) использовали именно эту сеть
  • чтобы контейнер, mac которого мы не знаем получал заранее известный ip (тут спорно, т.к. можно обыграть иначе, но пусть так)
  • чтобы контейнер по dhcp(центральному, а не тому, что предоставляет macvlan) получал default gw, а также 2-3 кастомных маршрута

Вы можете показать практически работающее решение, на основании того, как вы его описываете?

Нет, я выдвинул предположение о том что правильней для такого функционала было бы использовать. Все последующие комментарии были только для более полного и подробного описания идеи. Надеюсь вы не серчаете на меня.
Конечно не серчаю, мы же просто обсуждали предложенную вами идею. Обсуждать, предлагать, да и вообще думать – очень полезно.
Изначально, когда вы абстрактно предложили свою идею, без подробностей – она казалась вполне себе состоятельной, я воспринял некоторые моменты по-своему. Далее, когда вы начали более подробно раскрывать её – стало понятно, что не всё можно сделать так просто и прозрачно, а значит это скорее всего приведет к некоторым дополнительным костылям/сервисам и т.д. (не обязательно, но на основании написанного – приведет).
Где-то в середине дискуссии мы говорили о том, что можно упростить предложенную мной строку запуска(про linux capabilities продолжать не будем) – я согласен, можно. Но приведенная строка запуска не дает до конца расслабиться инженеру в те моменты, когда он запускает сервис или диагностирует его, т.е. глядя на строку запуска он уже имеет некоторое понимание о том, с чем ему придется иметь дело. Можем упростить команду и скрыть детали? Да! Проблема лишь в том, что это мы уберем в дебри инита нашего контейнера, тем самым осложним диагностику, если это потребуется. А самое главное – человеку придется меньше думать и работать со «сферическим конем в вакууме» =)

p.s.: самое главное и хорошее – это то, что у вам есть мысли и идеи, а также и то, что вы не боитесь и не стесняетесь ими делиться. Так держать!
Всем привет! Собсотвенно начитался этой статьи и docs.docker.com/engine/userguide/networking/get-started-macvlan/#pre-requisites
Выполнил простые настройки:
# docker network create -d macvlan --subnet=172.16.80.0/23 --gateway=172.16.80.1 -o parent=ens192 pub_net 
# docker run --net=pub_net --ip=172.16.80.60 -i --name test -d centos


Заходим на контейнер test пингуем дефолтный гейт 172.16.80.1 — ни фига из сети 172.16.80.0/23 IP-адрес 172.16.80.60 тоже не пингуется, ну что ещё сделать я не знаю
На хост-машине фаервол и SELinux выключены, в сети фаерволов нету
Sign up to leave a comment.