Pull to refresh

Управление памятью гостевой машины в облаке

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

Ядро забирает себе всю свободную память для кеша. Если есть дисковые операции и есть свободная память — кеш будет расти. В случае сервера с единолично пользуемой памятью это благо, однако, если мы говорим о том, что все мегабайты платные, платить за дисковый кеш в 10-20Гб откровенно не хочется.

Я пытался найти возможность ограничить размер дискового кеша для линукса, но всё, что нашёл — это странный патч 2003 года (который, разумеется, в основную ветку не взяли).

Получается, что чем больше гость работает, тем больше его ядро берёт себе памяти от (неограниченного) объёма. Результат — если не ограничивать систему вообще, то она за весьма незначительное время вырастает либо до размера дисковых устройств (спасибо, дискового кеша больше, чем размер диска, не бывает), либо до максимально доступного на платформе объёма памяти. Заметим, что в этих условиях пасуют все технологии — и компрессия памяти, и дедупликация страниц памяти (у каждой ВМ свой кеш). Эта проблема стоит перед любой системой виртуализации. Ниже описываются варианты решения с оглядкой на Xen Cloud Platform.



Варианты решений


Я вижу три варианта решения проблемы:

  1. Использующийся в Xen механизм xenballoon. В ядре специальный драйвер при обращении к нему изнутри самой системы, резервирует память у операционной системы и отдаёт её гипервизору («освободждает»). При необходимости его просят «взять обратно» — и он берёт (т.е. возвращает системе). Фактически, используемая balloon память является занятой с точки зрения гостя и свободой с точки зрения гипервизора. Когда память забирается у гипервизора, она становится свободной для гостя и занятой для гипервизора.
  2. Внешний механизм регуляции доступной памяти. От балунинга отличается только тем, что решение о выделении/удалении памяти принимает не приложение, дёргающее xenballloon, а внешная система управления. Зен давно позволяет на ходу менять объём доступной памяти для гостевых машин (сколько поставишь, столько и будет). Вплоть до забавной ситуации, когда памяти дают меньше, чем занято сейчас. В этом случае на помощь приходит oom_killer внутри гостевой системы (и так лучше не делать)
  3. Написание патча к ядру, который бы ограничивал размер дискового кеша неким фиксированным значением.


Подробнее


Третий вариант, наверное, самый интересный. Но, требующий существенных изменений в коде ядра, а, возможно, и пересмотра всего механизма работы с памятью. Для меня этот путь… несколько тернист.

Первый и второй — реально работающие уже сейчас. Однако, у них есть один существенный недостаток: при подобной системе добавление/удаление свободной памяти происходит асинхронно с запросами. Грубо говоря, если в гостевой системе свободно 200Мб памяти, приложение попросило 500, то ему откажут в выделении. Потому что у ядра нет лишних 300Мб. А демон (или внешний монитор) узнает об этой проблеме уже после отработки запроса на выделение памяти.

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

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

Свопирование


Во-вторых, есть своп-файл. Если приложение попросило при 500 свободных 200Мб, то ей дадут 200 мегабайт из свободной памяти, а 300Мб малоиспользуемых данных выкинут в своп и выдадут требуемое. А дальше тот же монитор, увидев нехватку памяти, накинет ещё 500Мб гостевой системе, так, чтобы она могла продолжать работать спокойно. Поскольку в своп будут выкинуты самые малоактуальные данные, то есть большая вероятность, что доступ к ним будет весьма и весьма редким (или вообще никогда не произойдёт). Благодаря «демпферу» в виде файла подкачки, есть возможность объективно предоставлять память без ситуаций oom (out of memory), но и без прожорливого кеша на десятки гигабайт.

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

Свободная память


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

В XCP (Xen Cloud Platform) единственным методом для определения свободной памяти является агент (демон), который сообщает в гипервизор о том, сколько памяти свободно. Исходя из этой информации гипервизор решает, сколько памяти добавить и убрать в госте.

Как это выглядит со стороны гостевой системы? У неё запущен простенький скрипт, который через интервалы времени пишет в xenstore (канал связи между гипервизором и гостевой системой) данные о свободной памяти (заодно он пишет текущий IP-адрес, версию ОС). Система управления облаком смотрит на эту информацию и добавляет/убирает память гостя.

С точки зрения гостя объём свободной памяти практически всегда остаётся один и тот же, вне зависимости от того, сколько памяти заняли приложения, эта память используется для дискового кеша. В случае каких-то стихийных взбрыков (запрос 1Гб за раз — это не очень типичное поведение) возникают кратковременные моменты свопинга, однако, на настоящий момент (тестирование ещё не началось) я полагаю, что эти случаи будут единичными и нехарактерными. С точки зрения гипервизора у гостевой машины меняется объём используемой памяти, причём меняется в зависимости от того, какой объём памяти реально используется в госте.

Что произойдёт, если гость решит «похулиганить» и поменяет код демона, сообщающего о свободном объёме памяти, или просто выключит его? Для хостера — ничего плохого. Он просто перестанет получать информацию о свободной памяти (и перестанет её регулировать). Если же данные напишут неправильные — либо заберёт много памяти у гостя (гость мог этого добиться и сам, прибив лишние приложения), либо даст ему много памяти — но гость-то платит по потреблению… Так что я не думаю, что кто-либо в продакте решит серьёзно хулиганить с этим сервисом.

Я всё ещё сомневаюсь в том, какой механизм управления памятью лучше — средствами демона гостя (xenballooning) или средствами внешнего монитора.
Tags:
Hubs:
Total votes 12: ↑8 and ↓4 +4
Views 1.3K
Comments Comments 3