Обновить
17
0

Пользователь

Отправить сообщение
контейнер работает(если повезет), а из сервиса получили тыкву.
лень других – двигатель прогресса первых! =)
мне если честно, то совсем не хочется зарываться в сторону софтовой маршрутизации. Как минимум на данный момент у нас есть отдел сетевых инженеров, которым по вопросам сети я доверяю больше, чем себе.
В данном примере я делаю какие-то телодвижения в рамках одного хоста, а гейтвеи и условия балансировки, а также маршруты до них я не меняю/не нарушаю. Это важно как минимум и потому, что не все сервисы в контейнерах. Т.е. решения так или иначе связанные с маршрутами и завязанные на docker и его экосистему на данный момент для внедрения сильно не рассматриваются.
спасибо, я обязательно посмотрю на вышеназванные решения.
вот от pipework и ручных телодвижений в случае поднятия контейнера я стараюсь держаться дальше, т.к. есть вероятность, что кто-то из коллег или, например, службы мониторинга не осилит определенные действия без понимая картины в целом.
«opencontrail или calico» – не смотрели. Особенности у нас только такие, о которых я написал в статье: есть всего 2 варианта :)
Не обращать внимания – неправильно, дискуссия – всегда отлично!
Давайте попробуем посмотреть на «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


А если учитывать то, что руками мы это не выполняем, то вывод напрашивается сам собой.
О том, почему маршруты внутри контейнера я попытался объяснить в теле статьи. Если это не до конца понятно – могу попробовать еще раз.
Простота решения – это мера сильно субъективная. Если вы хотите, то давайте я по каждому пункту, который кажется не простым, отвечу почему я считаю его простым. Осталось только обозначить пункты.
Как я сказал в комментарии выше – есть технология, а то как ее применять и использовать – это уже дело личное. Можно рассматривать предложенное решение не в формате «так нужно делать», а в формате «можно сделать вот так вот».
А какие фишки docker'а являются важными для вас и какие из них я потерял?
Исторически у нас всё несколько иначе – hostname в зависимости от адреса. Для данной задачи изначально делали VLAN, в котором даже нет DHCP хелпера. Если посмотреть под другим углом, то может быть и предложенная вами реализация оказалась бы уместна.
По поводу идей и логики микросервисов это все, конечно, хорошо, но не под все условия подходит. С моей точки зрения очень часто получается так, что идею микросервисов предлагают, а о том, будет ли с таким подходом хорошо и удобно – забывают.
В данном случае мы можем рассматривать Docker как и любой другой инструмент для выполнения тех или иных задач, а решение о том, как выполнять эти задачи остается за нами. Такой подход мне ближе.
Также в данном случае, я не считаю, что получился «огород», так как данная схема для нас вполне привычная.
Вариант с таким или подобным развитием мы вполне рассматриваем, но внедрять пока не стали. Скорее всего мы ждем момента, когда накопится достаточный эксплуатационный опыт с тем, что есть, а уж если он будет положительным…
В статье я сделал оговорку по этому поводу, также в ней содержится и ответ:
Внимательный читатель задаст вопрос: «А зачем адрес на основной интерфейс и на MACVLAN-интерфейс, если можно адрес основного интерфейса отдать виртуальному?» В таком случае мы оставим нашу систему без адресов на реальных интерфейсах, а на такой шаг я пойти пока не готов.

Для того, чтобы пакеты перестали ходить через свитч мы также высадили nginx в контейнер, который использует нужную нам сеть.
vaniaPooh отличная штука, спасибо! Есть опыт применения/использования.
Обычный use case – несколько сервисов на одной машине, использование диска – у какого-то сервиса больше, у другого – меньше, но «без фанатизма»:
— SUSE Linux Enterprise Server 11 Service Pack 3, kern 3.16.4
— порядка 20-25 running контейнеров
— порядка 30 в статусе Exited
— «базовые образы» не одинаковые для всех

Ошибки были, если не изменяет мне память: "… unable to mount rootfs...". В свое время находил подтверждения этому сочетанию на issues github.com/docker. После того, как время прошло и удалось провести тестирование производительности btrfs/dm/overlayfs – выбор остановили на последнем, к dm не возвращались.
от Badoo – админы
на «центральном» syslog никто не мешает гонять tail -f
Добрый день,

попробую ответить на ваши вопросы:

1. У нас для сборки «тестовых»(а потом уже и не тестовых, после тестирования) образов на той машине, где происходит сборка осуществляется поддержка структуры каталогов для сборки через Puppet. Я понимаю, что это может быть не самое красивое решение, но нам для переходного этапа, когда часть сервисов в контейнере, а часть по прежнему на «голом железе» этот вариант кажется самым предпочтительным. Т.е. у нас получается так:
Build_Directory/
— service_name/
— Dockerfile
— file1
— file2


т.е. автоматически наполняем Dockerfile и всю необходимую структуру.
Далее, когда в build системе происходит сборка бинаря/приложения, то оно на основании «шаблона» собирает образ. Тут есть 2 варианта: собралось/не собралось. Если собралось, то тегируем образ, пушим в registry, сообщаем команде тестирования о том, что есть новый образ и нужно начать его тестировать(образ оказывается на нужной для тестирования машины, в задаче на тестирования присутствуют все нужные параметры для запуска контейнера из образа).
2. тут вы уже сами ответ нашли.
3. У нас нет как такого глобального service discovery. У нас есть «карта сервисов», на основании которой мы регулируем то, на каком хосте и кто/что у нас должно работать.
etcd/confd используется уже на отдельновзятом хосте, если мы точно знаем о том, что сервис может быть перезапущен с переключением нагрузки на второй/третий/… инстанс. Да, не все сервисы, к сожалению, умеют так делать. Многим нужен корректный shutdown перед тем, как запустить вторую копию и прочее. Именно поэтому реализация «плавного» перезапуска у нас сделана «поштучно».
4. У нас есть «карта» сервисов, которая поддерживается инженером, на основании которой уже и происходит принятие решений о том кого где и сколько. Т.е. вариант «вот тебе вычислительные мощности — запусти мне где-нить 10-ку инстансов и мне все равно где...» нам не подходит.
deployment – xCAT, тут есть статья, а также запись выступления с #YaC2013.
По поводу второго вопроса: мы целиком и полностью доверяем тем, кто пишет манифесты всю ту информацию, что может быть там описана.
Если бы пришлось делать что-то подобное, то я думаю, что встал бы вопрос описания некоторого внешнего ресурса, который содержал бы в себе скрытые данные, т.е. в описании манифеста достаточно было бы указать какую-то маску в этом ресурсе(при первой прикидке: ментейнер действовал бы вслепую, полагаясь на валидные данные в источнике). Но это очень отдаленно и абстракнто, из серии – что в голову пришло.
Вот я тоже не нашёл хорошего и простого способа откатывать изменения с паппетом. Теоретически, есть идеи — в духе писать для каждого изменения скрипт отката, но времени это потребует неприлично много. И если есть возможность пересоздать систему с нуля, то лучше так и сделать.

Тут я с Вами полностью согласен. Есть еще вариант использовать:

ensure => ${some_if} ? {
     'val1' => present,
     'val2' => present,
     default => absent; #for example
}

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

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

Я ни в коем случае не против, пусть так.

2) По поводу неодинаковой среды. Есть же виртуальные машины + vagrant. С ним можно довольно быстро поднять виртуалку + выполнить нужные скрипты. Всё в консоли. Неужели не используете?

Можно быстро, да, НО: для того, чтобы поднять/развернуть копию той среды, в которой на самом деле будет применяться окружение/модуль/манифест нам не достаточно просто поднять образ под Vagrant. Для этого уже есть готовое окружение с виртуалками, которое сильно ближе к реалиям. Т.е. зачем нам что-то гонять на машине «разработчика», если мы можем тестировать (безболезненно, в том числе и с --noop, на условно боевой инфраструктуре).

Про модули: прочитав ваше понимание, я не думаю, что мы говорим о разном. За исключением того, что мы не часто прибегаем к помощи открытых модулей с puppetforge.
Модуль – это описание чего-то законченного (это, конечно, относительно). Т.е. в нашем случае, если мы хотим описать тот или иной сервис модулем – это ни в коем случае не говорит о том, что модуль не модет использовать некоторые куски из других модулей. У нас есть условно оговоренная иерархия модулей, т.е. в момент написания мы можем на 100% быть уверенны в том, что использование каких-то структур, объектов, глобальных переменных нам разрешено и доступно, т.к. это применено к ноде на более раннем этапе.

А почему? Было ли это осознанным выбором? (или может просто никто не заморачивался изучением этого вопроса)


Да, это было осознанным выбором, потомучто никто не заморачивался :)

stages очень удобно использовать, например для того, чтобы обновить список репозиториев на target system, например:
условимся, что у нас есть 2 доп. стейджа, не считая main stage. Картинка будет выглядеть, например вот так.
1. stage «pre»
2. stage «main» #default
3. stage post

зачем нужен pre? ну например, нам нужно залочить версии определенных пакетов, чтобы на основном стейдже быть точно уверенным в том, что на системе уже стоит то, что нам нужно и нужных версий, некоторая подстраховка. Также, если мы хотим использовать те или иные пакеты в основном стейдже, то нам надо быть уверенными в том, что все нужные custom репозитории объявлены и работают – это мы тоже сделаем на подготовительном стейдже.
«stage main» – тут все понятно
«stage post» – тут мы можем подчистить за собой и/или выполнить какие-то завершающие процедуры.

Единственный минус стейджей или то о чем нужно помнить – у них своя область видимости, наследования классов и вот этого вот всего.
external_node scripts — это имеется в виду External Node Classifier или что-то еще? Насколько я понял из презентации — у вас его роль выполняет foreman, не?

именно External Node Classifier и именно его мы не используем.
Foreman используем для «посмотреть как там дела» + завязаны какие-то тригеры мониторинга, не особенно приоритетные, а так «чтобы в курсе быть».
По поводу модулей: у вас очень идеальное представление :) В нашем случае _несколько_отдаленно_ модуль – это описание того или иного сервиса, т.е. почти сервис == модуль в паппете.
Привязка модуля осуществляется по карте, по примеру должен быть модуль на сервере или нет. Забегая вперед, раз уж вы спрашивали про hiera – именно тут в том числе она у нас используется. Также отвечая на возможный вопрос «а что делать, если модуль на этом сервере больше не нужен? нужно же что-то удалить, остановить и прочее»: для нас «дешевле» в этом случае отправить машину на полный цикл ресетапа, нежели заниматься точечной чисткой. Готового и на 100% отработанного решения по подобной чистке паппетом у нас нет, есть только мысли.
Далее… Разработчики у нас не пишут модулей для паппета, да и чего бы то ни было для него они не пишут, всем этим занимается команда эксплуатации.
Проверка на локальной машины – только синтаксис, все остальное проверить невозможно в силу не одинаковой среды на localhost и боевой или условно боевой машине.
Т.е. отвечая на вопросы про тесты – тесты не пишутся, по крайней мере в том виде, в котором они могут быть знакомы разработчику.
Связка с другими модулями – это не частый кейс, т.к. чаще всего один модуль == один сервис. Один сервис – это не тоже самое, что одна служба, т.е. это вполне может быть некой связкой многих файлов, многих служб. Получается, что сервисы изолированы, а значит и модули в большинстве своем тоже. Однако проверка работы в связке с остальным осуществляется на неком devel-окружении, который представляет собой очень близкую копию production окружения, но работает на виртуальных машинах.
Дальше, если на devel все ОК, то осуществляется точечная проверка в production окружении. Условно увеличение применения в геометрической прогрессии. Часто получается так, что если 1-2 ноды применили изменения удачно – бояться нечего.

При обновлении модуля: этап проверки в devel окружении может быть опущен, но выкладка происходит постепенно в том случае, если модуль значимый, если нет — можно и везде обновить. Тому, кто занимается обновлением заранее известны последствия.
Для отката – откат в git до последнего стабильного состояния.

environments используем, нам очень нравится. Также используем stages, тоже удобно.
mcollective – да, для получения разных отчетов (мелких и быстрых, для себя, не бюрократических), а также для выполнения команд на серверах (быстро и удобно).
Про hiera я ответил чуть выше – да используем, чем дальше, тем больше.

Постарался ответить максимально подбробно, надеясь на то, что вопросы понял верно. Если интересно что-то еще – спрашивайте.
Добрый день,

Подробности всегда готов рассказать, если будут чуть более конкретные вопросы, например «как работает вот это?», «как делаете вот то?».
Модули создаем по двум путям:
1. пишем руками, проверяем также руками, далее с помощью «карты сервисов» привязываем «сервис-модуль».
2. когда понимаем, что модуль (кусок манифестов или целиком) можно(нужно) формировать автоматически – пишем костыль скрипт, который как-раз и будет формировать модуль по заданному нами сценарию.

Что касается тестирования: разные окружения, puppet parser validate, оценка времени выполнения/применения тех или иных ресурс-типов, использование графов, которые puppet умеет формировать сам, использование визуальных инструментов, например, foreman, в котором удобно смотреть динамику применения манифестов.

external_node scripts не используем и/или используем минимум от этого функционала.

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность