Как стать автором
Обновить

Комментарии 38

Имеет ли смысл использовать эти инструменты для деплоймента (1 раз 2-4 недели) своего продукта в системе CI/CD?

  • Ansible: Хорошо подходит для средних и малых инфраструктур, но может столкнуться с проблемами при масштабировании до очень больших систем.

Какие у ансибла проблемы при масштабировании до очень больших систем? Можно с этого места поподробнее?

Работаю в крупняке где у нас и Chef и Ansible. В любом случае предпочту Ansible. Зачем нужны другие системы кроме Ansible в 2023 году мне не понятно.
По Chef ещё складывается ощущение что сообщество на него подзабило, основные доки, статьи и прочее обычно находятся довольно старые, типа там 2012-2016.

Chef уже давно устоялся, что то новое про него и не напишешь. Статьи 2012 скорее всего актуальны сегодня и будут работать, в этом его фишка.

Ansible все еще сырой в плане IaaC, Molecule конечно шаг вперёд по сравнению с тем же Test Kitchen, но местами недопилен. Написание своих модулей после Chef кажется странным, сильно много шела.

Для действительно сложного проекта всегда предпочитайте Chef, порог входа выше, но сложные вещи на нем делаются проще чем в Ansible.

Что именно странного в модулях ансибла и при чем тут шелл?

Можно пример сложной вещи которая делается проще?

Для IaaC есть Terraform

Отвечать вопросом на вопрос - это демагогия. Ваша цитата звучала так:

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

Можно уточнить - что именно вы имели в виду? В чем именно странность и как это связано с шеллом?

Это был не я :)

Тут скорее пробема в том, что Ansible использует Push-model, и там где я могу вызвать нативный метод Ruby, приходится иногда писать много Python обвязок для Shell.

По поводу сложных вещей, даже просто (не)запускать какой-то ресурс в зависимости от того есть файл или нет, нужно писать много кода.

При написании собственных модулей в Ansible мне не хватает Chef`овского LWRP, когда в коде ресурса ты используешь тот же код что и в рецепте. В Ansible ты пишешь на дргугом языке - Python.

Ну и в целом я не фанат Jinja программирования, что в Ansible что в SaltStack.

Тут скорее пробема в том, что Ansible использует Push-model, и там где я могу вызвать нативный метод Ruby, приходится иногда писать много Python обвязок для Shell.

Как связана push-модель с обвязками для shell, все еще непонятно, если честно. Что мешает использовать нативные вызовы Python вместо shell, тоже не очень понятно. Количество питоновских библиотек для управления разными ресурсами инфраструктуры уж точно не меньше, чем на Ruby.

При написании собственных модулей в Ansible мне не хватает Chef`овского LWRP, когда в коде ресурса ты используешь тот же код что и в рецепте. В Ansible ты пишешь на дргугом языке - Python.

Не понимаю, о чем вы, если честно. О каком "другом" языке идет речь и по отношению к чему он другой? Если речь о модулях, то их можно писать на любом языке, вообще говоря. Хоть на Ruby, хоть на Go, хоть на бейсике.

В том-то и дело что это любой другой язык, но не YAML, т.е. я не совсем понимаю зачем нужен YAML в ролях, если что-то сложнее install, restart нужно писать на Python. Плюс Jinja, это третий DSL, это и не Python и не YAML, после ERubis в Chef, где все, от метадаты в кукбуке до темплейтов в конфигах это Ruby код, это все очень напрягает.

Не поймите меня неправильно, я в равной мере владею и Ansible и Chef и мое недовольство не идет от незнания технических деталей, исключительно из опыта применения обеих CM в больших проектах.

Ansible победил всех своей простотой входа, но повторюсь еще раз, для сложных вещей он становится слишком громоздким.

Yaml - просто наиболее удобный и человекочитаемый формат. Поэтому он и выбран как язык описания структуры в плейбуках, инвентаре и прочих файлах с данными. Так-то в принципе ничего не мешает писать ансибл-плейбуки в json-формате, только получается гораздо менее читабельно и гораздо более неудобно. Весь код в ансибле убран внутрь модулей и плагинов, на уровне плейбуков и ролей все максимально лаконично и декларативно. Не понимаю, что тут может напрягать. Месье любит сложности на пустом месте?

Ну что же вы так, YAML единственное тем и удобен, что он не JSON, на этом его удобство "всё". Это действительно язык описания структуры, поэтому он хорошо подходит для описания состояния системы...пока вам не нужна логика. Как только нужна логика, начинается веселуха со всякими ужасами типа TOML (Helm) или Jinja (Ansible, SaltStack). Для Jinja получается что языка три, YAML, Python, Jinja.

В Ansible, сколько нибудь сложный проект превращается вот в это - https://github.com/splunk/splunk-ansible/blob/develop/roles/splunk_cluster_master/tasks/main.yml, код не мой, но мне приходилось его адаптировать, лучше чем он есть его и не напишешь.

Вот пару примеров того что мне не нравится в Ansible:

  1. Сможете с ходу ответить в чем разница между Action и Module в Ansible и зачем их делить?

  1. Перепишите на Ansible:

  2. services = ['jboss1', 'jboss2', 'jboss3']
    services.each do |svc|
    template "/etc/jboss/conf/#{svc}.conf" do
    source "#{svc}.conf.erb"
    notify :reload, "service[#{svc}]", :delayed
    end
    service svc do
    action :nothing
    notify :reload, 'service[nginx]', :delayed
    end
    end

    # Task with '*', restart nginx now, without reloading JBosses before run end
    template '/etc/nginx/nging.conf' do
    source 'nginx.conf.erb'
    notify :restart, 'service[nginx]', :immidiately
    end

    service 'nginx'

    # Some other actions
    # ...

  3. Сравните код для InSpec и TestInfra:

    def test_nginx_is_installed(host): nginx = host.package("nginx") assert nginx.is_installed assert nginx.version.startswith("1.2") def test_nginx_running_and_enabled(host): nginx = host.service("nginx") assert nginx.is_running assert nginx.is_enabled

  4. InSpec:

    describe package('clamav') do it { should be_installed } its('version') { should eq '0.98.7' } end describe service('clamd') do it { should be_enabled } it { should be_installed } it { should be_latest } it { should be_running } end

В Ansible, сколько нибудь сложный проект превращается вот в это - https://github.com/splunk/splunk-ansible/blob/develop/roles/splunk_cluster_master/tasks/main.yml, код не мой, но мне приходилось его адаптировать, лучше чем он есть его и не напишешь.

Я бы взялся написать лучше. Как минимум, ветвление по разным сценариям можно делать не так, с кучей when, а с использованием лукапа first_found.

  1. Сможете с ходу ответить в чем разница между Action и Module в Ansible и зачем их делить?

Вам нужно объяснять, что такое Action Plugin? Он всегда исполняется на контрол-ноде и может сам под капотом вызывать модуль или параметризовать его. Модуль - просто скрипт, который отправляется на таргет-ноду для выполнения. Деление позволяет добавлять мета-логику вроде того же package, который определяет package-менеджер и под капотом запускает соответствующий модуль на таргете.

Мне не нравится что Ansible плодит сущности для того что называется ресурс (без привязки к СМ).

Ansible изначально был "SSH на стероидах", а уже потом стали изобретать архитектуру, отсюда все эти сложности: plugin, filter, lookup, action, module (хотя это все ресурс, еденица конфигурирования).

Роли до сих пор не оформились как самостоятельная еденица, как библиотека в этом нашем программировании, которую можно разрабатывать независимо от других библиотек. FQCN даже в документации используются не везде, и т.д.

В Chef и Puppet это все было в ~2009 году.

  1. Перепишите на Ansible:

    services = ['jboss1', 'jboss2', 'jboss3']services.each do |svc|template "/etc/jboss/conf/#{svc}.conf" dosource "#{svc}.conf.erb"notify :reload, "service[#{svc}]", :delayedendservice svc doaction :nothingnotify :reload, 'service[nginx]', :delayedendend

    # Task with '*', restart nginx now, without reloading JBosses before run endtemplate '/etc/nginx/nging.conf' dosource 'nginx.conf.erb'notify :restart, 'service[nginx]', :immidiatelyend

    service 'nginx'

Без проблем. Если в лоб, то будет примерно так:

vars:
  services:
    - jboss1
    - jboss2
    - jboss3

tasks:
  - name: Configure JBoss services
    template:
      src: "{{ item }}.conf.erb"
      dest: "/etc/jboss/conf/{{ item }}.conf"
    notify:
      - reload {{ item }}
    with_items: "{{ services }}"

  - name: Configure nginx
    template:
      src: nginx.conf.erb
      dest: /etc/nginx/nginx.conf
    notify:
      - restart nginx

  - name: Ensure nginx is running
    service:
      name: nginx
      state: started
      enabled: yes

handlers:
  - name: reload {{ item }}
    service:
      name: "{{ item }}"
      state: reloaded
    listen: "reload {{ item }}"
    with_items: "{{ services }}"

  - name: restart nginx
    service:
      name: nginx
      state: restarted

Чуть подлиннее, зато читабельнее. Если сделать кастомный модуль, который сможет сразу конфигурить конфиг и стартовать/рестартовать сервис, то можно и в аналогичный объем текста уложиться.

handlers, будет в другом файле если это роль ;)

Заставьте flush_handlers не перезапускать nginx :D

Это плейбук. При чем тут flush_handlers? У меня в коде этого нет. Но если нужно, то можно сделать. В чем пойнт-то?

При чем тут плейбук, еденица разработки - роль, вы же не плейбуки тестировать будете.
P.S. Как вы код вставляете? У меня в редактировании все ок, в конечном результате вот такое вот.

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

В любом случае непонятна суть вопроса. Вы просили пример аналогичной реализации на ансибле вашего примера с сервисами. Я его привел. Что не так?

P.S. Насчет форматирования. В редакторе есть функция отправки форматированного кода. С выбором языка форматирования (там есть Yaml). Не знаю как у него с поддержкой руби.

  1. Сравните код для InSpec и TestInfra:

    def test_nginx_is_installed(host): nginx = host.package("nginx") assert nginx.is_installed assert nginx.version.startswith("1.2") def test_nginx_running_and_enabled(host): nginx = host.service("nginx") assert nginx.is_running assert nginx.is_enabled

  2. InSpec:

    describe package('clamav') do it { should be_installed } its('version') { should eq '0.98.7' } end describe service('clamd') do it { should be_enabled } it { should be_installed } it { should be_latest } it { should be_running } end

  1. Зачем его сравнивать?

  2. Что нам должно показать это сравнение?

  3. При чем тут Ansible?

Это штатные фреймворки для тестирования. Не будете же вы роль писать без тестов?

В той же молекуле тесты можно писать на самом же ансибле, если что. Тестинфра и прочие фреймворки - не части ансибла, так что непонятно, к чему вы их упомянули.

Еще раз, мне нравится Chef больше но я прекрасно понимаю что массового пользователя он програл )))

У меня есть опыт написания автоматизации на Chef для огромного monolith приложения, 12 разработчиков на Chef, ~290k строк кода. На Ansible это был бы ужас, особенно если учесть что дело было почти 7 лет назад, когда у Ansible даже Ansible-lint не было, не то что Molecule.

В плане IaaC, я имею ввиду ВСЮ инфраструктуру, не считая деплоймента приложения, от промпта в bash до настройки Application Server (Tomcat/JBoss/LAMP).

Больше всего бести, что нельзя в dependency, когда твоя роль:

  • AppRole -- depends --> base_linux_role -- depends --> sudo_role

sudo_role нужно ЯВНО указать в requirements.yml для AppRole, а если таких dependency 60?

Больше всего бести, что нельзя в dependency, когда твоя роль:

  • AppRole -- depends --> base_linux_role -- depends --> sudo_role

sudo_role нужно ЯВНО указать в requirements.yml для AppRole, а если таких dependency 60?

На мой взгляд, это не баг, а фича. Explicit is better than implicit.

Not always, I dont care about thrird level dependencies when setting up infra for app ;)

Ну, в ансибле тоже можно инклудить вложенный код почти до бесконечности, если есть такое желание.

ansible-galaxy не тянет dependency дальше первого уровня, самому нужно подбирать для каждой роли, что капец как неудобно если ты разрабатываешь большой проект.

При чем тут galaxy? Зависимости на уровне реп - вообще зло, на мой взгляд. Хотите все в одном - берите монорепу и там включайте код друг в друга как хотите. В Ансибле на такой случай есть коллекции, например.

Мы с Вами друг-друга не понимаем :D

Galaxy это dependency manager и он очень хреновый.

Еденица исполнения может и плейбук, а вот еденица разработки - роль. И ее действительно очень тяжело разрабатывать отдельно в Ansible. Коллекции конечно есть, но это тоже умножение сущностей, из-за странностей архитектуры. Получается что все роли организации должны быть в одной коллекции чтобы их можно было использовать без заморочек, но тогда все должны использовать latest роли, а так в жизни не получается.

Вы ярый фанат Ansible, это я понял ;) Попробуйте Chef + Test Kitchen + InSpec, хотя бы для саморазвития и расширения горизонтов, если что спрашивайте в PM.

Galaxy - это вообще не dependency manager, если на то пошло, он просто позволяет удобно выкачивать роли и коллекции из репозитория, а также релизить их туда. Но можно обойтись и без него.

Еденица исполнения может и плейбук, а вот еденица разработки - роль. И ее действительно очень тяжело разрабатывать отдельно в Ansible.

Я не знаю такого понятия как "единица разработки". Код в ансибле запускается с помощью плейбуки и именно плейбук - первичная структурная единица сценариев автоматизации в ансибле. Можно сделать проект на ансибле с нормально работающими сценариями и сложной структурой, вообще не используя роли. Роль - вспомогательная сущность для более удобной переносимости части кода в структурированном виде. Но она вовсе не является необходимой. Я не знаю, что значит "разрабатывать роль отдельно", без плейбука, в контексте которого запускается роль, она вообще бесполезна в любом случае.

Коллекции конечно есть, но это тоже умножение сущностей, из-за странностей архитектуры.

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

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

Никто не заставляет держать все роли в одной коллекции. Просто в рамках одной коллекции действует единый контекст переменных и тасков, и там удобно делать шаринг кода между плейбуками и ролями. А в конкретной плейбуке вы можете включать роли из любой коллекции, вообще говоря. Коллекции имеют глобальный контекст по отношению к плейбукам, и это очень удобно. Можно не вспоминать, где у тебя лежит конкретный плейбук, а запускать его из любого места с указанием FQCN. Версионирование для коллекций работает точно также, как и для ролей.

Вы ярый фанат Ansible, это я понял ;) Попробуйте Chef + Test Kitchen + InSpec, хотя бы для саморазвития и расширения горизонтов, если что спрашивайте в PM.

У меня есть опыт с Chef, использовали на многих проектах ранее. Но позже пришли к выводу, что проще все на Ансибл смигрировать, т.к. количество эффортов на поддержку кодовой базы сокращается в разы.

У Chef есть без серверный вариант запуска - chef-zero.

Плюс стоит упомянуть что два года назад у него поменялась лицензия, так что если вы не платите за неё, лучше использовать Cinc (https://cinc.sh), тот же Chef только под другим именем.

Странно что в обзор не включили SaltStack. По-моему весьма достойное решение: всем знакомый yaml, хорошее горизонтальное масштабирование и pull-модель.

В примерах Ansible не хватает FQCN

Еще забыли упомянуть, что в отличие от Puppet/Ansible, Chef является продуктом платным)

еще есть SaltStack, который тоже, как и Chef и Puppet проиграл конкуренцию Ansible с его Ansible Galaxy и пользовательской базой.

Chef Supermarket был уже старым когда Ansible Galaxy еще не было)))

Chef и Puppet програли массового пользователя, технологически они взрослее Ansible.

Уважаемые участвующие в обсуждениях!

Расскажите, пожалуйста, какая система была Вами выбрана самой первой (для самого первого проекта) и почему?

Спасибо.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий