Pull to refresh

Comments 38

Спасибо, Андрей. Такой подход действительно экономит кучу времени и сил.
Теперь представьте, что вам нужно разделить эти сайты на две роли app_server и blog_server. Ну и как вы собираетесь это тестировать на dev окружении?


Применяю обе роли на ноду в dev окружении.

Можно рискнуть и надеяться, что все будет ОК или перезаписать атрибуты в Chef Environments (сначала на dev, потом на qa и т.д.) и не забыть почистить их после того, как они попадут на продакшн. Не самый лучший вариант.


А зачем чистить атрибуты environment, которые не касаются продакшена (а значит при правильном использовании никогда там не будут видны)? Как раз при тестировании нового функционала закидываете атрибуты в env, тестируете только на нем, и если все ок — выносите в роль.

Chef роли кажутся идеальнами для хранения списка запускаемых рецептов. Однако, этот подход страдает теми же недостатками, что и предыдущий антипаттерн. Если вы добавите или удалите рецепт из списка run_list в роли, то эти изменения применятся ко всем серверам с этой ролью, включая продакшн серверы.


Это никто не заставляет вас делать. Никто вам не помещает сделать:

knife ssh -E dev ‘role:webapp’ ‘sudo chef-client’

Который только затронет dev environment с ролью webapp.
Теперь представьте, что вам нужно разделить эти сайты на две роли app_server и blog_server. Ну и как вы собираетесь это тестировать на dev окружении?


Применяю обе роли на ноду в dev окружении.

Если изменить роль, то она применится для всех энвов — об этом и речь в статье.
Можно рискнуть и надеяться, что все будет ОК или перезаписать атрибуты в Chef Environments (сначала на dev, потом на qa и т.д.) и не забыть почистить их после того, как они попадут на продакшн. Не самый лучший вариант.


А зачем чистить атрибуты environment, которые не касаются продакшена (а значит при правильном использовании никогда там не будут видны)? Как раз при тестировании нового функционала закидываете атрибуты в env, тестируете только на нем, и если все ок — выносите в роль.

Здесь речь о CI/CD — когда инфраструктурный код движется от дев к проду. И опять же, в роль нельзя, так как это глобальный конфиг и применится ко всем окружениям.
Chef роли кажутся идеальнами для хранения списка запускаемых рецептов. Однако, этот подход страдает теми же недостатками, что и предыдущий антипаттерн. Если вы добавите или удалите рецепт из списка run_list в роли, то эти изменения применятся ко всем серверам с этой ролью, включая продакшн серверы.


Это никто не заставляет вас делать. Никто вам не помещает сделать:

knife ssh -E dev ‘role:webapp’ ‘sudo chef-client’

Который только затронет dev environment с ролью webapp.

Никто не мешает вообще и по ssh зайти и ручками что-то поменять, но тогда зачем Chef?
Если изменить роль, то она применится для всех энвов — об этом и речь в статье.


Ну во первых применится — но не будет выполнена (chef-client сам не узнает про изменения). Вариатны решения без усугубления «Все в кукбуку»:

1) ничто не мешает нам создать отдельную роль (с атрибутами и ран листами) и тестировать на ней, а потом перенести в основную

2) никто не запрещал использовать специальные run_list для env:

{
  "name": "webserver",
  "default_attributes": {
  },
  "json_class": "Chef::Role",
  "env_run_lists": {
    "test": [ "role[base]", "recipe[apache]", "recipe[apache::copy_test_configs]" ],
    "dev": [ "role[base]", "recipe[apache]", "recipe[apache::copy_dev_configs]" ]
    },
  "run_list": [ "role[base]", "recipe[apache]" ],
  "description": "The webserver role",
  "chef_type": "role",
  "override_attributes": {
  }
}


Тоесть для dev и test я указал специфичные run_list, остальные будут использовать стандартный.

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

attribute_i_want = node[node.chef_environment]

Или просто ложим в env :)

Здесь речь о CI/CD — когда инфраструктурный код движется от дев к проду


Используя систему контроля версий создаете отдельную ветку в chef-repo, дальше тестируете в dev (который находится на вашей машине), используя chef-zero и vagrant, что бы не затрагивать основной сервер. По завершению — мерджим в мастер и заливаем на сервер. Вот так делаем движение от dev to prod.

Никто не мешает вообще и по ssh зайти и ручками что-то поменять, но тогда зачем Chef?


В моем примере все делается через knife, усугубления «руками» или работа без Chef в нем не присутствуют.
Ну во первых применится — но не будет выполнена (chef-client сам не узнает про изменения).

Извини, но бред написал. Чисто для теста:

$ knife role edit ftp:

{
  "name": "ftp",
  "description": "",
  "json_class": "Chef::Role",
  "default_attributes": {
  },
  "override_attributes": {
  },
  "chef_type": "role",
  "run_list": [
    "recipe[test1]",
    "recipe[test2]"
  ],
  "env_run_lists": {
  }
}


$ knife ssh "role:ftp" "tailf /var/log/chef/client.log" -x ec2-user -i /home/ec2-user/test.pem
ip-10-1-12-98.eu-west-1.compute.internal [2014-01-27T18:48:41+00:00] INFO: Running start handlers
ip-10-1-12-98.eu-west-1.compute.internal [2014-01-27T18:48:41+00:00] INFO: Start handlers complete.
ip-10-1-12-98.eu-west-1.compute.internal [2014-01-27T18:48:41+00:00] INFO: HTTP Request Returned 404 Object Not Found:
ip-10-1-12-98.eu-west-1.compute.internal [2014-01-27T18:48:41+00:00] INFO: HTTP Request Returned 412 Precondition Failed: {"message"=>"Run list contains invalid items: no such cookbooks test1, test2.", "non_existent_cookbooks"=>["test1", "test2"], "cookbooks_with_no_versions"=>[]}
ip-10-1-12-98.eu-west-1.compute.internal [2014-01-27T18:48:41+00:00] ERROR: Running exception handlers
ip-10-1-12-98.eu-west-1.compute.internal [2014-01-27T18:48:41+00:00] ERROR: Exception handlers complete
ip-10-1-12-98.eu-west-1.compute.internal [2014-01-27T18:48:41+00:00] FATAL: Stacktrace dumped to /var/chef/cache/chef-stacktrace.out
ip-10-1-12-98.eu-west-1.compute.internal [2014-01-27T18:48:41+00:00] ERROR: 412 "Precondition Failed"
ip-10-1-12-98.eu-west-1.compute.internal [2014-01-27T18:48:41+00:00] ERROR: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)
ip-10-1-12-98.eu-west-1.compute.internal [2014-01-27T18:48:41+00:00] ERROR: Sleeping for 300 seconds before trying again



Вот именно: «knife ssh» нужно, чтобы выполнить (как я писал после «knife role edit|load from file» ничего не изменится на нодах) или же ставить chef-client как демон (для тестирования мы эту возможность отключаем). А как я писал, никто не запрещает делать эту команду, ограничивая env для роли :)
Не соглашусь с вами. Точнее даже не так: у вас конкретный подход, когда chef-client выключен.
Тогда всё просто: речь идёт о явном запуске и переконфигурации. В большинстве случаев chef-client постоянно крутится на сервере и следит за состоянием серверов. Особенно в клауде.

Добавились 3-4 бэканда — балансер уже «знает» об этом и перенастраивается (без явного вызова chef-client). Именно в таких случаях опасно менять глобальные роли/рецепты и т.д.
Если у вас по 10 серверов на окружение и вы толкнули роль, вероятно, через 3-5 минут 2-3 сервера уже будут перенастроены. Подход выше позволяет контролировать этот процесс и тестировать сначала на отдельных окружениях.

Такая же ситуация и с рецептами: обновил cookbook и везде, где его версия строго не была зафиксирована, он обновится (и что-нибудь сломает).

Кстати, в вашем же случае отключение chef-client как демон — не спасение! Это просто надежда, что «вот пока я буду разрабатывать/тетсить/исправлять баг» никто не додумается запустить chef-client на проде.

PS. В примере выше через knife ssh запускалась команда tail, а не chef-client. Сам по себе knife ssh не запускает реконфигурацию.
В данном коментарии я написал как вообще делается подход разработки или изменения кухни.

Такая же ситуация и с рецептами: обновил cookbook и везде, где его версия строго не была зафиксирована, он обновится (и что-нибудь сломает).


Укажите версии в env.

Кстати, в вашем же случае отключение chef-client как демон — не спасение! Это просто надежда, что «вот пока я буду разрабатывать/тетсить/исправлять баг» никто не додумается запустить chef-client на проде.


Поэтому сначала это и делается на dev (тоесть локальной машине). Я против тестирования вообще на живую на реальном сервере. На сервер заливается уже готовый результат.

PS. В примере выше через knife ssh запускалась команда tail, а не chef-client. Сам по себе knife ssh не запускает реконфигурацию.


B по логам той команды четко видно, что chef-client демонизирован на проверку каждые 5 минут :) и данная команда через knife ssh запускает (была указана в этом коментарии):

knife ssh -E dev ‘role:webapp’ ‘sudo chef-client'
Локальное окружение и dev — обычно разные вещи. А если у вас не так, то значит у вас небольшое количество серверов и участников разработки кукбуков, поэтому вы можете себе позволить запускать клента руками и раскидывать конфигурацию по нескольким сущностям.

Если ещё berkshelf использовать, то указание версий в Chef Environments тоже не будет удобным.
У нас до 100 машин на один Chef Server (у каждого проекта свой сервер, на самом большом проекте уже больше 100, но точное число глянуть не могу — нет доступа). На текущем пока только 24 машины. Не много, но есть и berkshelf, vagrant, chef-zero, fauxhai, chefspec, test-kitchen — развернуть одну ноду на основе кукбуков, ролей и прочего делается на локальной машине (что мы называем development environment) при разработке с покрытием тестами (например меняем ноду роли веб). Далее выкатываем на стейджинг — staging environment (через env и env_run_lists). Если вдруг сломался (риск минимизирован через тесты) — откатываем, чиним, и опять в бой. При успехе раскидывам как нужно по ролям и env, заливаем в мастер ветку и загружаем в сервер. Процес не быстрый, но пока ни одного сбоя (хоть за последнее время все работы сводятся к поддержки кукбуков и софта на нодах «up to date» ).

Если ещё berkshelf использовать, то указание версий в Chef Environments тоже не будет удобным.

Указываем только особо важные кукбуки (или перед тестированием на staging, если просто обновляем вендорные кукбуки).

Локальное окружение и dev — обычно разные вещи.


Вы правы. В моем понимании dev (development environment) — это там, где ведется разработка и первичное тестирование — его машина (ноутбук).
Укажите версии в env.

Именно это и имел в виду, когда говорил:
где его версия строго не была зафиксирована


Поэтому сначала это и делается на dev (тоесть локальной машине)

Не всегда можно воспроизвести всё на локальной машине. Более того, может быть чёткое требование: на PROD1 делай так, а на PROD2 по-другому.

А так, да — сам пытаюсь всё локально проверять и тестить перед отправкой. И все версии зафиксированы строго. Сначала думал, что будет очень тяжело поддерживать все версии. На практике оказалось это очень редкое занятие и отнимает буквально пару минут. Зато не раз спало в сложных ситуациях.

Вот ещё никак руки не дойдут потыкать палочкой vagrant-lxc для поднятия более сложных вещей с меньшими ресурсами…
> Если изменить роль, то она применится для всех энвов — об этом и речь в статье.

Не надо просто держать все энвы на одном шеф-сервере.
Да, есть такой подход. Свои плюсы и минусы.
Минус: дополнительные расходы на содержание одного сервера.

Плюсы: всё достаточно изолировано, можно ограничивать права разработчиков и не пускать их на прод, оставляя полные права на dev/qa/staging.

Очень хорошо, что вы об этом упомянули.

Не нужно так категорично заявлять.

Вы деньги считать умеете? Заказчик — точно. И если окружение не очень большое, то будет использоваться один сервер. Также, возможен вариант, когда окружения не изолированны полностью и нужно, чтобы Chef сервер знал о них все.
> Вы деньги считать умеете? Заказчик — точно. И если окружение не очень большое, то будет использоваться один сервер.

Отдельный шеф-сервер не то же самое, что отдельный физический сервер.
А вы занете из каких (и из скольки) отдельных компонентов состоит Chef-server? И каждый из них потребляет реурсы. И не так-то просто их будет впихнуть в один сервер.
Разумеется, знаю. А также я знаю то, что можно настроить несколько шеф-серверов на использование одного и того же postgres-а, rabbitmq и bookshelf-а, а также подкрутить настройки jvm solr-ов, если окружения небольшие.
Это реальный опыт или теоретические изыскания? Я понимаю, что это возможно, но сколько времени понадобится, чтобы заставить несколько Chef-серверов работать на одной ноде?
> сколько времени понадобится, чтобы заставить несколько Chef-серверов работать на одной ноде

Пара часов, если все впервые руками делать.
Вы сами это делали?
Ещё один момент: каждая копия будет потреблять ресурсы, т.е. все равно нужны пропорциональные мощности. И я не думаю, что держать отдельный Chef-сервер для окружения из двух срверов — это правильно.
>Вы сами это делали?

Да.

>Ещё один момент: каждая копия будет потреблять ресурсы, т.е. все равно нужны пропорциональные мощности.

Если вы беспокоитесь за ресурсы, которые могут потребить демоны, то на дополнительный шеф-сервер (erchef, webui, solr) уйдет 300 мегабайт (bookshelf, postgres, rabbitmq общие). И это если не урезать память jvm solr-а, которому для пары серверов dev окружения явно потребуется ее меньше, чем для продакшена.

>И я не думаю, что держать отдельный Chef-сервер для окружения из двух срверов — это правильно.

Почему, кроме экономии полугигабайта памяти?
Дополнительные рецепты также могут быть включены, но тогда это правильнее называть application cookbook (прим. переводчика).


С моей точки зрения wrapper-cookbook не перестает быть wrapper'ом при расширении, например Jetty-cookbook не умеет ставить Jetty9 если мы в своей обертке добавим эту возможность, разве он станет при таком подходе App-cookbook'ом?
Ты прав, lincore. Я поправлю в статье. Спасибо за замечание.
Видел статьи epam о puppet, как считаете, где usecase для puppet а где для chef?
Трудно разделить их объективно. Оба инструмента позволяют готовить инфраструктуру, автомтизировать любые задачи. Лично для меня, был путь Chef -> Puppet. После Chef-а Puppet кажется более бедным и не таким гибким по функционалу. Но это лишь мое личное мнение. Ещё Chef может предоставлятся как сервис (Enterprise Chef), так что начать его использовать легче.
Спасибо за ответ, интересно почитать Ваше мнение. Мое мнение, если хотите, что puppet не чуть не уступает chef, т.к. весь функционал написан на том же ruby, с дополнением приятного DSL для людей, которые не хотят вникать в то, что конкретно puppet делает для достижения цели, а хотят сфокусироваться на самой конфигурации и конечном состоянии инфраструктуры (ИМХО, конечно:). Проверено на .net девелоперах, которые уже сами создают свои манифесты и конфигурируют IIS хосты при помощи puppet — для них это как INI файл =)
Лично пока с puppet не работал, но мой друг столкнулся с проблемой организации циклов, которые DSL не поддерживает (во всяком случае я такое от него услышал год назад). И ему пришлось сильно постараться.

Всё-таки puppet основан на DSL, который явно ограничен по сравнению с plain ruby. А сам по себе язык ruby имеет довольно приятный синтаксис.

Но, давайте не будем сравнивать тёплое с мягким, а остановимся на более конкретных вещах.

В последнее время, что в сообществе Chef, что в Puppet (да и других) очень часто тиражируют бесполезные «красивые» примеры применения в стиле «как поставить apache + wordpress» или «добавить юзера в mysql».

Очень не хватает реальных задач, который имеют свои особенности и не являются такими тривиальными. Вот тут-то и начинается самое интересное.

Вот, например, какую мне пришлось решить:
Установить и настроить mongodb cluster с возможностью объединения нод в реплики (replicaset) и добавлением этих реплик или просто нод как shard в общий кластер. При этом нужно уметь:
* держать на одном сервере несколько демонов: config db, mongo router и какой-нибудь mongod инстанс; или MongoDB Arbiter для ReplicaSet1 вместе с Mongod для ReplicaSet2
* Добавлять на лету ноды в реплику, реплики/шарды в кластер
* Иметь возможность дополнительно настраивать реплики (rs.conf())

Вот такая вот интересная задачка. Можно подумать как её решить с использованием Chef, а как с использованием Puppet.

Как только задачи перестаёт быть сферической в вакууме, сразу станет понятнее, что лучше использовать.

В интернете можно найти несколько cookbooks для MongoDB, но есть впечатление, что авторы не читали документацию вообще. И сколько бы там всего заявлено не было, хорошо, если этот cookbook сможет поднять примитивный кластер или реплику.
Оооочень разумный комментарий — Спасибо!

По поводу «красивых» примеров — да, Вы отчасти правы. Но все преимущество puppet в том, что весь heavy-lifting прячется в коде модуля, который написан на ruby, и очень часто конечными точками, с которыми работают девелоперы/админы являются манифесты на puppet DSL, где обычно задаются параметры ресурса. Поэтому такой ресурс вполне имеет смысл.

Вот идеальный вариант (mock code):
node "mongo-1a" {
	mongo_node {"data_27001":
	  type => "awesome_cluster_type"  #Я - часть кластера awesome_cluster_type
	  shard => sh_1, #Я - часть шарда sh_1
	  rs => rs_1, #Я часть репликасет rs_1_sh1
	}

	mongo_node {"data_27002":
	  type => "awesome_cluster_type"  #Я - часть кластера awesome_cluster_type
	  shard => sh_1, #Я - часть шарда sh_2
	  rs => rs_1, #Я часть репликасет rs_1_sh2
	}
}

node "mongo-1b" {
	mongo_node {"data_27001":
	  type => "awesome_cluster_type"  #Я - часть кластера awesome_cluster_type
	  shard => sh_1, #Я - часть шарда sh_1
	  rs => rs_1, #Я часть репликасет rs_1_sh1
	}

	mongo_node {"data_27002":
	  type => "awesome_cluster_type"  #Я - часть кластера awesome_cluster_type
	  shard => sh_1, #Я - часть шарда sh_2
	  rs => rs_1, #Я часть репликасет rs_1_sh2
	}
}


node "mongo-2a" {
	mongo_node {"data_27001":
	  type => "awesome_cluster_type"  #Я - часть кластера awesome_cluster_type
	  shard => sh_1, #Я - часть шарда sh_1
	  rs => rs_1, #Я часть репликасет rs_2_sh1
	}

	mongo_node {"data_27002":
	  type => "awesome_cluster_type"  #Я - часть кластера awesome_cluster_type
	  shard => sh_1, #Я - часть шарда sh_2
	  rs => rs_1, #Я часть репликасет rs_2_sh2
	}
}

node "mongo-2b" {
	mongo_node {"data_27001":
	  type => "awesome_cluster_type"  #Я - часть кластера awesome_cluster_type
	  shard => sh_1, #Я - часть шарда sh_1
	  rs => rs_1, #Я часть репликасет rs_2_sh1
	}

	mongo_node {"data_27002":
	  type => "awesome_cluster_type"  #Я - часть кластера awesome_cluster_type
	  shard => sh_1, #Я - часть шарда sh_2
	  rs => rs_1, #Я часть репликасет rs_2_sh2
	}
}

А сам модуль уже позаботится о том, чтобы все встало куда нужно (вот он и heavy-lifting) — как раз там будут все циклы и условия.

Сейчас я делаю всю конфигурацию вручную (не так часто поднимаются новые кластеры). Но каждый раз когда я читаю (свою же) документацию — это огромная головная боль не ошибиться в портах, так-как у меня на одном сервере 3 конфиг ноды от другого шарда, mongos, arbiter и 3 дата-ноды :)

Посмотрел на существующие решения и на мой первый взгляд установка всех компонентов на сервер при помощью puppet достаточно тривиальная задача (есть puppetlabs/mongodb и echocat/puppet-mongodb).

Основная сложность в синхронизации нод между собой, сейчас мы используем foreman, и для выполнения этой задачи, возможно, потребуется использовать node.pp (как в примере выше) с описанием всех нод разом — удобнее портировать в облако или на другой новый кластер, к примеру.

Также описание кластера в виде конфигурации puppet явно поможет улучшить понимание кластера другими разработчиками.

Как только появится задача по поднятия еще одного кластера (думаю достаточно скоро) — зафиксирую все в puppet, обещаю :)
Допустил пару ошибок, вот что в идеале имелось в виду:
node "mongo-1a" {
	mongo_node {"data_27001":
	  type => "awesome_cluster_type"  #Я из awesome_cluster_type
	  shard => sh_1, #Я - часть шарда sh_1
	  rs => rs_1_sh1, #Я часть репликасет rs_1_sh1
	}

	mongo_node {"data_27002":
	  type => "awesome_cluster_type"  
	  shard => sh_2,
	  rs => rs_1_sh2,
	}
}

node "mongo-1b" {
	mongo_node {"data_27001":
	  type => "awesome_cluster_type"  
	  shard => sh_1,
	  rs => rs_1_sh1,
	}

	mongo_node {"data_27002":
	  type => "awesome_cluster_type"  
	  shard => sh_2,
	  rs => rs_1_sh2,
	}
}


node "mongo-2a" {
	mongo_node {"data_27001":
	  type => "awesome_cluster_type"  
	  shard => sh_1,
	  rs => rs_2_sh1,
	}

	mongo_node {"data_27002":
	  type => "awesome_cluster_type"
	  shard => sh_2,
	  rs => rs_2_sh2,
	}
}

node "mongo-2b" {
	mongo_node {"data_27001":
	  type => "awesome_cluster_type"
	  shard => sh_1,
	  rs => rs_2_sh1,
	}

	mongo_node {"data_27002":
	  type => "awesome_cluster_type"
	  shard => sh_2,
	  rs => rs_2_sh2,
	}
}
А что будете делать, если в монго-реплике будет количество нод меняться, например при авто-масштабировании?
Количество нод в реплике есть смысл увеличивать только когда нужно много read либо redundancy, чаще проще масштабировать «в ширь» и добавлять шарды, что увеличит не только read но и write производительность, это если я правильно Вас понял.
Но основной вопрос не в этом, о каком способе авто-масштабировании идет речь? Из программного кода? На виртуальные инстансы? Если да, то это будет чуть сложнее, но не на много: нужно интегрироваться с foreman или puppet dashboard, используя их api проделывать тоже самое, устанавливая соответствующие параметры для ресурса mongo_node. Но когда есть настоящее авто-масштабирование, например на EC2, это не должно быть проблемой поднять ноду с нуля.

Я правильно понял вопрос?
Да. Вы правильно поняли. Я как раз и ожидал примерно такого ответа. Если точнее, то речь не только о EC2 auto scaling, а о любом кластере и автоматическом добавлении/удалении нод. В Puppet приходится изобретать велосипед, в то время к в Chef есть унифицированное API. Это, на мой взгляд, главное отличие.

Вот пример из community cookbook elasticsearch:

seeds = search(:node, "elasticsearch_cluster_name:#{node[:elasticsearch][:cluster_name]} AND elasticsearch_seed:true").sort_by { |n| n.name }.collect {|n| n["ipaddress"]}

node[:elasticsearch][:seeds] = seeds

Таким простым способом получаем список нод, которые объединяются в кластер. При добавлении/удалении ноды изменится и результат поиска и кластер автоматически перенастраивается.
Это явно проще, но в puppet, как оказалось такое можно сделать при помощи puppetdb и puppetdbquery.

Кстати, где chef хранит информацию о текущем состоянии той или иной конфигурации?
Тут вы по сути описали волшебную кнопку, которую надо нажать. А речь шла скорее про то, на сколько тяжело эту самую кнопку сделать. с таким же успехом я бы мог ответить на свой вопрос так:
node.set['mongodb']['install'] = true
node.set['mongodb']['build_me_really_cool_cluster'] = true
node.set['mongodb']['with'] = [ :shards, :replicas, :routers]
node.set['mongodb']['configure_it'] = :immediately
include_recipe "mongodb::fix_all_errors"


Дополню этот вопрос:
Как вы добавите шард в кластер, даже если кол-во нод не будет меняться? Как вы настроите реплику?
Было бы здорово, если существовала такая волшебная кнопка! :) Сейчас у меня не существует решения, т.к. практически задачи не стоит, но если говорить на словах, то выходит следующее:
Ресурс mongo_node, который я описал — верхушка айсберга. За ним — стоит ruby code и другие классы puppet. Но это был всего лишь пример, глянул глубже, вот пример который лежит по второй ссылке, который я присылал в одном из комментариев выше:

    node mongo_sharding_default {

        # Install MongoDB
        include mongodb

        # Install the MongoDB shard server
        mongodb::mongod {'mongod_Shard1': mongod_instance => "Shard1", mongod_port => '27019', mongod_replSet => "Shard1", mongod_shardsvr => 'true' }
        mongodb::mongod {'mongod_Shard2': mongod_instance => "Shard2", mongod_port => '27020', mongod_replSet => "Shard2", mongod_shardsvr => 'true' }
        mongodb::mongod {'mongod_Shard3': mongod_instance => "Shard3", mongod_port => '27021', mongod_replSet => "Shard3", mongod_shardsvr => 'true' }
        mongodb::mongod {'mongod_Shard4': mongod_instance => "Shard4", mongod_port => '27022', mongod_replSet => "Shard4", mongod_shardsvr => 'true' }

        # Install the MongoDB Loadbalancer server
        mongodb::mongos {
            'mongos_profile':
                mongos_instance      => 'mongoproxy',
                mongos_port          => 27017,
                  mongos_configServers => 'mongo1.my.domain:27018,mongo2.my.domain:27018,mongo3.my.domain:27018'
        }
    }

    node 'mongo1.my.domain',
        'mongo2.my.domain',
        'mongo3.my.domain' inherits mongo_sharding_default {

        # Install the MongoDB config server
        include mongodb
        mongodb::mongod {
            'mongod_config':
                mongod_instance  => 'profileConfig',
                mongod_port      => '27018',
                mongod_replSet   => '',
                mongod_configsvr => 'true'
        }
    }

    node 'mongo4.my.domain' inherits mongo_sharding_default { }


Здесь создается базовый тип сервера монго при помощи inherits mongo_sharding_default наследуем эти параметры на нужные хосты, а далее дополнительно ставим на те же хосты конфиг ноды.

На 4й сервер ни mongos ни конфиги не ставятся.

Я это не проверял, но по мне вполне удовлетворительная конфигурация.

Как вы добавите шард в кластер, даже если кол-во нод не будет меняться? Как вы настроите реплику?

Как добавлять шард в кластер — добавляем в базовое описание:

mongodb::mongod {'mongod_Shard5': mongod_instance => "Shard5", mongod_port => '27023', mongod_replSet => "Shard5", mongod_shardsvr => 'true' }


Я ни разу не использовал chef, поэтому ни в коем случае не холиварю здесь. Знаю о нем только по-наслышке и из недостатков лично для меня вижу (если это не так, буду рад услышать опровержение):

— Puppet декларативный, мне проще думать о конечном состоянии сервера а не о пути к нему, когда я внедряю новый конфиг — девелоперы не запариваются о том, в каком состоянии сейчас находится сервер. Отсюда другой подход, в том числе на первый взгляд бедном DSL. Если рассматривать DSL как «умный» .ini или .conf файл, тогда все встает на свои места и heavy lifting делается в самом провайдере, а не в манифесте, что увеличивает читабельность кода.

Типичное сравнение:

service "example_service" do
  action :start
end

и

service {"example_service":
  ensure => running,
}


— Уровень абстракции «ресурс» позволяет мыслить на этом уровне, забывая местами о типе операционной системы, что очень удобно и позволяет сильно унифицировать код для инфраструктуры-зооопарка (У меня Windows + CentOS + Ubuntu) — в chef это тоже поддерживается и тот же пример со службой сработает, но для меня концепт «продвинутого конфигурационного» выглядит удобнее чем «инструкции к применению», но опять же это все очень субъективно. На сайте puppet labs этот DSL называют «Человеческий интерфейс» :)
Так, вот, говоря о конфигурации mongo кластера — я буду уверен в результате, если скажу «Должно быть вот так», вместо «Нужно сделать последовательность действий» (а какой результат Вы хотели)?..
Все остальное очень схоже, и особенно сравнивать технологии смысла нет =)
Все это ИМХО человека, который почти 3 года пишет инфраструктуру на puppet и не пробовал, но слышал об особенностях chef.
В примере выше — у вас хардкод, в частности — хардкод хостов, например, список где конфиг-сервера стоят.
Недавно разговаривал с представителем opscode на конференции SCALE. Как Вы и указали ранее, из коробки все используют поиск, который решает проблему оркестрации (знать о текущем состоянии конфигурации кластера и действовать на основании этого).
Также узнал много нового из «первых уст», и как оказалось, в действительности в chef та же абстракция от уровня ос, и декларативная модель. А еще я узнал почему используется install («что сделать? — Установить.»), вместо puppetовского «installed» («как должно быть? — Установлено). Ходят слухи, что они такое сделали чтобы не казаться „слизанными“ с набирающего тогда обороты puppet.
В общем будет возможность — буду пробовать chef, а пока уже половина всей инфраструктуры описаны в puppet.
Кстати, chef теперь поддерживается в theforeman — рекомендую попробовать, хорошая штука.

Всем добра и ясных инфраструктур!
Sign up to leave a comment.