17 декабря 2014 в 16:44

OpenStack, Docker и веб-терминал, или как мы делаем интерактивные упражнения для обучения Linux

В статье об онлайн-курсе «Введение в Linux» на образовательной платформе Stepic мы обещали рассказать о технической реализации нового типа интерактивных задач, который был впервые применен в этом курсе. Этот тип задач позволяет создавать на лету виртуальные серверы с Linux для работы через веб-терминал прямо в окне браузера. Автоматическая проверяющая система следит за корректностью выполнения заданий.

Пример задания из курса:



В этой статье я хочу рассказать о проекте, который лег в основу нового типа заданий на Stepic. Я также расскажу о том, из каких компонентов состоит система, и как они взаимодействуют между собой, как и где создаются удаленные сервера, как работает веб-терминал и автоматическая проверяющая система.

Вдохновение


Я один из тех многих, кто при поиске работы не любит составлять резюме и писать десятки мотивационных писем IT-компаниям, чтобы пробиться через фильтр HR-специалистов и наконец получить от них заветное приглашение на собеседование. Куда более естественно, вместо того, чтобы писать о себе похвальные слова, показать свой реальный опыт и навыки на примере решения ежедневных задач.

Еще в 2012 году, будучи студентом Матмеха СПбГУ, я вдохновился проектом InterviewStreet, позже эволюционировавшим в проект HackerRank. Ребята разработали платформу, на которой IT-компании могут проводить онлайн-соревнования по программированию. По результатам таких соревнований компании приглашают лучших участников пройти собеседование. В дополнение к рекрутингу целью проекта HackerRank стало создание сайта, на котором любой желающий может развивать навыки программирования через решение задач из разных областей Computer Science, таких как теория алгоритмов, искусственный интеллект, машинное обучение и другие. Уже тогда существовало большое количество других платформ, на которых проводились соревнования для программистов. Активно набирали популярность интерактивные онлайн-платформы для обучения программированию, такие как Codecademy и Code School. К тому моменту я имел достаточный опыт работы системным администратором Linux и хотел видеть подобные ресурсы для упрощения процесса трудоустройства системных инженеров, проведения соревнований по администрированию Linux, ресурсы для обучения системному администрированию путем решения реальных задач в этой области.

После упорного поиска из похожих проектов нашелся только LinuxZoo, разработанный для академических целей в Эдинбургском университете им. Непера (Edinburgh Napier University). Мне также попался на глаза промо-ролик весьма успешного и амбициозного проекта Coderloop, уже тогда заброшенного после покупки компанией Gild. В этом ролике я увидел именно то, о чем тогда мечтал. К сожалению, разработанная в Coderloop технология для создания интерактивных упражнений по системному администрированию так и не увидела свет. Во время переписки с одним из основателей проекта Coderloop я получил много теплых слов и пожеланий по разработке и дальнейшему развитию этой идеи. Моему вдохновению не было предела. Так я начал разработку платформы Root’n'Roll, которой стал посвящать практически все свое свободное время.

Цели Root’n’Roll


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

Ключевыми требованиями базовой платформы стали следующие:
  • Иметь возможность максимально быстро и дешево запускать одновременно сотни или даже тысячи виртуальных машин с минимальной Linux-системой, которые можно безопасно вместе с root-правами отдать на растерзание пользователям. Дешево — значит минимизировать количество потребляемых системных ресурсов на одну виртуальную машину. Отсутствие какого-либо существенного бюджета подразумевает отказ от использования облачного хостинга вроде Amazon EC2 или Rackspace по принципу «одна виртуальная машина» = «один облачный инстенс».
  • Позволять работать с виртуальной машиной через веб-терминал прямо в окне браузера. Никакие внешние программы для этого не требуются, только веб-браузер.
  • Наконец, иметь интерфейс для тестирования конфигурации любой виртуальной машины. Тестирование конфигурации может включать в себя как проверку состояния файловой системы (лежат ли нужные файлы на своих местах, корректно ли их содержимое), так и проверки сервисов и сетевой активности (запущены ли какие-то сервисы, правильно ли они настроены, корректно ли отвечают на определенные сетевые запросы и т.д.).

Все перечисленные требования в какой-то мере уже удалось реализовать. Обо всем по порядку.

Запуск виртуальных машин


Для запуска виртуальных машин сначала нужно было определиться с технологией виртуализации. Варианты с гипервизорной виртуализацией: аппаратной (KVM, VMware ESXi) и паравиртуализацией (Xen) — отпали довольно быстро. Эти подходы имеют довольно большие накладные расходы на системные ресурсы, в частности память, т.к. для каждой машины запускается свое отдельное ядро, и стартуют различные подсистемы ОС. Виртуализации такого типа также требуют наличия выделенного физического сервера, к тому же, при заявленном желании запускать сотни виртуалок, с весьма неплохим «железом». Для наглядности можно посмотреть на технические характеристики серверной инфраструктуры, используемой в проекте LinuxZoo.

Далее фокус пал на системы виртуализации уровня операционной системы (OpenVZ и Linux Containers (LXC)). Контейнерную виртуализацию можно очень грубо сравнить с запуском процессов в изолированном chroot окружении. Про сравнение и технические характеристики различных систем виртуализации написано уже огромное количество статей, в том числе на хабре, поэтому не останавливаюсь на подробностях их реализации. Контейнеризация не имеет таких накладных расходов, как полноценная виртуализации, потому что все контейнеры разделяют одно ядро хостовой системы.

Как раз к моменту моего выбора виртуализации успел выйти в Open Source и нашуметь о себе проект Docker, предоставляющий инструменты и среду для создания и управления LXC-контейнерами. Запуск LXC-контейнера под управлением Docker (далее docker-контейнер или просто контейнер) сравним с запуском процесса в Linux. Как и обычному linux-процессу, контейнеру не нужно заранее резервировать оперативную память. Память выделяется и очищается по мере использования. Если нужно, можно установить гибкие ограничения на максимальный объем используемой памяти в контейнере. Огромное преимущество контейнеров в том, что для контроля их памятью используется общая хостовая подсистема управления страницами памяти (в том числе механизм copy-on-write и разделяемые страницы). Это позволяет увеличить плотность размещения контейнеров, то есть можно запускать гораздо больше экземпляров linux-машин, чем при использовании гипервизорных систем виртуализации. Благодаря этому достигается эффективная утилизация ресурсов сервера. С запуском нескольких сотен docker-контейнеров с процессом bash внутри запросто справится даже micro-инстенс в облаке Amazon EC2. Еще один приятный бонус — сам процесс запуска контейнера занимает миллисекунды.

Таким образом, на первый взгляд Docker дешево решал задачу запуска большого количества машин (контейнеров), поэтому для первого proof-of-concept решения я решил остановиться именно на нем. Вопрос о безопасности достоин отдельного обсуждения, пока опустим. Кстати, ребята из Coderloop для создания виртуальных окружений в своих упражнениях также использовали LXC-контейнеры.

Управление контейнерами


Docker предоставляет программный REST-интерфейс для создания и запуска контейнеров. Через этот интерфейс можно управлять только контейнерами, находящимися на том же сервере, на котором запущен сервис docker.

Если заглянуть на один шаг вперед, то хорошо было бы иметь возможность горизонтально масштабироваться, то есть запускать все контейнеры не на одном сервере, а распределить их на несколько серверов. Для этого необходимо иметь централизованное управление docker-хостами и планировщик, позволяющий балансировать нагрузку между несколькими серверами. Наличие планировщика может быть очень полезно во время технического обслуживания сервера, например, установки обновлений, требующих перезагрузку. В таком случае сервер помечается как «в обслуживании», в результате чего новые контейнеры на нем не создаются.

Дополнительные требования к централизованной системе управления — настройка сети в контейнерах и управление квотами системных ресурсов (процессор, память, диск). А ведь эти все требования — это не что иное, как задачи, которые успешно решаются облаками (IaaS). Своевременно летом 2013 вышел пост от разработчиков Docker об интеграции Docker с облачной платформой OpenStack. Новый nova-docker драйвер позволяет с помощью openstack-облака управлять парком docker-хостов: запускать контейнеры, поднимать сеть, контролировать и балансировать потребление системных ресурсов — именно то, что нам нужно!

К сожалению, даже на сегодняшний день nova-docker драйвер все еще довольно «сырой». Часто появляются изменения, несовместимые даже с последней стабильной версией openstack’а. Приходится самостоятельно поддерживать отдельную стабильную ветку драйвера. Пришлось также написать несколько патчей, улучшающих производительность. К примеру, для получения статуса одного docker-контейнера драйвер запрашивал статусы всех запущенных контейнеров (посылал N http-запросов к docker-хосту, где N — число всех контейнеров). В случае запуска нескольких сотен контейнеров создавалась ненужная нагрузка на docker-хосты.

Несмотря на определенные неудобства, выбор OpenStack'а в качестве оркестратора контейнеров в моем случае все же того стоит: появилась централизованная система управления виртуальными машинами (контейнерами) и вычислительными ресурсами с единым API. Большой бонус единого интерфейса заключается еще в том, что добавление в Root’n’Roll поддержки полноценных виртуальных машин на базе KVM не потребует никаких существенных изменений в архитектуре и коде самой платформы.

Из недостатков OpenStack можно отметить лишь довольно высокую сложность разворачивания и администрирования приватного облака. Совсем недавно заявил о себе достойный внимания проект Virtkick — этакая упрощенная альтернатива OpenStack. С нетерпением жду его успешного развития.

Выбор веб-терминала


Еще на начальном этапе составления требований к платформе Root’n’Roll основной фичей, которую я хотел видеть в первую очередь, была возможность работы с удаленным linux-сервером через окно веб-терминала прямо у себя в браузере. Именно с выбора терминала и началась разработка, а точнее изучение и выбор технических решений для платформы. Веб-терминал является едва ли не единственной точкой входа пользователя во всю систему. Это именно то, что он в первую очередь видит и с чем работает.

Одним из немногих в то время онлайн-проектов, в которых активно использовался веб-терминал был PythonAnywhere. Он стал эталоном, на который я периодически посматривал. Это сейчас уже появилось огромное количество веб-проектов и облачных сред разработки, в которых можно увидеть терминалы: Koding, Nitrous, Codebox, Runnable и др.

Любой веб-терминал состоит из двух основных частей:
  • Клиентской: динамическое JavaScript приложение, занимающееся перехватом нажатий клавиш и отсылкой их серверной части, приемом данных от серверной части и их отрисовкой в веб-браузере пользователя.
  • Серверной: веб-сервис, который принимает сообщения о нажатиях клавиш от клиента и отправляет их в управляющее терминальное устройство (pseudo terminal или PTY) связанного с терминалом процесса, например bash. Сырой вывод терминала из pty-устройства пересылается неизменным в клиентскую часть или обрабатывается на стороне сервера, в этом случае в клиентскую часть передается уже преобразованным, например, в формате HTML.

Было рассмотрено множество эмуляторов терминала: Anyterm, Ajaxterm, Shellinabox (используется в PythonAnywhere), Secure Shell, GateOne и tty.js. Последние два оказались наиболее функциональными и активно развивающимися. Из-за распространения под более свободной лицензией MIT выбор остановился на tty.js. Tty.js является client-side эмулятором терминала (разбор сырого вывода терминала, в том числе управляющих последовательностей, выполняется на клиенте с помощью JavaScript).

Серверная часть tty.js, написанная на Node.js, была беспощадно отломана и переписана на Python. Транспорт Socket.IO был заменен на SockJS, о подобном удачном опыте уже писали в блоге PythonAnywhere.

Полет «Светлячка»


Наконец дошли до движка платформы Root’n’Roll. Проект построен по принципам микросервисной архитектуры. Основной язык разработки серверной части — Python.

Диаграмма связей сервисов платформы Root’n’Roll:
Диаграмма связей сервисов платформы Root’n’Roll

Микросервисы носят имена основных героев научно-фантастического телесериала «Светлячок» (Firefly). Основные герои фильма — экипаж межпланетного космического корабля «Серенити» класса Светлячок. Назначение и место персонажа на корабле в некоторой степени отражает предназначение и функционал соответствующего его имени сервиса.

Mal – backend API


Mal — владелец и капитан корабля. На нашем корабле Mal является ключевым сервисом, координирующим работу всех остальных сервисов. Это приложение на Django, которое реализует бизнес-логику платформы Root’n’Roll. Mal выполняет роль API-клиента приватного OpenStack-облака и в свою очередь предоставляет высокоуровневый REST интерфейс для выполнения следующих действий:
  • Создание/удаление виртуальной машины (контейнера). Запрос преобразовывается и делегируется облаку.
  • Создание и подключение терминала к контейнеру.
  • Запуск тестового сценария для проверки конфигурации виртуальной машины. Запрос делегируется микросервису проверяющей системы.
  • Получение результатов проверки конфигурации.
  • Аутентификация клиентов и авторизация различных действий.

Kaylee – мультиплексор терминалов


Kaylee — механик корабля. Сервис Kaylee является двигателем процесса коммуникации веб-терминала с удаленной виртуальной машиной. Это асинхронный веб-сервер на Python и Tornado, реализующий серверную часть tty.js.

С одной стороны, клиентская часть tty.js (терминальное окно) устанавливает соединение с Kaylee по протоколу SockJS. С другой стороны, Kaylee устанавливает соединение с терминальным устройством виртуальной машины. В случае с docker-контейнерами соединение устанавливается по протоколу HTTPS с управляющим pty-устройством работающего в контейнере процесса, как правило, это процесс bash. После чего Kaylee выполняет простую функцию прокси-сервера между двумя установленными соединениями.

Для аутентификации клиента и получения данных о виртуальной машине Kaylee общается с Mal по REST API.

Zoe – check-система


Zoe — помощник капитана на борту, во всем ему безоговорочно доверяет. Zoe является автоматической проверяющей системой, выполняющей тестирование конфигураций виртуальных машин. Сервис Zoe в виде celery-таски получает от Mal’а задание на запуск тестового сценария. По окончанию проверки сообщает по REST API обратно Mal’у результаты тестирования. Как правило, Zoe ошибок не прощает (многие участники курса по Linux на Stepic’е уже успели в этом убедиться).

Тестовый сценарий представляет из себя не что иное, как Python-скрипт с набором тестов, написанных с использованием фреймворка для тестирования py.test. Для py.test был разработан специальный плагин, который обрабатывает результаты запуска тестов и посылает их Mal'у по REST API.

Пример сценария для упражнения, в котором нужно написать и запустить простой одностраничный сайт на веб-фреймворке Django:

import re
import requests

def test_connection(s):
    assert s.run('true').succeeded, "Could not connect to server"

def test_is_django_installed(s):
    assert s.run('python -c "import django"').succeeded, "Django is not installed"

def test_is_project_created(s):
    assert s.run('[ -x /home/quiz/llama/manage.py ]').succeeded, "Project is not created"

def test_hello_lama(s):
    try:
        r = requests.get("http://%s:8080/" % s.ip)
    except:
        assert False, "Service is not running"
    if r.status_code != 200 or not re.match(".*Hello, lama.*", r.text):
        assert False, "Incorrect response"

Для удаленного выполнения команд на тестируемой виртуальной машине Zoe использует библиотеку Fabric.

Заключение


Вскоре на платформе Stepic любой желающий сможет создавать свои курсы и интерактивные упражнения по работе в Linux с использованием всех тех технологий, о которых я рассказал в статье.

В следующей статье я напишу о своем успешном участии в JetBrains EdTech хакатоне, об особенностях и проблемах интеграции Root’n’Roll в Stepic и, по вашему желанию, раскрою глубже любую из затронутых тем.
Автор: @psviderski
Stepik.org
рейтинг 55,62
Открытые бесплатные курсы на технические темы
Похожие публикации

Комментарии (24)

  • +3
    спасибо за статью и упоминания Светлячка
    а у нас сервера носят названия из Star Wars
  • +1
    А не пробовали CoreOS для управления докерами?
    • +1
      Да, и спасибо за статью.
    • +2
      Не пробовали, и вряд ли это имеет для нас смысл. OpenStack выбран с перспективой, что вскоре добавим поддержку полноценных виртуалок, например, на KVM. Могут быть нужны для создания более сложных упражнений, которые выходят за рамки возможностей контейнеров. Например, задания по настройке сети, туннелей, каким-нибудь махинациям с ядром.
      В таком случае мы добавим новые compute-ноды с гипервизором KVM в наше облако и автоматом по тому же OpenStack API сможем запускать и контейнеры, и нормальные виртуалки.
  • +1
    1. Какие были причины для перепиливания tty-сервера? Какие были проблемы/нестыковки со штатным (кроме транспорта)?
    2. Осуществляется ли миграция запущенных контейнеров в случае потери хоста?
    3. На диаграмме показано, что zoe общается с докер-хостами по ssh. Какие причины были на то, чтобы не запускать свою собственную zoe на каждом докер-хосте?

    А вообще, архитектурка аккуратная получилась, вполне неплохо.
    • +2
      1. Одна из причин — нежелание внедрять в проект еще одну нанотехнологию в лице node.js (docker'а с openstack'ом пока хватает более чем). Вторая причина — все равно ведь пришлось бы адаптировать штатный: нужен механизм аутентификации клиентского терминала, получение инфы о терминале от сервиса Mal, механизм подключения к tty контейнера (штатный, если я не ошибаюсь, поддерживает только tty сессию с локально запущенными процессами).
      2. Миграция контейнеров не осуществляется. Пока нет родных средств миграции docker-контейнеров. Предполагаю, что можно извратиться и мигрировать контейнер с помощью CRIU, т.к. по сути контейнер — это обычный процесс, запущенный в необычном окружении. А вообще оно и не критично сейчас: ну издох сервер, ну упали текущие решаемые задания, да, грусть и печаль, но не смертельно.
      3. На диаграмме показано, что Zoe общается по ssh с docker-контейнерами, не хостами. Эта связь нужна для выполнения удаленных команд в контейнере. На данный момент ssh оказался самым простым и доступным способом проверки состояния контейнера, в частности файловой системы. Если с контейнерами еще можно играться через хостовую систему, то с полноценной виртуалкой сложно что-то похожее сделать с гипервизора. Для виртуалок, видимо, ssh тоже будет самым простым способом пошариться во внутренностях машинки.
      • +1
        Т.е., zoe заходит по ssh именно в контейнер? Понял, спасибо.

        PS: Просто на мой взгляд, испекция содержимого контейнера и инспекция содержимого виртуалки — две большие разницы. Мне как-то в первую очередь подумалось о том, чтобы (в случае именно с докером), находясь на докер хосте, просто запускать процесс-чекер в целевом контейнере. И не держать sshd без лишней надобности. Но, в принципе, тут уже дело личных предпочтений.
        • 0
          Да, вы все верно разобрали: в каждом контейнере помимо bash запускается еще sshd. Согласен, что есть оверхед с демоном ssh, запросто можно инспектировать контейнер и без него с docker-хоста. Но в этом случае нужно разрабатывать инструментарий, чтобы этим пользоваться. В случае с ssh, запустили демон и сразу имеем кучу тулов, которые с ним работают, в нашем случае библиотека fabric на python. В общем, иногда лучше добавить небольшой оверхед, чтобы снять с себя другие проблемы, эффективное решения которых не так и важно.

          Интересно, а какой у вас опыт использования контейнеров?
          • +1
            Мы около года назад начали использовать докер для доставки релизов бэкенд-части сервиса. Тоже микросервисная архитектура, но микросервисов около 50 вместо трех. Плюс требования к масштабируемости и доступности. Сервисы преимущественно на эрланге.

            Одновременно используем двух облачных провайдеров и еше парк baremetal-хостов (тут больше организационно-политические моменты, нежели технические). Проблем много, многие из них еще в процессе решения.

            Для управления baremetal-хостами сначала пытались приспособить openstack, но потом отказались (я как-то упустил этот момент, не участвовал в этом проекте). Потом мучались с mesosphere. Это был кромешный ад, на эту тему я могу материться очень долго =) Сейчас пробуем coreos. Привыкаем, но вопросов много.
            • 0
              Если будет возможность, напишите, пожалуйста, статью о подводных камнях, то хвалебных од много, а описания проблем — не очень (хотя, в issues, конечно, прилично).

              Я сейчас мигрирую одно приложение (совсем не микросервисы, но 10-12 компонент) в докер. В принципе, всё более-менее работает, доставка через registry (на s3), пока собираю шишки.

              В качестве хостов пока centos 6 и 7, т. к. не всё смигрированно, да и btrfs на coreos смущает (с учетом того, что развертывание системы может происходить и на 1 хосте).

              Из регулярно раздражающих вещей пока то, что dm не всегда отмонтирует разделы, что мешает автоматическому удалению машин при перезапуске сервиса.

              Кроме того, data volume (device mapper'овский) прилично загаживается (в особенности актуально на dev-машине с небольшим ssd). Это несмотря на регулярное удаление ненужного барахла (старых образов). Правда, на btrfs тоже ругаются в этом плане.
              • 0
                К сожалению, не думаю, что это будет в ближайшее время. Конкретно сейчас мы висим в промежуточной стадии между mesosphere и coreos, а конкретно проектом по coreos я не занимаюсь. Поэтому, поделиться опытом я смогу только тогда, когда оно уже окажется в реальном продакшоне.
                • 0
                  Никогда не поздно, тем более, что могут вылезти новые интересные corner cases.

                  Вы, кстати, какое-либо решение используете для создания оверлейной сети между docker-хостами?
                  • 0
                    Пытались наколдовать свой велосипед на openvswitch, потом решили, что оно нам тупо нафиг не нужно =) Все контейнеры вполне удовлетворительно чувствуют себя в одной сети, поэтому пока что не тратим силы.
                  • 0
                    У нас тоже пока без особых изяществ и вкусностей насчет сети: все пользовательские контейнеры в одном L2 сегменте и одной 10.16.0.0/12 сети. Пока серьезных проблем с безопасностью не видится, возможно, позже допиливать будем nova-docker драйвер для поддержки floating network.
                    • 0
                      Сори за нубский вопрос. Можете раскрыть суть понятия floating network? Можете просто тыкнуть ссылкой в описание и типовые сценарии использования.

                      PS: Вот это оно? www.mirantis.com/blog/configuring-floating-ip-addresses-networking-openstack-public-private-clouds/
                      • 0
                        Да, хорошо мирантис написали. Типа пул публичных ip адресов. Если взять для примера amazon ec2, то там для инстенса выделяют 10.x.x.x адрес (приватный) и floating (публичный), по которому инстенс доступен из интернетов.
                        Не уверен, что это именно то, что нам будет нужно, может, приватные сетки для разных заданий лучше создавать. Хорошо бы еще по vlan'ам рассовать их разным. Вообще, были какие-то попытки сделать поддержку neutron (SDN controller) для докера в openstack'е, не в курсе, как там успехи.
                        В ближайшее время в конфигурации сети точно ничего не буду глобального менять.
                        • 0
                          А, кстати, зачем вам могут понадобиться разные сетки и vlan'ы? (я просто не спец в сетях)

                          Не смотря на то, что у нас достаточно большое количество контейнеров, а некоторые (особенно во время рынка) генерят достаточно большой объем трафика, у нас даже подозрений ни разу не было, что надо делать сеть более продвинутой (именно с точки зрения производительности сети).

                          А что касается группировки сервисов — все сервисы организуются в кластера на более высоких уровнях. В основном, приложения внутри контейнеров сами несут ответственность за то, чтобы обнаруживать свои зависимости (через zookeeper или etcd, например). Они же сами обнаруживают изменения в составе кластера, переподключаются куда-либо при необходимости. Конечно, всегда есть вероятность, что сервис полезет куда-нибудь не туда. Но на практике такого никогда не возникало.

                          Какие еще могут быть показания для этого?

                          UPD: Это что касается управления baremetal-хостами. В amazon-е все более или менее распилено по vpc. Но там другие соображения, другие задачи.
            • +3
              Сервисы и все остальное (базы, message queue) тоже деплоим в контейнерах. Довольно сыро еще в этой области, вроде как docker совсем недавно начали активно это направление развивать blog.docker.com/tag/orchestration/.
              Все хостовые системы у нас CentOS 7. Пока часть сервисов деплою с помощью Geard. Достаточно хорошо работает, особенно подходит для версий docker, когда в которых еще плохо работал механизм авторестарта контейнера (geard использует systemd). Еще geard'шные link'и мне понравились больше, чем встроенные в docker (geard разруливает линки с помощью iptables nat в сетевом неймспейсе контейнера).
              Другую часть сервисов попробую деплоить уже без systemd, со встроенным авторестартом с помощью ansible. Не всем удовлетворил меня docker модуль для ansible. К примеру, нет возможность сделать docker pull нового имаджа с реестра. Можно передеплоить контейнер с предварительным pull'ом, но тогда получается даунтайм сервиса на время скачивания нового образа.
              • +1
                Ух ты! Вот geard я вообще упустил из вида. Большое спасибо за наводку. Мы в деплойментах, не использующих systemd, раскатываем puppet-ом контейнеры на хостах.
                Я даже не в курсе, есть ли у puppet-модуля проблема аналогичная той, которую Вы описали. Вернее, я не уверен, что правильно понял смысл фразы

                >> К примеру, нет возможность сделать docker pull нового имаджа с реестра.

                У нас в допустимо нормальное одновременное сосуществование нескольких версий одного и того же сервиса. Т.е., мы имеем возможность поднять новую версию контейнера рядом со старой, а потом, убедившись, что она работает корректно, просто потушить старую версию. Нюансы, конечно, есть. Но жить с ними можно.
                • +1
                  А как вы следили за живностью контейнеров и рестартовали их, если они подыхали, на docker версиях до 1.2.0 (до добавления restart policy blog.docker.com/2014/08/announcing-docker-1-2-0/)?

                  Еще интересно, как вы организуете версионирование образов контейнеров (названия, тэги)?

                  Правильно я понял, что ваша архитектура позволяет делать апдейты без даунтайма? Т.е. выкатываете новую версию контейнера, она уже входит в работу одновременно со старой, потом тушите старую. Балансировщики какие-то есть?
                  • +3
                    Изначально (я кажется выше вскользь упоминал) мы пытались использовать mesosphere. Раскатыванием контейнеров по хостам (и слежением за ними) должна была заниматься вот эта хрень github.com/mesosphere/marathon. Оно перезапускало остановленные контейнеры, и в случае потери хоста, перетаскивало контейнеры на другие живые хосты.

                    Мы жрали этот кактус более полугода, и докер 1.2 вышел еще тогда, когда мы не бросили mesosphere. Тем не менее, мы и сейчас не используем коробочный рестарт докера — за контейнерами следит, например, upstart. Функцию свою выполняет, острой необходимости что-то менять пока не было.

                    С версионированием пока что бардак.
                    1. Cо всякой инфраструктурой (проксики, zookeeper'ы и всякие прочие rabbitmq) все элементарно. Имя сервиса — и есть имя образа. Если образ собран из мастер-бранча, ему автоматически каждый раз лепится тэг latest. Если из какого-то постороннего бранча — в тэге просто выставляется имя бранча и номер сборки. Все потребности такая схема покрывает.
                    2. С эрланг-сервисами (которые мы сами разрабатываем) все уже чуть печальнее. Для каждой сборки задается отдельное имя образа (что-то типа "${BRANCH_NAME}_${BULD_ID}"), в качестве тега — уже конкретное имя сервиса (например, те же mal, zoe, kaylee).

                    Насчет апдейтов — да, все верно поняли. Не уверен, что точно понял, какие балансировщики вы имеете в виду, но попытаюсь.
                    1. Во-первых, на уровне клиентских web-socket'ов, мы по разным датацентрам раскидываем запросы dns'ом.
                    2. В каждом датацентре может быть поднято несколько одновременно функционирующих кластеров, дублирующих друг друга (например, на случай факапа при апдейтах). В каждом кластере (если он предназначен для вебсокет-клиентов, разумеется) одновременно работает ферма веб-серверов. Все они регистрируются в zookeeper (или etcd, не важно). По этим записям конфигурятся проксики (ngxin, либо haproxy) и именно они раскидывают клиентов по вебсерверам в пределах датацентра.
                    3. Для взаимодействия сервисов между собой у нас есть собственный самопальный мессаджинг (брат-близнец zeromq). Причины ухода со стандартного erlang distribution — отдельная обширная тема. Там тоже балансировщик уровня сообщений (самопальный) с некоторым уклоном в предметную область (и отчасти в legacy).

                    В плане апдейтов без даунтайма мы оставляем себе достаточно большой простор для действий. Все сервисы мы разрабатываем так, чтобы в любой момент они могли потерять свое состояние без каких-либо последствий. Поэтому, для нас вполне доступен даже самый простой вариант «выключить контейнер, сходить покурить и потом включить новый» (утрирую, конечно). Вполне работоспособна (и часто применяется) схема, про которую я упоминал выше — запустить новую версию сервиса, убедиться, что она работает, потушить старую. Чаще всего, все-таки, обновляемся целыми кластерами.
    • 0
      А, и кстати, еще вопрос. Пользователь внутри контейнера видит все 100500 Гб RAM и столько же ядер с хоста? Ну, например, если запустит htop. Ну и загрузку CPU и памяти он увидит именно хостовую? Или вы как-то справляетесь с этим? Если не секрет — как?
  • +1
    В начале статье есть ссылка на первое задание из курса, можете сами посмотреть, запустить top, извините, htop не поставил :)). Да, пользователь видит все хостовые ресурсы, как есть, никак не справляемся с этим. Docker-хосты, кстати, — это KVM виртуалки. Сейчас задача стоит донести пользователям максимум нашего опыта, показать, как и что можно делать с платформой, собрать фидбек и двигать в правильном направлении. Можно, конечно, с головой закопаться в вопросах безопасности, стараемся находить некий компромисс.
    • 0
      Да насчет компромиссов — это понятно ) Мне просто было интересно, может вы как-то случайно зацепили этот вопрос в процессе исследований.

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

Самое читаемое Разное