Как стать автором
Обновить

Виртуализация второго порядка

Время на прочтение 4 мин
Количество просмотров 20K
UPDATE(2016-01-28): теперь для этого есть Docker.

Что делать, когда нужна куча маленьких и дешевых серверов для тестирования разных версий разных сайтов? Можно прикупить дедик и поставить на него 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).
Теги:
Хабы:
+34
Комментарии 15
Комментарии Комментарии 15

Публикации

Истории

Работа

DevOps инженер
39 вакансий

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн