Ускоряем Ansible с помощью Mitogen

  • Tutorial

Ansible стал одним из самых популярных Configuration Management систем. После того как был куплен Red Hat в 2015 году число участников проекта превысило тысячи и Ansible стал наверное самым используемой системой развертывания и оркестрации. Его широкие области применения очень впечатляют.


Ansible работает через SSH соединения к удаленным хостам. Он открывает SSH сессию, делает логин, копирует код на Python по сети и записывает его в отдельный временный файл. После этого он запускает этот файл на удаленной машине. Вся эта последовательность операций довольно долгая и нудная, поэтому существуют различные способы ее оптимизировать.


Одним из этих способов является SSH pipelines который позволяет использовать одну SSH сессию для исполнения инструкций, а не открывать каждый раз новую сессию, что может экономить нам много времени. (Только не забывайте отключить requiretty настройку для sudo в вашем /etc/sudoers файле на удаленной машине)


Новым способом "разогнать" Ansible является библиотека python по имени Mitogen. если кто-то о ней не слышал — то вкратце опишу ее функциональность. Она позволяет быстрое исполнение кода python на удаленной машине и Ansible это только один из примеров использования. Mitogen использует UNIX pipe на удаленной машине и передает код python сжатый zlib и сериализованный с помощью pickle. Это помогает выполнять его быстрее и экономит трафик. Если вы заинтересованы в более детальном объяснении, лучше всего прочитать об этом на странице "How it works". Но сегодня мы сфокусируемся только на работе библиотеки с Ansible.


Mitogen в определенных обстоятельствах может ускорить ваш Ansible код в несколько раз и значительно уменьшить расход трафика. Давайте проверим самые популярные примеры использования и посмотрим насколько нам это помогает.


Я больше всего использую Ansible для: создания файлов конфигурации на удаленной машине, установка пакетов, копирование файлов на удаленную машину и обратно. Возможно у вас есть другие примеры — напишите в комментариях.


Поехали!


Конфигурация Mitogen для Ansible очень проста:
Устанавливаем Mitogen библиотеку:


pip install mitogen

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


Предположим что путь к установленному Mitogen будет /usr/lib/python2.7/site-packages/ansible_mitogen/plugins/strategy. Тогда:


export ANSIBLE_STRATEGY_PLUGINS=/usr/lib/python2.7/site-packages/ansible_mitogen/plugins/strategy
export ANSIBLE_STRATEGY=mitogen_linear

или


[defaults]
strategy = mitogen_linear
strategy_plugins = /usr/lib/python2.7/site-packages/ansible_mitogen/plugins/strategy

Установим Ansible в virtualenv, с Mitogen и без нее:


virtualenv mitogen_ansible
./mitogen_ansible/bin/pip install ansible==2.7.10 mitogen
virtualenv pure_ansible
./pure_ansible/bin/pip install ansible==2.7.10

Обратите внимание что Mitogen 0.2.7 не работает с Ansible 2.8 (на май 2019)


Делаем aliases:


alias pure-ansible-playbook='$(pwd)/pure_ansible/bin/ansible-playbook'
alias mitogen-ansible-playbook='ANSIBLE_STRATEGY_PLUGINS=$(pwd)/mitogen_ansible/lib/python3.7/site-packages/ansible_mitogen/plugins/strategy ANSIBLE_STRATEGY=mitogen_linear $(pwd)/mitogen_ansible/bin/ansible-playbook'

Теперь попробуем запустить playbook создающий файлы на удаленной машине:


---
- hosts: all
  gather_facts: false
  tasks:
    - name: Create files with copy content module
      copy:
        content: |
          test file {{ item }}
        dest: ~/file_{{ item }}
      with_sequence: start=1 end={{ n }}

И запустим с Mitogen и без нее для создания 10 файлов:


time mitogen-ansible-playbook file_creation.yml -i hosts -e n=10 &>/dev/null

real    0m2.603s
user    0m1.152s
sys     0m0.096s

time pure-ansible-playbook file_creation.yml -i hosts -e n=10 &>/dev/null

real    0m5.908s
user    0m1.745s
sys     0m0.643s

Мы видим улучшение в 2 раза. Давайте проверим для 20, 30, ..., 100 файлов:


time pure-ansible-playbook file_creation.yml -i hosts -e n=100 &>/dev/null

real    0m51.775s
user    0m8.039s
sys     0m6.305s

time mitogen-ansible-playbook file_creation.yml -i hosts -e n=100 &>/dev/null

real    0m4.331s
user    0m1.903s
sys     0m0.197s

В итоге мы ускорили исполнение более чем в 10 раз!
Теперь попробуем различные сценарии и посмотрим насколько у нас быстрее все работает:


  • Сценарий копирования файлов на удаленный хост с локального (с модулем copy):
    Uploading files


  • Сценарий создания файлов на удаленном хосте с copy модулем:
    Creating files


  • Сценарий с загрузкой файлов с удаленного хоста на локальный:
    Fetching files


  • Сценарий с созданием темплейтов на уделенном хосте с некоторыми переменными и вычислениями в Jinja
    Template files



Попробуем сценарий с несколькими (3) удаленными машинами, например сценарий с копированием файлов на удаленный хост:
Uploading files to multiple hosts


Как видно Mitogen экономит нам как время так и трафик в этих сценариях. Но если "бутылочное горлышко" не в Ansible, а например в I/O диска или сети, или где либо еще, тогда трудно ожидать что Mitogen нам поможет.


Давайте попробуем сценарий с установкой пакетов с yum/dnf и модулей python с помощью pip. Пакеты были закешированы чтобы не зависеть от глюков в сети:


---
- hosts: all
  gather_facts: false
  tasks:
    - name: Install packages
      become: true
      package:
        name:
          - samba
          - httpd
          - nano
          - ruby
        state: present

    - name: Install pip modules
      become: true
      pip:
        name:
          - pytest-split-tests
          - bottle
          - pep8
          - flask
        state: present

С Mitogen это взяло 12 секунд, как и без него.
На странице Mitogen for Ansible page вы можете посмотреть другие бенчмарки и тесты. Как утверждается на странице:


Mitogen не может ускорить модуль когда он исполняется. Он может только сделать исполнение этого модуля настолько быстрым насколько это возможно.

Поэтому важно найти ваши узкие места в развертывании и если они из-за Ansible, то Mitogen поможет вам решить их и значительно ускорить исполнение ваших playbooks.


edit: Добавлен сценарий с темплейтами

Поделиться публикацией

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

    0

    Браво! Реально ожидал, что кто-то напишет про mitogen. Но есть нюансы:


    • Обратите внимание что Mitogen 0.2.7 не работает с Ansible 2.8 (на май 2019)
      И это прекрасно. Такое тащить в продакшен как-то стремновато
    • Не нужно забывать, что ansible — это про ssh. А если закрытый контур? А если там чехарда с ключами? Все-таки это с одной стороны реально сила Ansible, а с другой стороны — и его серьезное ограничение
    • Я все никак не дойду до сделать сравнение ansible vs salt-ssh. Во всех моих кейсах Salt обгоняет ansible по производительности. Да и Salt гибче — больше кейсов использования и т.п. Проблема только одна — кривая входа в Salt. Она реально круче, чем у Ansible. Но это и приводит к тому, что экосистема Ansible на 90% состоит из шлака — можно в тот же galaxy посмотреть.
      +2
      Такое тащить в продакшен как-то стремновато

      Я бы не тащил Ansible 2.8 сейчас в продакшн :)

      Было бы интересно посмотреть на сравнение с salt, особенно ansible+mitogen с salt. Сам с salt не работал, почему там больше кейсов использования?
        0

        Я имею в виду, что основной способ применения Сольта — это мастер-клиент. Примерно как puppet — для управления конфигурацией целевой машины. Здесь сделаю ремарку, что Ansible — это не SCM. От слова совсем. Скорее нечто типа "баша на стероидах".
        Соответственно, в salt'е есть еще режим salt-ssh — это примерно как ansible работает. Есть еще оркестрация (если нужно не просто разливать некое состояние, а делать цепочки из стейтов).


        В общем, для расширения кругозора рекомендую посмотреть. Если понравится — здорово. Если нет, ну, что ж, бывает. Чудес не обещаю, т.к. болячки систем — это продолжение их преимуществ. Ну, и наоборот.

          0
          Ну, если у Ansible нет мастера, это не значит что он не SCM. Может не такой декларативный как terraform, но все равно. А если добавить Tower/AWX, то вообще будет полный комплект :)
            +1

            Он не SCM, потому что он не про state. Ансибл — это процедурная история, просто завернутая в YAML.
            А terraform — действительно хороший пример декларативности.


            А если добавить Tower/AWX, то вообще будет полный комплект :)

            Ага. Только Tower/AWX — это не мастер, а, если упрощать, запускалка плейбуков, чтоб это делать не с компа админа.

              0
              SCM — это system configuration management, Ansible — да, императивный SCM.
              А связка terraform+ansible по-моему самое лучшее что есть сейчас.
                0
                Ansible — да, императивный SCM

                нет. Не SCM от слова совсем, но это не мешает в том числе ансиблем раскладывать файлы конфигов.


                А связка terraform+ansible по-моему самое лучшее что есть сейчас.

                да, достаточно оптимальный вариант. Но можно и без ansible — terraform умеет и другие провижионеры. И все равно нужно как-то предпоготавливать образы операционной системы. С этим справляется packer (с возможностью подключения расширений).

          0
          А что не так в версии Ansible 2.8 в продакшене?
            0
            Только потому что новый, мы обычно ждем пару релизов.
          0
          Я много работал с salt и salt-ssh и у меня к нему много претензий: habr.com/ru/post/315012/#comment_9905944
          С ansible пока поработать не получилось, сравнивать не могу.
            0
            salt тормозит сильнее (как только хостов станет достаточно количество), это проблема его архитектуры.
            salt-ssh — вообще очень тупая штука, сделанная только ради того, что бы было.
              0
              Не нужно забывать, что ansible — это про ssh. А если закрытый контур? А если там чехарда с ключами? Все-таки это с одной стороны реально сила Ansible, а с другой стороны — и его серьезное ограничение

              Ну, например, CyberArk AIM отлично решает эту задачу.

              0
              Copy меняем на synchronize, включаем ssh-мульиплексинг на сутки — деплои летают. Вот только как ускорить джинджу?
                0
                Вот только как ускорить джинджу?

                А зачем? Что это даст? К самой джиндже (я ее и отдельно использую) у меня никогда вопросов по скорости не было

                  0

                  Включаем статы по таскам и находим:


                  [14:51:58]
                  Sunday 19 May 2019  11:51:58 +0000 (0:00:00.340)       0:06:00.528 ************ 
                  [14:51:58]
                  =============================================================================== 
                  [14:51:58]
                  yum ------------------------------------------------------------------- 116.96s
                  [14:51:58]
                  uri -------------------------------------------------------------------- 68.91s
                  [14:51:58]
                  template --------------------------------------------------------------- 58.35s
                  [14:51:58]
                  shell ------------------------------------------------------------------ 46.33s
                  [14:51:58]
                  synchronize ------------------------------------------------------------ 14.37s
                  [14:51:58]
                  zabbix_host ------------------------------------------------------------ 13.85s
                  [14:51:58]
                  setup ------------------------------------------------------------------ 12.50s

                  Что это даст?

                  Общее ускорение деплоя, естественно.

                    0

                    ээээ… А Вы дайте более нормальную разбивку. Ну, template долго работает, но он же наверняка файлы по сети качает? И, кстати, разница по времени между shell и template практически в рамках погрешности. И что Вы хотели сказать? :-/

                      0

                      Что yum можно ускорить, поставив в локалке своё зеркало (или отказавший от принудительного обновления кешей) А вот с template подобного хака не существует. Точнее, наверно можно приделать кеширование для шаблонов, но потом придется решать другие проблемы.

                        0

                        Повторюсь, что этот лог вообще не дает понимания ЧТО ПРОИСХОДИТ. Ну, 50 секунд, ну, ок. Либо нужно делать разбивку дальше — на вызовы python и то, как он ходит в систему. Либо забить, т.к. на текущем уровне не продвинуться. И, повторюсь, что САМА jinja не является медленной.
                        По yum понятно почему он медленный — он, во-первых, спавнит почти наверняка настоящий yum, а не работает с библиотеками напрямую. А, во-вторых, yum сам по себе не обладает прытью :-)

                          0
                          Один из решений для yum может быть установка всех пакетов за раз, будет быстрее чем вызывать его несколько раз для разных пакетов.
                        0
                        Ну, общее время template модуля включает в себя все — работу Ansible, сеть, и т.д. Как раз таки часть джинджа здесь скорее всего минимальна. Вот именно для вас Mitogen и должен помочь.
                      0
                      Действительно, а в чем проблем с джинджа? Вы вычислили что это ваше узкое место?
                        0

                        Речь не про узкое место, а общее ускорение тасок. Естественно надо прибавлять везде, есть модули где понятно как. Есть модули (типа того же темплейта) где непонятно или вообще без вариантов.

                          0
                          добавил отдельный график по темплейтам в статью
                      0

                      Коллеги утверждают, что модуль raw не работает с mitogen, что ставит крест на бутстрапе им нод с убунтой.
                      https://github.com/dw/mitogen/issues/266
                      Вот такой вот митогенчик.

                        0
                        mitogen.networkgenomics.com/ansible_detailed.html#noteworthy-differences
                        The raw action executes as a regular Mitogen connection, which requires Python on the target, precluding its use for installing Python. This will be addressed in a future release. For now, simply mix Mitogen and vanilla Ansible strategies:

                        - hosts: web-servers
                        strategy: linear
                        tasks:
                        - name: Install Python if necessary.
                        raw: test -e /usr/bin/python || apt install -y python-minimal

                        - hosts: web-servers
                        strategy: mitogen_linear
                        roles:
                        - nginx
                        - initech_app
                        - y2k_fix
                          0

                          Видел, но это костыли. Желаю им в скорейшем времени пофиксить этот ишью.

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

                      Самое читаемое