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

Будни разработки облака, часть первая

Время на прочтение6 мин
Количество просмотров1.6K
Серию официальных постов в блоге компании про то, как работать с облаком я ещё продолжу, но параллельно мне хочется рассказать про те проблемы, с которыми мы столкнулись во время адаптации Xen Cloud Platform под нашу модель работы облака. Эти посты будут чуток сложнее и предполагают, что читатель хотя бы в общих чертах знает, как работает Xen.

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

Действительно, у нас есть xencontrol (библиотека управления гипервизором Xen), которая может точно сказать про каждый домен (запущенную виртуальную машину), сколько у неё есть памяти, сколько наносекунд времени было потрачено. Эта библиотека запрашивает информацию напрямую (через xenbus) у гипервизора и подвергает её минимальной обработке.

Выглядит эта информация примерно так (вывод биндинга xencontrol для питона):
{
    'paused': 0, 
    'cpu_time': 1038829778010L, 
    'ssidref': 0, 
    'hvm': 0, 
    'shutdown_reason': 0, 
    'dying': 0, 
    'mem_kb': 262144L, 
    'domid': 3, 
    'max_vcpu_id': 7, 
    'crashed': 0, 
    'running': 0, 
    'maxmem_kb': 943684L, 
    'shutdown': 0, 
    'online_vcpus': 8, 
    'handle': [148, 37, 12, 110, 141, 24, 149, 226, 8, 104, 198, 5, 239, 16, 20, 25], 
    'blocked': 1
}


Как мы видим, есть поле mem_kb, соответствующее выделенной памяти для виртуальной машины и есть поле cpu_time, содержащее какое-то умопомрачительное число (хотя на самом деле это всего лишь 17 минут). cpu_time считает с точностью до наносекунд (точнее, величина, которая тут хранится считается в наносекундах, реальная точность около микросекунды). Память, как понятно, в килобайтах (хотя внутренней единицей учёта, что гипервизора, что ядра линукс является страница — её размер по-умолчанию 4 килобайта).

Казалось бы «бери и считай», однако, дьявол кроется в деталях…

Извините за жёлтый заголовок ниже, но именно так звучал вопрос в полемике в ходе обсуждения одной из проблем:

Hyper-threading + Xen = воровство денег у клиентов



Вопрос: включать или нет на хостах с Xen'ом hyperthreading? Его включение позволяет предложить клиенту больше ядер. Для двух зеонов по 4 ядра на каждом это даст 16 ядер, а если мы зарезервируем парочку под собственные нужды, то 14 ядер. 14 круче, чем 8? Круче. Значит, должно быть 14.

Кроме того, если запускать multithread приложение, то оно на 14 «фальшивых» ядрах посчитает в полтора раза быстрее, чем на 7 настоящих. Это действительно так, я проверял на тестах на «голом» линуксе на одном из тестовых серверов.

… Стоп. В полтора? То есть 14 ядер будет работать в полтора раза меньше при в два раза большем числе ядер?

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

Уровень загрузки Учтённое время процессора без HT С HT
соседи idle, 1 ядро 313.758 313.149
соседи idle, 4 ядра 79.992 * 4 80.286 * 4
соседи idle, 8 ядер 40.330 * 8 40.240 * 8
соседи idle, 16 ядер - 29.165 * 16
соседи с полной загрузкой, 1 ядро 313.958 469.510
соседи с полной загрузкой, 4 ядра 79.812 *4 119.33 * 4
соседи с полной загрузкой, 8 ядер 40.119 * 8 59.376 * 8
соседи с полной загрузкой, 16 ядер - 29.634 * 16


Легко увидеть, 29.6*16 — это 473.6, так же как и 59.376*8 (475). И это в полтора раза больше, чем 40.119*8 (320).

Другими словами — hyper-threading в полтора раза замедляет процессоры при удвоении их числа.

Это помогает, если процессор целиком ваш. А если оплачивается процессорное время и рядом есть даже не «коллеги», а просто «посторонние люди»?

После этого у нас состоялась большая дискуссия (заняла она с перерывами примерно три дня) — делать ли HT на хостах облака для клиентов? Помимо очевидного «честно-нечестно» и «никто не узнает» были куда более серьёзные аргументы:
  • Один сервер будет генерировать больше ресурсов процессора (то, ради чего Intel эту технологию делала)
  • Мы можем учесть эту «потерю производительности» в снижении цены машинного времени
  • Мы можем следить за загрузкой хоста и не допускать перегрузку выше 50%, зато сможем предоставить клиенту больше ядер


После дискуссии мы пришли к следующему набору аргументов: Мы не можем контролировать и реально (а не статистически) предсказывать потребление машинного времени. Миграция, хоть и выход, но частичный, ибо реакция миграцией должна быть порядка 30-40с минимум, а взбрыки по загрузке могут быть мгновенными (менее секунды). В связи с этим мы не знаем какое машинное время (полноценное или нет) мы предоставили клиенту, и в любом случае клиент будет сталкиваться с неоправданной потерей производительности без видимых причин из-за того, что его соседу захотелось посчитать что-то тяжёлое.

Из-за невозможности обеспечить постоянную производительность виртуальной машины с hyper-threading у нас таки победила точка зрения, что HT в облаке с оплатой машинного времени должен быть выключен (отсюда и лимит в 8 ядер на виртуалку).

Миграция: copy and delete


Вторым смешным моментом была проблема учёта ресурсов при миграции. По-умолчанию полагается, что handle (он же uuid) — это доказательство уникальности объекта, и двух виртуальных машин с одним uuid'ом быть не может. Действительно, это так. Однако, это касается виртуальных машин, а не доменов. При миграции же содержимое домена (оперативная память) копируется, запускается на новом узле, и только после этого удаляется на старом. Всё это сопровождается многочисленными перекопированиями фрагментов домена (т.к. виртуальная машина при этом продолжает работать). В любом случае, у нас получается ДВА домена от ОДНОЙ виртуальной машины. Если мы будем грубо и в лоб считать циферки (суммировать), то в итоговых счётчиках мы получим совершенно неверные цифры. (Кстати, эта проблема обнаружилась довольно поздно и была одной из причин задержки запуска).

Решение проблемы было изящным и архитектурно-красивым. В один момент времени может работать только одна копия домена — все остальные находятся в режиме паузы. Это очень важно, потому что если у нас будут работать два домена, то они могут наломать редкостных дров. Таким образом, решение выглядит так: остановленный (paused) домен не обсчитывается. У этого есть несколько мелких негативных эффектов:
  • Мы не смогли предложить клиентам эффектную кнопку «пауза» (в этом режиме домен существует, но не выполняется). Так как такой домен потребляет память, то мы не можем позволить себе не учитывать его, если клиент ставит виртуальную машину на паузу и уезжает в отпуск. А различить «паузу при миграции» и просто «паузу» мы не можем (по-крайней мере без очень больших и нетривиальных танцев с состояниями и базами данных).
  • Когда клиент перезагружает машину, есть маленький момент, когда домен уже существует, но ещё paused — мы его не считаем (таким образом, клиент, постоянно перезагружающий машину сможет неучтённо потребить небольшой объём памяти). Возможно, что так даже честнее, потому что это наши проблемы — где там что строится, пока машина не начала работать, клиенту нет резона её оплачивать.


Но в остальном это решение не имеет никаких побочных эффектов. А обсуждалось несколько: наличие блокировки в базе учёта, учёт срока жизни домена и т.д. Все они на фоне элегантности решения с неучётом остановленных доменов выглядят громоздкими и уродливыми (сам не похвалишь никто не похвалит, увы).

Кто заплатит за dom0?


Ещё одной гигантской проблемой была проблема загрузки dom0. Когда пользователь делает запрос по сети или совершает дисковые операции, запрос передаётся из domU (домена, который и есть выполняющаяся виртуальная машина) в dom0 второй половинке драйвера. Драйвер кумекает над запросом, передаёт его уже настоящим драйверам настоящих железок. И надо сказать, при интенсивных дисковых операциях он кумекает ой как. Увидеть us под 50-80% — как нефиг делать. И большая часть из этого числа — OVS, blktap, xenstore и т.д. (оставшееся — xapi, squeezed, stunnel, являющиеся частью системы управления облаком). Кому предъявлять счёт за это машинное время? И главное, как отделить одного пользователя от другого? На уровне драйвера это ещё, быть может, и возможно, но дальше…
Тот же OVS (Open vSwitch, программа, обеспечивающая виртуальную сеть) коммутирует фреймы, и ему дела нет, какому домену они принадлежат.

Зеновцы (разработчики гипервизора и его обвязки) голову сломали над этим вопросом. Я тоже начал было думать, но вовремя опомнился. Если дисковые операции платные, то в их цену, собственно, и заложена стоимость обработки запроса. Это не только IOPS'ы дисков, нагрузка на рейд контроллеры, SAN, амортизация 10Г-карточек и т.д. Это и (совсем незначительное по цене на фоне вышеперечисленного) машинное время dom0. Всё логично и решилось само собой.
Теги:
Хабы:
+63
Комментарии13

Публикации

Истории

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

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн