Как сделать облачный (кластерный) хостинг за пару копеек*
Три года назад у меня была интересная задача. Необходимо было собрать платформу, объединявшую несколько стоек с серверами в единое целое, для динамического распределения ресурсов между сайтами написанным для LAMP платформы. Причем так, чтоб вмешательство в код сайтов было минимальным, а еще лучше — вообще отсутствовало.
При этом никаких дорогих решений вроде Cisco Content Switch или дисковой полки с оптоволокном использовать нельзя — не хватало бюджета.
А кроме того, разумеется, в случае выхода одного из серверов из строя — это не должно было влиять на работу платформы.
Голь на выдумки хитра
Прежде всего нужно разделить создание платформы на подзадачи. Сразу понятно, что придется что-то делать для синхронизации данных, так как общий диск недоступен. Кроме того, необходимо балансировать трафик и иметь по нему кое-какую статистику. Ну и наконец, автоматизация предоставления нужных ресурсов — это тоже достаточно серьезная задача.
Начнем с начала, да прибудет со мной КО
У меня был выбор, на чем организовать платформу. Это OpenVZ и XEN. У каждого есть свои плюсы и минусы. OpenVZ имеет меньший оверхед, работает с файлами а не блочными устройствами, но не умеет запускать что-то кроме Linux'овых дистрибутивов. XEN позволяет запустить и Windows, но более сложен в работе. Я использовал OpenVZ, так как это более подходило для решения задачи, но вас-то никто не ограничивает в выборе.
Затем я разделил сервера на места под VDS, по одной на каждое ядро. Сервера были разные, по этому у меня был набор от 2-х до 16-и виртуалок на каждом из серверов. В «среднем по палате» вышло ~150 виртуалок на стойку.
Как синхронизацировать данные
Следующий пункт — это оперативное создание VDS по требованию + защита от поломки любого сервера. Решение было простым и красивым.
Для каждой VDS создается начальный образ в виде файлов на LVM разделе. Этот образ «разливается» по всем серверам платформы. В результате мы имеем бекап всех проектов на каждом сервере (параноики плачут от умиления), а создание новой VDS «по запросу» упростилось до снапшота с образа и его старта в виде VDS (дело буквально нескольких секунд).
База и API
Если с целостностью файлов было все просто, то вот с синхронизацией базы дело обстояло хуже. С начала я попробовал классический пример — master-slave, и столкнулся с классической проблемой: slave отставал от master (да, и спасибо за репликацию в один поток, очень большое спасибо).
Следующим шагом был Mysql-Proxy. Как сисадмину, мне подобное решение было очень удобным — поставил и забыл, только конфиг обновлять надо при добавлении/удалении новых VDS. Но у разработчиков было свое мнение. В частности, то, что проще написать некий класс PHP для синхронизации INSERT/UPDATE/DELETE запросов, чем изучать Lua, без которого Mysql-Proxy бесполезен.
Результатом их работы стал так называемый API, который умел находить соседей широковещательным запросом, синхронизироваться до актуального состояния и информировать соседей о всех изменениях с базой.
Но все же стоит изучить Lua и сделать нативный режим работы, когда все запросы будут синхронизированы с соседями.
Слава FreeBSD
Балансер — это можно сказать ключевой аспект платформы. Если упадет балансирующий сервер, то вся работа не будет иметь никакого смысла.
Именно по этому я использовал CARP для создания отказоустойчивого балансера, выбрав FreeBSD в качестве ОС и Nginx в качестве балансера.
Да-да, дорогущий NLB был заменен двумя слабыми машинками с FreeBSD (маркетологи в ярости).
И самое главное — как это работало
При старте платформы для каждого сайта запускалось по одной копии и monit на баланесере следил, за тем, чтобы первичная копия всегда работала.
Кроме того на балансере был установлен анализатор статистики Awstats, который предоставлял все логи в удобном формате, а главное — там был скрипт, опрашивающий каждую VDS по SNMP на предмет ее нагрузки.
Как мы помним, я выделял на каждую VDS по одному ядру, следовательно Load Average в 1 — это будет нормальной нагрузкой для VDS. Если LA становился 2 или выше — запускался скрипт, создающий копию VDS на случайном сервере и прописывал ее в апстрим nginx'а. А когда нагрузка на дополнительной VDS падала меньше 1 — соответственно, все удалялось.
Резюмирую
Если взять стойку с серверами и свитчем поддерживающим CARP протокол, то для создания облачного хостинга будет необходимо:
- Изучить Lua и настроить прозрачную синхронизацию через Mysql-Proxy
- Прикрутить биллинг для учета дополнительных копий VDS и трафика
- Написать веб-интерфейс для управления VDS
*На заполнение стойки хватит суммы с четырьмя нулями. По сравнению с решениями от брендов, где цена одной стойки — сумма с шестью нулями, это действительно пару копеек.