Pull to refresh
1260.94
Timeweb Cloud
То самое облако

Just add some Salt. Опыт Timeweb

Reading time6 min
Views3.8K

Как мы мигрировали 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 в качестве бэкенда, дайте пять! Скорее всего, вы переживаете те же проблемы, что и мы. Так что будем рады обсудить эту тему в комментариях.

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


Tags:
Hubs:
Total votes 7: ↑5 and ↓2+5
Comments13

Articles

Information

Website
timeweb.cloud
Registered
Founded
Employees
201–500 employees
Location
Россия
Representative
Timeweb Cloud