Just add some Salt

Как мы мигрировали 700+ серверов на Salt


Долгое время нас устраивала сложная и неповоротливая конфигурация с 2 Git-репозиториями, где часть данных хранится в MySQL, а другая часть Puppet 3.8. Но наши потребности постепенно росли, количество сервисов увеличивалось, а производительность конфигурации снижалась. Тогда мы поставили перед собой задачу усовершенствовать конфигурацию, оптимизировав все имеющиеся данные и инструменты.

Наша команда подобрала для себя подходящую конфигурацию в 3 этапа. Делимся опытом оптимизации Salt, как применить и настроить без лишних усилий.

Примечание: На Хабре мы нашли классные статьи наших коллег, поэтому не будем останавливаться подробно на уже освещенных вопросах. Очень советуем прочитать:

Чем хорош SaltStack, и какие задачи с его помощью можно решить — статья от ptsecurity, Positive Technologies.

Установка, запуск, первые команды и знакомство с функциями — статья автора zerghack007.

Salt — система управления конфигурациями и удаленного выполнения операций. Инфраструктурный фреймворк с открытым исходным кодом, написан на Python.


Почему Salt?


Salt, Ansible, Puppet и Chef — достойные варианты для выбора инструмента управления конфигурациями. Мы выбрали Salt, так как выделили для себя в качестве приоритета такие преимущества:

  • Модульность, наличие API в бесплатной версии в отличие от Ansible.
  • Python, а значит, можно легко разобраться в любом компоненте и написать самостоятельно функционал, которого не хватает.
  • Высокая производительность и масштабируемость. Мастер устанавливает постоянное соединение с миньонами, используя ZeroMQ, что дает максимальную производительность.
  • Реакторы (reactors) — это своеобразные триггеры, которые выполняются при появлении определенного сообщения в шине сообщений.
  • Оркестрация — возможность выстраивать сложные связи и выполнять действия в определенной последовательности, например, настроить сначала балансировщик нагрузки, а затем кластер веб-серверов.
  • Puppet и Chef написаны на Ruby. В нашей команде нет компетентного специалиста для работы с этим языком программирования, зато Python хорошо знаком и чаще нами используется.
  • Для тех команд, которые использовали ранее Ansible, будет актуальной возможность использовать плейбуки от Ansible. Это позволит безболезненно мигрировать на Salt.

Обратите внимание:

Мы используем Salt почти два года и советуем обратить внимание на следующие моменты:

  • Не всегда актуальная документация Salt, она может отставать от реальности, и мало примеров. Иногда приходится самостоятельно проверять наличие новых функций, так как в документации их описание отсутствует. Но мы знаем, что команда SaltStack активно работает над этой проблемой.
  • SaltStack предлагает очень много модулей. Это круто, но не всегда стоит использовать их все. Множество модулей может привести к избыточности: чем больше модулей, тем больше усложнений и зависимостей. Например, иногда проще использовать cmd.run или file.managed, чем специальный модуль.

Наш дашборд в Grafana с данными за последние полгода.
Жаль, что не сохранились данные первых этапов настройки, так как мы были слишком увлечены настройкой и не знали, что будем об этом рассказывать.

Дано. Найти. Решение


Дано:

Итак, наша исходная конфигурация:

  • 2 Git-репозитория (один — для инженеров и админов; второй — для особо критичных серверов, доступен только админам);
  • часть данных в MySQL;
  • другая часть — в Puppet 3.8 (перестарались с наследованием, практически не использовав Hiera — key-value хранилище).

Задача: мигрировать систему управления конфигурацией на Salt, увеличить ее производительность, сделать более удобным и понятным управление серверами.

Решение:

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

Затем подготовили конфигурацию для VDS-серверов. В нашем случае это профили под служебные сервера, сервера разработки и сервера клиентов.

Основной проблемой при переходе с Puppet на Salt была устаревшая операционная система (в 2018 году стояла ОС Ubuntu 12.04 и 14.04). Перед миграцией необходимо было обновить ОС и не затронуть работу сервиса / сервера. В остальном все было достаточно легко: коллеги постепенно втягивались в процесс.

Среди главных достоинств команда отметила, например, более понятный синтаксис. Мы с коллегами договорились использовать советы Salt Best Practices, но дополняли их собственными рекомендациями, которые отражают наши особенности.

Команда оценила также способы доставки конфигурации: push (мастер «проталкивает») и pull (миньон «стягивает»). Режим Masterless выручает, если нужно протестировать что-то несложное и при этом не связываться с Git-репозиторием. Запуск миньона в режиме masterless позволяет использовать управление конфигурацией Salt для одной машины, не обращаясь к мастеру Salt на другой машине. Конфигурация полностью локальна.

До 300 миньонов с подобным решением у нас не было серьезных проблем. Конфигурация мастера на тот момент — это VDS с 6 ядрами и 4 Гб памяти.

Однако, как только количество миньонов достигло 300, показатель Load Average (cредняя загрузка системы) вырос до значений 3.5-4, и работа системы сильно замедлилась. Раньше команда state.apply выполнялась 30-40 секунд, а сейчас все 18 минут!

Такой результат, конечно, был неприемлем для нас. Тем более эксперты из других компаний писали об успешных историях с 10,000 миньонами. Мы стали разбираться, в чем дело.

Наблюдения за мастером не давали однозначного ответа на вопрос. Памяти хватало, сеть не была нагружена, диск утилизировался на 10%. Думали, что виноват GitLab, но и он оказался ни при чем.

Похоже, что не хватало процессорной мощности: при добавлении ядер показатель Load Average естественно падал, и команда state.apply выполнялась хоть и быстрее, около 5-7 минут, но не так быстро, как нам хотелось.

Добавление воркеров отчасти решало проблему, но при этом значительно увеличивалось потребление памяти.

Тогда мы решили оптимизировать саму конфигурацию.

Этап №1


Так как пиллары — это защищенное хранилище, обращение к хранилищу связано с операциями шифрования, за доступ к нему нужно платить процессорным временем. Поэтому мы уменьшили количество обращений к пилларам: одни и те же данные брались только 1 раз; если они были нужны еще где-то, то доступ к ним осуществлялся через import ({%- from 'defaults/pillar.sls' import profile %}).

Применение конфигурации происходит 1 раз в час, время выполнения выбирается рандомно. Проанализировав, сколько задач выполняется в минуту и насколько равномерно они распределены в течение часа, мы выяснили: в начале часа с 1-й по 8-ю минуты проходит больше всего заданий, а в 34-ю минуту ни одного! Мы написали раннер, который 1 раз в неделю проходил по всем миньонам и равномерно распределял задания. Благодаря такому подходу нагрузка стала равномерной, без скачков.

Звучали предложения переехать на железный сервер, но на тот момент его не было и… мы решили проблему по-другому. Добавили немного памяти и разместили в ней весь кеш. Глядя в дашборд Grafana, мы сначала подумали что salt-master не работает, так как показатель Load Average упал до значения 0.5. Проверили время выполнения state.apply и тоже удивились — 20-30 секунд. Это была победа!

Этап №2


Через полгода количество миньонов возросло до 650, и… снова наступила деградация производительности. График Load Average растет вместе с количеством миньонов.

Первое, что мы сделали: включили кеш для пилларов, время жизни установили в 1 час (pillar_cache_ttl: 3600). Мы понимали, что в теперь наши коммиты не будут мгновенными и придется подождать, пока мастер обновит кеш.

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

Этап №3


Немного помедитировали над debug-логами и выдвинули гипотезу: а что если увеличить интервал обновления файлового бекенда и кеша списка файлов (gitfs_update_interval, fileserver_list_cache_time)? Обновление которых происходило 1 раз в минуту и порой занимало до 15 секунд. Увеличив интервал обновления с 1 минуты до 10 минут, мы снова выиграли в скорости! Показатель LA снизился с 1.5 до 0.5. Время применения конфигурации уменьшилось до желаемых 20 секунд. Не смотря на то, что через какое-то время LA снова подрос, скорость выполнения state.apply изменилась не существенно. Принудительное обновление этих кешей добавили в хуки при git push’е.


Добавили аналитику в Elasticsearch: переписали встроенный elasticsearch_return и теперь мы можем следить за результатами state.apply (среднее время выполнения, самый долгий стейт и количество ошибок).

Результаты


Сейчас производительность Salt'a нас полностью устраивает. В планах увеличить количество миньонов в 2 раза. Как справится с такой нагрузкой наш мастер, пока сказать сложно. Возможно, мы обратимся к горизонтальному масштабированию или найдем волшебный параметр. Время покажет!

Если вы используете gitfs в качестве бэкенда, дайте пять! Скорее всего, вы переживаете те же проблемы, что и мы. Так что будем рады обсудить эту тему в комментариях.

Полезные ресурсы


Timeweb
VDS, виртуальный хостинг, домены, серверы

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

    +1

    gitfs у нас очень тормозил. Заменили на git pull на мастере и потом работали просто с файлами на диске. В остальном — та же история, что и у вас.

      +1
      Здравствуйте!
      Да, мы тоже думали о таком варианте, но проблему удалось решить.
      +1

      То есть пока у вас еще один мастер? Про мультимастер не думали?

        0
        Здравствуйте!

        На самом деле, у нас два мастера: один — в проде, второй — для тестовых веток. У них общие ключи миньонов, поэтому для перехода на мультимастер нужен будет только общий ключ мастера, но один пока хорошо справляется.
        +1
        > Для тех команд, которые использовали ранее Ansible, будет актуальной возможность использовать плейбуки от Ansible. Это позволит безболезненно мигрировать на Salt.

        Можете поделится результатами этого подхода?
          0
          Здравствуйте!

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

          Так как Ansible у нас не был внедрен повсеместно (всего было около 50 плейбуков), скорее, это была проба инструмента, постепенно мы переделали плейбуки на стейты.
          0

          web gui какие-нибудь используете?
          https://github.com/latenighttales/alcali?
          Salt master в HA режиме? Или одна нода ?

            +1
            web gui какие-нибудь используете?
            github.com/latenighttales/alcali?

            Пока не используем. Указанный Вами alcali смотрели, и он нам очень понравился! В нём только необходимо сделать авторизацию в freeipa.

            Salt master в HA режиме? Или одна нода?

            HA-режима нет, одна нода. Сейчас Salt используется для применения конфигурации. Деплой, оркестрацию еще не используем, поэтому можем себе позволить некоторый простой в работе мастера.

            К тому же, сам мастер управляет собой, и вся его актуальная конфигурация есть в Git'е, поэтому создание нового мастера не проблема.
              0
              К тому же, сам мастер управляет собой, и вся его актуальная конфигурация есть в Git'е, поэтому создание нового мастера не проблема.

              тогда есть беспректис — не использовать gitfs (лишний гемор с кэшированием), а использовать отдельный стейт для синхронизации мастера и гита (мастер сам себя конфигурирует)


              В остальном — ок, понял

                0
                Согласны! Это сильно бы упростило использование Salt'a в случае с одним репозиторием, но у нас их два. Они имеют одинаковую структуру и должны правильно мержиться (пиллары и стейты).
            0
            Заюзали gitpython ( по совету самих солт спецов с enterprise ) вроде помогло, но подтикает в другом месте ( salt api, ws4py + cherrypy ) будем еще tornado пробовать
              0
              Вот как! Оказывается, они сами рекомендует pygit2.

              А есть ли какие-то ограничения или особенности при использовании GitPython?

              Мы пока API мало используем, CherryPy устраивает. Только после перезапуска salt-api бывает, что первый запрос фейлится.
                0

                А мы тоже на сайт ссылались, но смогли достать enterprise спецов с их стороны и они сказали что, мол, юзайте gitpython потому он юзает просто git( + у них тоже проблемы были и просто заюзали gitpython и все мол хорошо ), так как pygit2 пытается переизобрести обычный git через python

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

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