Главная » Хабрахабр » Ансамбль солёных поваров-кукловодов: сравниваем Ansible, SaltStack, Chef и Puppet

Ансамбль солёных поваров-кукловодов: сравниваем Ansible, SaltStack, Chef и Puppet

Сегодня мы поговорим о том, что такое SCM и расскажем несколько историй, через призму которых рассмотрим Ansible, SaltStack, Chef и Puppet, выбрав лучший вариант для конкретной задачи.

В основе материала — расшифровка доклада Андрея Филатова, ведущего системного инженера компании EPAM Systems, c нашей октябрьской конференции DevOops 2017.

Что такое SCM и с чем его едят?

В первую очередь это штука, которая позволяет нашу инфраструктуру из состояния A при помощи выполнения какого-то кода привести к состоянию Б. Что же такое SCM? Многие разработчики, которые не являются на практике DevOps инженерами, думают, что каким-то «автомагическим» способом что-то происходит на инфраструктуре.

Для чего это нужно? «Автомагический» способ нам реализует SCM (System Configuration Management). SCM хорошо расширяет CI/CD-процессы. В первую очередь для того, чтобы строить повторяемые и консистентные инфраструктуры. Его достаточно просто развивать и поддерживать. Так как это код, его можно хранить в любой системе контроля версий: Git, Mercurial.

Финальное — это замкнутый цикл автоматизации: все можно делать в автоматическом режиме, от создания инфраструктуры до ее развертывания и deployment-а кода.

Что такое SCM: Ansible

Первый — Ansible. Рассмотрим наших претендентов. Ansible имеет самый низкий порог вхождения — вы можете научить кого угодно. Имеет безагентную архитектуру, если мы говорим об open source-версии, написан на Python, имеет Yaml-подобный DSL, легко расширяемый за счет модулей, написанных на Python, очень простой и легковесный.

Код на Ansible, кто видел Yaml — ничего нового. Есть опыт, когда человек, не зная Python, не зная ничего о SCM, вошел в Ansible буквально за два дня и уже начал что-то делать.
Ниже пример ChatOps: нотификатор в Slack.

- block: - name: "SlackNotify : Deploy Start" local_action: module: slack token: "}" attachments: - title: "Deploy to {{ inventory_hostname }} has been Started" text: "<!here> :point_up_2:" color: "#551a8b" - include: configure.yml tags: - configure - include: remote-fetch.yml tags: - remote - include: assets.yml

Что такое SCM: Chef

Конфигурация основана на поиске, написан на Ruby, имеет Ruby DSL. Chef — это клиент-серверная архитектура, есть Chef-сервер и Chef-клиент. У Chef огромное комьюнити и самый большой набор инструментов среди всех SСM. Соответственно, внутри своих cookbook-ов и рецептов вы можете использовать всю мощь Ruby, но я не советую этого делать. Вот так выглядит код на Chef, это разворачивание Jetty.

#
# Cookbook Name:: dg-app-edl
# Recipe::fe
# node.normal[:jetty][:home] = "/usr/share/jetty"
node.normal[:jetty][:group] = "deploy" include_recipe "dg-auth::deploy"
include_recipe "newrelic::repository"
include_recipe "newrelic::server-monitor"
include_recipe "dg-jetty::jetty9"
include_recipe "newrelic::java-agent" directory "edl" do action :create owner group "deploy" mode "0775" path "/usr/share/where/edl" recursive true
end

Что такое SCM: SaltStack

Упор сделан на автоматизацию в реальном времени, имеет из коробки параллельное исполнение всех процессов и написан на Python. SaltStack имеет как безагентную архитектуру, которая работает в push-режиме при помощи Salt-SSH, так и клиент-серверную архитектуру, когда есть Salt-master и Salt-minion. Тоже Yaml-подобный язык, код очень похож на Ansible.

#ntp-packages: pkg.installed: - pkgs: - ntp - ntpdate #/etc/ntp.conf: file: - managed - source: salt://common/ntpd/ntp.conf - template: jinja - mode: 644 #/etc/sysconfig/ntpd: file: - managed - source: salt://common/ntpd/ntpd - template: jinja - mode: 644 #ntp-service: service.running: - name: ntpd

Что такое SCM: Puppet

Тоже имеет клиент-серверную архитектуру, как Chef, конфигурация основана не на поиске, а на «фактах», которые приходят с Puppet-master-а, написан на Ruby, имеет Ruby-подобный DSL. Последний из наших претендентов — Puppet. Это и плюс, и минус. Но ребята из Puppet не разрешают использовать в своих манифестах чистый код Ruby. Вот так выглядит код манифеста на Puppet:

class { 'mysql::server' : root_password => 'password'
} mysql::db{ ['test', 'test2', 'test3']: ensure => present, charset => 'utf8', require => Class['mysql::server'],
} mysql::db{ 'test4': ensure => present, charset => 'latin1',
} mysql::db{ 'test5': ensure => present, charset => 'binary', collate => 'binary',
}

SСM на практике

SaltStack в условиях демилитаризованной среды

В первую очередь я хотел бы поделиться проектом, который был написан на SaltStack. Это наш предыдущий проект и самая свежая боль, а свежая боль всегда самая больная. Наш заказчик занимается хранением данных — это производство железных серверов для хранения данных на GPFS, GlusterFS, но сборки кастомные. Он пришел к нам со следующими задачами:

  1. Создание USB/DVD инсталлятора. Нужно создать медиа, из которого все инсталлируется. Это делается для клиентов заказчика, которые живут в закрытых зонах, где на серверах чаще всего нет интернета. Нам нужно упаковать в одну ISO, отправлять field-инженерам, которые на месте развернут все необходимое.
  2. Развертывание кластера с продуктом. У заказчиков несколько крупных продуктов, мы должны уметь их разворачивать в кластерном режиме.
  3. Управление, настройка и сопровождение кластера с помощью CLI-утилиты. Наш фреймворк должен помогать field-инженерам управлять кластером.

У заказчика было несколько требований. В первую очередь, у него огромное количество Python-экспертизы, по факту только C и Python-разработчики. Заказчик сразу сказал: «Мы хотим SaltStack», не оставив выбора.

У заказчика в инсталляции есть несколько продуктов, все должны быть c Salt-Master’ами. С чем мы столкнулись? К примеру, у нас в NODЕ Info (состояние конкретного сервера) выбиралось при двухмастерной конфигурации миллисекунды, при трех — уже секунды, а при пяти мы ни разу не дождались завершения операции. Но мы столкнулись с проблемой масштабирования Multi-Master-конфигурации. MultiMaster хорошая фишка, но масштабируется плохо.

Module — расширение, которое выполняется на Salt Minion, на стороне машины. Вторая проблема, с которой мы столкнулись — командная работа: в SaltStack есть Runner и Module. У нас очень часто возникали баталии: что делать Runner, и что делать Modules. Runner выполняется на стороне сервера.

Затем столкнулись с небольшим сюрпризом от сache.mine:

ime = ImeActions()
id = __grains__['id'] if id == ime.master_id: ret = __salt__['mine.get'](id, 'ime_actions.make_bfs_uuid') ime_dict = ret.get(id, None) if not ime_dict: try: result = __salt__['mine.send']('ime_actions.make_bfs_uuid') except Exeption, e: log.error("Failed to generate uuid: {0}.".format(str(e))) result = False else:

У нас есть утилита, которая написана на C. Мы ее запускаем, она генерирует случайный ID. Он должен быть уникален среди всех участников кластера, соответственно, нам это нужно делать один раз на мастере, и дальше распространять среди машин. Мы для этого использовали cache.mine. Как оказалось, он не переживает перезагрузки.

Параллелизация — хорошо, но в базовой конфигурации state.orchestrate приходит в состояние state.sls is running, если происходят длительные процессы. «Race condition». Возникает ошибка. По таймауту он считает, что State уже выполнился, хотя тот еще выполняется, и пытается запустить следующий. И эта проблема пока ещё не исправлена.


Можно посмотреть на GitHub.

Что мы могли использовать, кроме SaltStack?

SaltStack в DMZ окружении

  • DMZ. Chef отлично пакуется, Puppet тоже. А с Ansible проблема — если нет Tower, — нет возможности запустить конфигурацию в Pull-режиме с наших нод, что необходимо делать в демилитаризованной зоне.
  • Framework for CLI (на Python). Chef и Puppet не очень подходят, но если у вас нет ограничений использовать только Python — можно писать на Ruby и использовать API Chef или Puppet. Ansible подобный инструментарий не поддерживает.
  • Cluster Management. Chef хорошо подходит для управления кластерами, Puppet тоже, а Ansible изначально писался для того, чтобы управлять кластерами в Amazon.

Chef в большой и динамичной среде

Заказчик пришел с задачей консолидировать все ресурсы в одном облаке — это был Openstack. До этого все было разбросано: что-то на Rackspace Cloud, что-то на выделенных серверах или своих приватных датацентрах.

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

Мы создали для них SDLC — Software Development Lifecycle, и применили его, в том числе, для SCM. Для того чтобы правильно построить процесс CD, нужна полностью автоматизированная среда. У них проходят интеграционные тесты не только приложений, но и инфраструктуры.

Соответственно, когда у нас идет что-то не так, мы должны, как ребята из Netflix, уметь убивать дефективные ресурсы и на их место восстанавливать свежие и гарантированно рабочие.

С какими проблемами мы столкнулись:

  1. Это был 2013 год, использовали Chef 10, в котором медленный поиск. Мы запускали поиск, обходя все машины, и это занимало вечность. Попытались решить проблему naming-конвенцией, а также выбором и поиском по fqdn. Это сужало область поиска, за счет чего он ускорялся.

    Соответственно, поиск запускался один раз в самом начале, результат сохранялся в атрибуте, и с помощью Ruby фильтровали результаты: парсили нужные нам кусочки и делали, что было нужно. Но некоторые операции нужно делать на всем окружении.

    if !Chef::Config[:solo] search(:node, "fqdn:*metro-#{node[:env]}-mongodb*").each do |mongo| @mongodbs << mongo.fqdn end
    else @mongodbs = ["lvs-metro-#{node[:env]}-mongodb3001.qa.example.com"] end

    Итог: используйте нейминг-конвенции, запускайте поиск один раз, используйте Ruby для фильтрации нужных результатов.

  2. Использовать «node.save» небезопасно, будьте внимательны и осторожны. Мы столкнулись с этой проблемой, когда разворачивали MySQL-кластеры, и использовали внутри рецепта node.save на не полностью сконфигурированной MySQL-ноде. И в момент Scale-up некоторые приложения выдавали 500 ошибку. Выяснилось, что мы не в то время сохраняли ноду: она уходит на Chef-сервер, тут же Chef-клиент на UI подхватывает новую ноду, которая не сконфигурировалась до рабочего режима.
  3. Отсутствие «splay» может убить chef-сервер. Splay — параметр Chef-клиента, который позволяет задать диапазон, когда клиент пойдет к серверу за конфигурацией. При большой нагрузке, когда нужно развернуть много нод одновременно, это позволит не убить сервер.

Что мы можем использовать вместо Chef?

  • Dynamic provisioning. SaltStack подходит идеально, так как у него есть SaltCloud, который отлично интегрируется куда угодно. В Puppet есть подобная функциональность, но она доступна только в Puppet Enterprise, за деньги. Ansible хорошо подходит, если компания «живет» в Amazon, если что-то другое — можно завязать его в альтернативы, но это не так удобно.
  • SDLC. В Chef есть всё, начиная от Test Kitchen до выбора инструментов для интеграционного тестирования. В SaltStack есть весь доступный Python-инструментарий, сейчас в Puppet тоже все есть. В Ansible есть Role Spec, можно использовать Test Kitchen от Chef, но это не нативный инструмент.
  • Resource replacement. В Chef все устроено хорошо, в SaltStack можно допилить SaltCloud до нужного состояния, в Puppet инструменты только в Enterprise-версии, а Ansible хорошо работает только с Amazon.

EPAM Private Cloud с Chef

За год-полтора до появления AWS OpsWorks мы хотели создать расширенный Amazon CloudFormation, интегрировав Chef, чтобы ресурсы не только разворачивались, но и настраивались.

Вторая глобальная задача — создание сервис-каталога, чтобы заказчики и пользователи могли при помощи CLI развернуть полностью готовый к использованию например LAMP-стек.

Мы стартовали со встроенным Chef-Server’ом, а также пользователи могли использовать собственный Chef-Server, который хостится где-то у них. Мы выбрали Chef, но проект должен был поддерживать разные SCM. То есть мы не получали доступа к пользовательским ресурсам и ноутбукам, но это все равно работало.

Для создания каталога — все, кроме SaltStack, хорошо с этим справятся. Для реализации CloudFormation + OpsWork можно использовать любой SCM, подходят все. У SaltStack есть нюансы: найти специалиста, который хорошо знает SaltStack и может создавать сервис и наполнять каталог, крайне сложно.

Популярность SCM в EPAM

SaltStack очень далеко позади. Это статистика популярности SCM внутри EPAM. Когда мы пытаемся найти кого-то на рынке со знанием SCM — рынок выглядит примерно так же. На первом месте Ansible, он самый простой и с низким порогом вхождения.

Работа с Ansible

Советы, которые я могу дать при работе с Ansible:

  1. Используйте ‘accelerate’, он в 2-6 раз быстрее SSH разворачивает конфигурации (для el6). Для всех остальных есть ‘pipelining’. Для обратной совместимости он выключен, но включить обратно ‘pipelining’ очень легко, рекомендую это делать.
  2. Используйте ‘with_items’

    - name: project apt dependencies installed apt: name: "{{ item }}" become: yes with_items: - build-essential - acl - git - curl - gnupg2 - libpcre3-dev - python-apt - python-pycurl - python-boto - imagemagick - libmysqlclient-dev # needed for data import

    В данном примере мы устанавливаем пакеты, эту схему можно использовать для создания пользователей и тому подобных операций.

  3. Аккуратно используйте ‘local_action’ и ‘delegated’. Первый позволяет получить нечто похожее на SaltStack Runner, второй умеет делегировать задачи конкретным машинам.

    - name: create postgresql database postgresql_db: name: "{{ database_name }}" login_host: "{{ database_host }}" login_user: "{{ database_master_user }}" login_password: "{{ database_master_password }}" encoding: "UTF-8" lc_collate: "en_US.UTF-8" lc_ctype: "en_US.UTF-8" template: "template0" state: present delegate_to: "{{ groups.pg_servers|random}}"

    Это кусок по созданию баз данных. Без последней строчки операция выполнилась бы несколько раз и свалилась на второй попытке создать ту же самую базу данных.

  4. Оптимизируйте ваши роли и исполнение при помощи тегов. Это позволяет значительно сократить время выполнения.

Выводы

Лично для меня Ansible — фаворит. SaltStack очень хороший, очень гибкий, но требует знания Python, без них SaltStack лучше не использовать. Chef — универсальная серебряная пуля для любых задач и любых масштабов, но требует больших знаний, чем Ansible. А кто использует Puppet —  я не знаю. В принципе, он очень похож на Chef, но со своими нюансами.

Если вам понравился этот доклад с конференции DevOops — обратите внимание, что 14 октября в Санкт-Петербурге пройдет новый DevOops 2018, в его программе тоже будет много интересного. Минутка рекламы. На сайте уже есть первые спикеры и доклады.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

На все компьютеры в России хотят предустанавливать российские антивирусы

В правительство РФ внесён национальный проект «Цифровая экономика», в паспорте которого указано интересное предложение от Министерство цифрового развития, связи и массовых коммуникаций России: законодательно обеспечить предустановку отечественных антивирусных программ на все персональные компьютеры, ввозимые и создаваемые на территории РФ, начиная ...

Когда нужны скорость и масштабирование: сервер распределенных iOS-устройств

В Badoo прогоняется более 1400 end-to-end тестов для iOS-приложений на каждый запуск регрессии. Многим разработчикам UI-тестов под iOS наверняка знакома проблема времени тестового прогона. Это более 40 машинных часов тестов, которые проходят за 30 реальных минут. Николай Абалов из Badoo ...