UPDATE(2016-01-28): теперь для этого есть Docker.
Что делать, когда нужна куча маленьких и дешевых серверов для тестирования разных версий разных сайтов? Можно прикупить дедик и поставить на него OpenVZ. Хотя, OpenVZ будет как-то мелковато — памяти-то много. Лучше поставим XEN. Или KVM. Или даже VMWare.
И начнем всё это админить? — Конечно же, нет.
Начну издалека, первый пост же. Больше шести лет назад я таки поменял один здоровенный и дорогущий железный сервер на несколько маленьких виртуальных. В то время мастерхост был еще торт, и виртуалки были у него только под Virtuozzo (впрочем, как и сейчас). Так и познакомились. Шло время, технология контейнеров очаровывала меня своей простотой: файловая система в простой папке, полные бекапы одним кликом, стабильные ядра от хостера и, главное, никаких заморочек с железом. Сбывшаяся мечта человека, никогда не собиравшего сервер.
Но когда появляется необходимость выйти за ограничения твух-трёх удобных хостеру тарифов, начинаются огорчения. В моём случае понадобилась масса создаваемых на лету маленьких серверов, которые запускают разные версии сайта для каждой ветки в репозитории. Памяти требуется чуть, диска тоже немного, процессор и сеть используются изредка. А главное, сервер надо уметь создавать из скрипта. И, лучше всего, быстро.
И с этим возникают сложности. Во-первых, серьёзные парни со своими API (Linode, Amazon) используют XEN от 20 баксов за сервер с кучей всего лишнего. Это не вариант. Во-вторых, дешевые хостинги постоянно лагают и отваливаются, даже если и научиться автоматом создавать у них серверы. Тоже не вариант. И всё это логично, ведь дорогие хостеры оттого и дорогие, что всё умеют и работают стабильно.
А что, если завести дешевые контейнеры на дорогом хостинге? Начиная с ubuntu 12.04 это сделать проще пареной репы: с помощью Linux Containers, которые уже несколько лет живут в ванильном ядре. В случае сервера от Linode, это пара
Начнем:
Поставим скрипты LXC:
И проверим поддержку Linux Containers в ядре:
Сегодняшнее дофолтное ядро у линоды поддерживает контейнеры очень частично. Поставим ванильное ядро от убунты:
Дальше двигаемся согласно кусочку инструкции по PV-GRUB:
Когда установщик граба задавал вопрос «куда ставить», я выбирал xvda.
Далее пачим `/boot/grub/menu.lst` (ближе к концу файла):
и обновляем конфиг граба:
Всё, контейнер готов к загрузке ванильного ядра. Осталось только попросить наш linode загружаться в соответствии с конфигом граба. Для этого надо зайти в редактор профиля виртуального сервера, посмотреть там битность ядра (у меня
Теперь можно проверить поддержку LXC в ядре:
и насладиться всеми зелененькими пунктами.
В системе появится новый сетевой интерфейс:
который будет объединять все контейнеры и выпускать их в интернет.
Наконец-то, создаем первый контейнер:
В первый раз этот процесс затянется минут на пять, так как
Запустить контейнер и попасть в его консоль можно вот так (логин и пароль
Выходить, предлагают, нажав
Осталось только настроить запуск контейнера при старте:
Теперь надо как-то попасть на сайт внутри контейнера. Так как у него нет публичного IP, придется мудрить.
Можно поковырять
Итак, конфиг для nginx:
Тут всё просто: nginx получает запрос на 80 порт виртуальной машины и передает его на 80 порт контейнера с адресом 10.3.0.2. Ответ не буферизируем, а то nginx любит складывать картинки сначала на диск, а потом уже в сеть. Секцию
С одной стороны, о чем тут говорить? Это ж сервер для демок и девелоперских изысканий. С другой стороны, контейнеры тем и хороши, что не добавляют сложных абстракций. Процессор все получают в его первозданном виде, память тоже. Наверное, немного тратится на логику изоляции файловой системы, да и то, только при открытии файла. Вот сеть да, виртуальная, но всего лишь на уровне IP, никто же не эмулирует сетевую карту. В комментах inkvizitor68sl называет 1-2% потерь. Я верю, что для рядового сайта будет и того меньше. Конечно, если включить квотирование, то многое изменится. Но учет и ограничение потребления ресурсов всегда чего-то стоит. Потому мои контейнеры не ограничены ни в чем, они просто изолированы, чтобы удобнее было разворачивать кучу маленьких сайтов из скрипта. Вот и всё.
Круто же!
Ах, да. Солярис и фря, сто лет уже как, умеют это из коробки. И то же самое можно сделать на OpenVZ (даже внутри LXC).
Что делать, когда нужна куча маленьких и дешевых серверов для тестирования разных версий разных сайтов? Можно прикупить дедик и поставить на него OpenVZ. Хотя, OpenVZ будет как-то мелковато — памяти-то много. Лучше поставим XEN. Или KVM. Или даже VMWare.
И начнем всё это админить? — Конечно же, нет.
Виртуализация, любовь моя
Начну издалека, первый пост же. Больше шести лет назад я таки поменял один здоровенный и дорогущий железный сервер на несколько маленьких виртуальных. В то время мастерхост был еще торт, и виртуалки были у него только под Virtuozzo (впрочем, как и сейчас). Так и познакомились. Шло время, технология контейнеров очаровывала меня своей простотой: файловая система в простой папке, полные бекапы одним кликом, стабильные ядра от хостера и, главное, никаких заморочек с железом. Сбывшаяся мечта человека, никогда не собиравшего сервер.
Но когда появляется необходимость выйти за ограничения твух-трёх удобных хостеру тарифов, начинаются огорчения. В моём случае понадобилась масса создаваемых на лету маленьких серверов, которые запускают разные версии сайта для каждой ветки в репозитории. Памяти требуется чуть, диска тоже немного, процессор и сеть используются изредка. А главное, сервер надо уметь создавать из скрипта. И, лучше всего, быстро.
И с этим возникают сложности. Во-первых, серьёзные парни со своими API (Linode, Amazon) используют XEN от 20 баксов за сервер с кучей всего лишнего. Это не вариант. Во-вторых, дешевые хостинги постоянно лагают и отваливаются, даже если и научиться автоматом создавать у них серверы. Тоже не вариант. И всё это логично, ведь дорогие хостеры оттого и дорогие, что всё умеют и работают стабильно.
А что, если завести дешевые контейнеры на дорогом хостинге? Начиная с ubuntu 12.04 это сделать проще пареной репы: с помощью Linux Containers, которые уже несколько лет живут в ванильном ядре. В случае сервера от Linode, это пара
apt-get
ов, маленький патч, перезагрузка и 300 Мб места.Ванильное ядро
Начнем:
sudo apt-get update && sudo apt-get upgrade
Поставим скрипты LXC:
sudo apt-get install lxc
И проверим поддержку Linux Containers в ядре:
sudo lxc-checkconfig
Сегодняшнее дофолтное ядро у линоды поддерживает контейнеры очень частично. Поставим ванильное ядро от убунты:
sudo apt-get install linux-virtual
virtual
потому, что нужна поддержка XEN.Дальше двигаемся согласно кусочку инструкции по PV-GRUB:
sudo apt-get install grub-legacy-ec2
Когда установщик граба задавал вопрос «куда ставить», я выбирал xvda.
Далее пачим `/boot/grub/menu.lst` (ближе к концу файла):
- # defoptions=console=hvc0
+ # defoptions=console=hvc0 rootflags=nobarrier
и обновляем конфиг граба:
sudo update-grub-legacy-ec2
Всё, контейнер готов к загрузке ванильного ядра. Осталось только попросить наш linode загружаться в соответствии с конфигом граба. Для этого надо зайти в редактор профиля виртуального сервера, посмотреть там битность ядра (у меня
Latest 32 bit
) и выбрать там соответствующий pv-grub-*
(у меня pv-grub-x86_32
). Далее сохраняем профиль и перезагружаем сервер.Контейнер
Теперь можно проверить поддержку LXC в ядре:
sudo lxc-checkconfig
и насладиться всеми зелененькими пунктами.
В системе появится новый сетевой интерфейс:
ifconfig | grep lxc
который будет объединять все контейнеры и выпускать их в интернет.
Наконец-то, создаем первый контейнер:
sudo lxc-create -t ubuntu -n demo1
В первый раз этот процесс затянется минут на пять, так как
lxc-create
соберёт новенькую убунту в папке /var/cache/lxc/
, а потом скопирует ее в папку /var/lib/lxc/demo1/rootfs/
, где и будет жить наш новый контейнер.Запустить контейнер и попасть в его консоль можно вот так (логин и пароль
ubuntu
):sudo lxc-start -n demo1
Выходить, предлагают, нажав
Ctrl+A Q
. Из lxc-start
так выйти не удаётся, но можно просто закрыть окно терминала. В дальнейшем открыть консоль контейнера можно вот так (логин и пароль те же):sudo lxc-console -n demo1
Осталось только настроить запуск контейнера при старте:
sudo ln -s /var/lib/lxc/demo1/config /etc/lxc/auto/demo1.conf
Окно в контейнер
Теперь надо как-то попасть на сайт внутри контейнера. Так как у него нет публичного IP, придется мудрить.
Можно поковырять
iptables
, так как контейнеры, всё же, на одной машине. Или отключить виртуализацию сети совсем, тогда у всех контейнеров будет общий сетевой интерфейс с виртуальной машиной. Но сегодня, я не готов курить такие крепкие маны. Лучше, поступим так же, как с любым другим приватным кластером: будем проксировать HTTP-запросы на внутренние ноды. Сегодня у меня есть опыт проксирования только с помощью nginx, его и опишу. Но если ваш сайт использует веб-сокеты, то проксировать надо с помощью HAproxy, так как nginx собирается обрести их поддержку только в начале 2013 года.Итак, конфиг для nginx:
user nobody nogroup;
worker_processes 2;
events { worker_connections 1024; }
http {
keepalive_timeout 90;
access_log off;
server {
server_name demo.example.com;
location / {
proxy_pass 10.3.0.2;
proxy_redirect http://localhost/ http://$host:$server_port/;
proxy_buffering off;
}
}
}
Тут всё просто: nginx получает запрос на 80 порт виртуальной машины и передает его на 80 порт контейнера с адресом 10.3.0.2. Ответ не буферизируем, а то nginx любит складывать картинки сначала на диск, а потом уже в сеть. Секцию
server
надо будет повторить для каждой пары сайт/контейнер, поменяв server_name
и proxy_pass
в соответствии с вашей ситуацией. Уверен, написать для этого скрипт сможет каждый.Производительность
С одной стороны, о чем тут говорить? Это ж сервер для демок и девелоперских изысканий. С другой стороны, контейнеры тем и хороши, что не добавляют сложных абстракций. Процессор все получают в его первозданном виде, память тоже. Наверное, немного тратится на логику изоляции файловой системы, да и то, только при открытии файла. Вот сеть да, виртуальная, но всего лишь на уровне IP, никто же не эмулирует сетевую карту. В комментах inkvizitor68sl называет 1-2% потерь. Я верю, что для рядового сайта будет и того меньше. Конечно, если включить квотирование, то многое изменится. Но учет и ограничение потребления ресурсов всегда чего-то стоит. Потому мои контейнеры не ограничены ни в чем, они просто изолированы, чтобы удобнее было разворачивать кучу маленьких сайтов из скрипта. Вот и всё.
Глубокие выводы
Круто же!
Ах, да. Солярис и фря, сто лет уже как, умеют это из коробки. И то же самое можно сделать на OpenVZ (даже внутри LXC).