Каждому специалисту по ИТ приходилось подбирать сервер для какой-либо задачи, и наверняка вопрос о том, сколько ставить на него памяти, заставлял призадуматься. Дело в том, что наперед сказать, сколько памяти потребуется для тех или иных задач, не всегда легко. А поручиться за то, что спустя некоторое время этой памяти будет все еще достаточно, — практически невозможно. Взять хотя бы простой пример: файл-сервер, на котором хранятся документы пользователей. Сколько понадобится памяти для файл-сервера в небольшой организации, с 10–20 пользователями? А сколько потребуется, когда организация разрастется, и штат сотрудников увеличится, скажем, до 100 человек? Другой пример — корпоративный веб-сайт. Нормальный режим работы предполагает 50–100 посещений в день, но тут запускается рекламная кампания, и наплыв посетителей резко возрастает до десятков тысяч посещений в день. В таких ситуациях нехватка памяти, приводящая к падению производительности, случается довольно часто. Заранее, на этапе проектирования, предсказать такие ситуации невозможно, поэтому обычно память берется с некоторым запасом. Теперь представим, что мы решили перейти на виртуальную инфраструктуру. Всего у нас, к примеру, десять серверов. И все эти серверы мы хотим перенести в виртуальную среду. Если для каждой из виртуальных машин делать такой же запас по памяти, как и раньше, придется закупать память для сервера с десятикратным (!) запасом. Стоит ли говорить о том, что использоваться из этого громадного объема памяти будет от силы 10%, а остальное будет лежать мертвым грузом, и руководству ИТ-отдела будет мучительно больно за бессмысленно потраченные средства.

Простой пример

Возьмем для примера хост с 16 Гбайт памяти (рисунок 1). Путем гадания на кофейной гуще мы установили, что одной виртуальной машине может потребоваться максимум 3 Гбайт памяти. Ну и еще гигабайт — «про запас», на всякий случай. Получаем по 4 Гбайт на каждую виртуальную машину. В итоге на нашем хосте будут комфортно работать три виртуальные машины. При этом большую часть времени использоваться будет не так и много (3,5 Гбайт в нашем случае), но доступно будет лишь 4 Гбайт памяти. Максимум это позволит создать еще одну виртуальную машину, и то если «потесниться» — уменьшить объем памяти других виртуальных машин или выделить 3 Гбайт вместо 4 Гбайт. Ведь операционная система хоста тоже «хочет кушать», и для нормальной работы ей нужен как минимум 1 Гбайт памяти.

 

 Рисунок 1. Сравнение статической и динамической памяти

 

А теперь, если мы используем динамическую память, то благодаря рациональному использованию памяти сможем запустить на том же самом хосте еще две виртуальные машины, которые могут спокойно переносить пиковые (потребление 3 Гбайт памяти) и сверхпиковые (4,5 Гбайт) нагрузки. И при этом теоретически можно запустить еще три виртуальных машины (при условии, что у них объем оперативной памяти для запуска равен 512 Мбайт). Забегая немного вперед, скажу, что в примере взяты настройки динамической памяти по умолчанию: Startup RAM = 512 Мбайт, Maximum RAM = 64 Гбайт, Free Buffer = 20%.

Высокая доступность

Возьмем другой пример: кластер с обработкой отказа из трех узлов. Каждый из узлов имеет 3 Гбайт памяти, и запущено на каждом узле по три виртуальных машины с объемом памяти по 3 и 4 Гбайт (рисунок 2).

 

Рисунок 2. Конфигурация кластера и виртуальных машин

 

Допустим, узел NODE3 выходит из строя, и виртуальные машины перезапускаются на других узлах. Как видно, одной из виртуальных машин не хватает памяти, и она не может стартовать (рисунок 3).

 

Рисунок 3. Перезапуск виртуальных машин при выходе из строя одного из узлов — одна из виртуальных машин не может запуститься из-за нехватки памяти

 

На узле NODE1 виртуальные машины уже используют 13 Гбайт памяти, и, поскольку операционная система сервера тоже «хочет кушать», то свободных 3 Гбайт для VM8 нет. То есть для полной отказоустойчивости нам нужно выполнить одно из следующих действий:

  • добавить еще один узел;
  • уменьшить количество виртуальных машин;
  • уменьшить объем памяти одной или нескольких виртуальных машин.

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

А теперь посмотрим, как будет выглядеть ситуация с использованием технологии Dynamic Memory. Допустим, что параметр Startup RAM установлен в 1 Гбайт. Это означает, что виртуальной машине при запуске будет выделяться 1 Гбайт памяти и для успешного запуска не нужны все 4 Гбайт свободной памяти. Как показано на рисунке 4, при использовании Dynamic Memory все виртуальные машины успешно стартуют на узлах NODE1 и NODE2.

 

Рисунок 4. При использовании Dynamic Memory все виртуальные машины успешно перезапускаются на других узлах

 

Как это работает?

До недавнего времени, как уже было замечено, статическое выделение памяти было одним из камней преткновения при внедрении инфраструктуры на базе Microsoft Hyper-V. С выходом Windows Server 2008 R2 Service Pack 1 ситуация значительно улучшилась: благодаря функции Dynamic Memory память теперь может перераспределяться между виртуальными машинами «на лету» в зависимости от потребностей. Соответственно, нужда в «десятикратном запасе» отпадает. Несмотря на это, .

Давайте познакомимся с основными принципами работы Dynamic Memory.

Архитектура

С точки зрения архитектуры (рисунок 5) работа Dynamic Memory основывается на взаимодействии служб, работающих в родительском разделе, Parent Partition, то есть в операционной системе хоста, и компонентов уровня ядра, так называемых «улучшений» в гостевой операционной системе. Внутри гостевой операционной системы работает компонент Dynamic Memory VSC (DMVSC), взаимодействующий непосредственно с диспетчером памяти гостевой операционной системы. VSC получает сведения о том, как используется в данный момент память гостевой операционной системы, и передает их посредством виртуальной шины VMBus провайдеру Dynamic Memory VSP (DMVSP), работающему в окружении базовой операционной системы хоста. Он в свою очередь передает данные балансировщику памяти Dynamic Memory Balancer. Балансировщик на основании полученных данных, а также настроек (Free Buffer, Weight, Startup/Max RAM) принимает решение о том, надо ли виртуальной машине добавить памяти или же, наоборот, у нее слишком много памяти и излишек можно «отобрать и поделить».

 

Рисунок 5. Архитектура Dynamic Memory

 

Команда на удаление или добавление памяти передается обратно по цепочке: Balancer — DMVSP — VMBus — DMVSC. Дальше происходит следующее.

Добавление памяти. Если нужно добавить память, диспетчер памяти стека виртуализации выделяет виртуальной машине дополнительную память. Компонент DMVSC, используя технологию «горячего добавления памяти», расширяет адресное пространство виртуальной машины, и после этого соответствующие виртуальные адреса сопоставляются с выделенными физическими адресами. Для того чтобы все это работало, необходима поддержка Hot Add RAM на уровне гостевой операционной системы. Именно этим обусловлен достаточно скромный список поддерживаемых операционных систем, о чем я расскажу ниже.

Удаление памяти. Для удаления памяти используется механизм, известный как ballooning. Когда поступает команда на удаление памяти, DMVSC проверяет, какие области памяти на данный момент не используются. Из них отбирается объем, предназначенный для удаления, и затем эти адреса «захватываются» DMVSC в монопольный доступ. После этого «захвата» область памяти помечается как Driver Locked и становится недоступной для использования операционной системой и приложениями. Как только память «захвачена», соответствующие виртуальные адреса «отвязываются» от физических адресов, и соответствующие ячейки памяти могут быть переданы другим виртуальным машинам. В дальнейшем, если виртуальной машине нужно добавить память, соответствующее адресное пространство «освобождается» и связывается с выделенной областью памяти. Важно отметить, что удаление памяти происходит для операционной системы абсолютно незаметно: «захваченная» память по-прежнему остается «видна» системе, хотя и помечается как Driver Locked. Поэтому программы типа Task Manager в гостевой операционной системе не покажут, сколько памяти выделено в данный момент на самом деле. Чтобы увидеть, сколько было выделено памяти виртуальной машине, следует задействовать оснастку консоли Hyper-V Manager или счетчики производительности (подробнее о них будет рассказано далее).

Параметры настройки

После установки SP1 на закладке Memory в свойствах виртуальной машины появится возможность выбора режима выделения памяти: Static или Dynamic. При выборе Static память будет задаваться «жестко», как было до SP1. При выборе Dynamic станут активными новые параметры настройки:

  • Startup RAM;
  • Maximum RAM;
  • Memory Buffer;
  • Memory Weight.

Рассмотрим эти параметры подробнее.

Startup RAM. Объем памяти, выделяемый виртуальной машине при ее запуске. По умолчанию равен 512 Мбайт. Если система не сможет выделить соответствующий объем памяти, виртуальная машина не запустится.

Maximum RAM. Максимальный объем памяти, который теоретически может быть выделен виртуальной машине. По умолчанию это 64 Гбайт.

Memory Buffer. Самый интересный параметр. Задается в процентах и может принимать значения от 5 до 2000%. Дело в том, что система выделяет виртуальной машине память, основываясь на текущем потреблении памяти. Но выдавать памяти в соответствии с учением Маркса «каждому — по потребностям» — не совсем хорошая идея. Например, виртуальная машина может периодически испытывать пиковые нагрузки. Разумеется, система тут же постарается выделить необходимый объем памяти, но, во-первых, его может не оказаться под рукой, а во-вторых, потребление памяти может возрасти настолько резко, что механизм Dynamic Memory просто не успеет среагировать, и на какое-то время производительность упадет за счет выгрузки данных из оперативной памяти на диск. Для того чтобы избежать подобных ситуаций, предусмотрен параметр Free Buffer, позволяющий держать определенный объем памяти свободным. Это означает, что, к примеру, если Free Buffer равен 20%, система всегда будет пытаться обеспечить, чтобы у виртуальной машины было свободно не менее 20% памяти. Free Buffer задается именно в процентах, а не в мегабайтах, поскольку зависит от текущего потребления памяти. Значение в мегабайтах можно вычислить по формуле:

 

 

где Current Commit — суммарное потребление памяти гостевой операционной системой и всеми запущенными приложениями. Надо заметить, что формула эта верна для Windows Server 2008 RC. В бета-версии формула была немного другая, более сложная.

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

Memory Reserve

Может возникнуть такая ситуация, когда виртуальные машины потихоньку «съедят» всю память, и свободной памяти у операционной системы хоста не останется. В силу особенностей архитектуры Hyper-V нехватка памяти в базовой операционной системе может иметь неприятные последствия для всех виртуальных машин, которые на ней запущены. Чтобы этого избежать, можно задействовать параметр Memory Reserve, позволяющий зарезервировать определенный объем памяти для использования базовой операционной системой. Зарезервированный объем будет недоступен для использования виртуальными машинами. К сожалению, данный параметр нельзя изменить через настройки в графической интерфейсе, это можно сделать только через редактирование реестра. Параметр можно найти в разделе HKLM\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Virtualization, называется он MemoryReserve и имеет тип DWORD. Он определяет объем резервируемой памяти в мегабайтах. Максимальное значение — 4096, то есть 4 Гбайт. Даже если установить 8192, все равно система зарезервирует только 4 Гбайт памяти.

Работа балансировщика

Теперь посмотрим, как работает Dynamic Memory Balancer и как он определяет, кому сколько выдать и у кого сколько забрать.

Ideal Target Memory. Для каждой виртуальной машины определяется «идеальный объем памяти». Вычисляется он по формуле:

 

 

Это значение — идеал: столько, сколько нужно виртуальной машине для нормальной работы. И именно этот объем памяти система попытается ей выделить. А вот выделит ли, вопрос интересный.

Memory Pressure. Ключевой критерий — нагрузка Memory Pressure. Нагрузка — это не что иное, как отношение Ideal Target Memory к фактически выделенной памяти:

 

 

Этот параметр показывает, что именно происходит в данный момент с памятью на виртуальной машине: малые значения показывают, что памяти более чем достаточно, большие — что использование памяти подходит к пределу. Значения, превышающие 100%, говорят о том, что памяти сильно не хватает, и виртуальная машина активно использует файлы подкачки.

Pressure Band. Так когда же память нужно добавить, а когда — убрать? На основании изменений нагрузки с течением времени, по каким-то одним разработчикам известным хитрым формулам система рассчитывает максимальное и минимальное допустимые значения нагрузки, образующие диапазон — Pressure Band. До тех пор пока текущее значение нагрузки в этот диапазон укладывается, не происходит ничего, но как только выходит за рамки — мы видим следующее:

  • если нагрузка больше максимально допустимого значения — виртуальной машине добавляется память;
  • если нагрузка меньше минимально допустимого значения — излишки памяти отнимаются.

Рекомендации по использованию

Поскольку механизм Dynamic Memory задействует как компоненты базовой операционной системы, так и компоненты уровня ядра в гостевых операционных системах, список поддерживаемых операционных систем невелик. Со стороны хоста это следующие операционные системы (разумеется, с установленным SP1):

  • Microsoft Windows Server 2008 R2 редакций Standard, Enterprise, Datacenter;
  • Microsoft Hyper-V Server 2008 R2.

Гостевые операционные системы следующие (при условии установки интеграционных служб):

  • Windows Server 2003 редакций Standard, Web, Enterprise, Datacenter SP2;
  • Windows Server 2008 редакций Standard, Web, Enterprise, Datacenter SP2;
  • Windows Server 2008 R2 редакций Standard, Web, Enterprise, Datacenter SP2;
  • Windows Vista редакций Enterprise, Ultimate;
  • Windows 7 редакций Enterprise, Ultimate.

Для гостевых операционных систем Windows Server 2008 R2 и Windows 7 необходимо вместо обновления интеграционных компонентов установить SP1.

Настройка

Собственно, ничего особо сложного здесь нет — все настройки (за исключением Memory Reserve) как на ладони, что они значат — уже было описано выше (рисунок 6).

 

Рисунок 6. Настройки памяти для виртуальной машины

Подводные камни

А вот теперь я упомяну о некоторых «подводных камнях», на которые можно наткнуться при использовании Dynamic Memory.

Достаточно ли для всех Startup RAM 512 Мбайт? При запуске виртуальной машины ей выделяется объем памяти, равный значению Startup RAM. Если требуемого объема свободной памяти нет, система попытается «отобрать» память у других виртуальных машин. Сделано это будет в первую очередь, независимо от приоритета запускаемой виртуальной машины. Если набрать требуемый объем памяти все равно не удастся — виртуальная машина не запустится. Особенно важно об этом помнить при планировании отказоустойчивых кластеров: может возникнуть такая ситуация, что при обработке отказа и переносе виртуальных машин с одного узла на другой для запуска некоторых виртуальных машин не хватит памяти. Поэтому значение Startup RAM желательно устанавливать на минимум, необходимый для запуска гостевых операционных систем. И только в случае, если используются «тяжелые приложения», требующие много памяти сразу на старте, значение Startup RAM можно увеличить.

Maximum RAM. Значение Maximum RAM по умолчанию равно 64 Гбайт. Это значение можно и нужно уменьшить, если используются приложения, очень «прожорливые» в отношении памяти, или если виртуальная машина используется в тестовых целях, чтобы одна маленькая «утечка памяти» не заняла всю доступную память на сервере.

Memory Buffer & Weight. Самое главное, о чем необходимо помнить, — большой вес виртуальной машины не гарантирует того, что ей будет выделен требуемый объем памяти. Это обеспечивает лишь Free Buffer, да и он, на самом деле, не гарантирует. К примеру, у нас есть две виртуальные машины. Одна из них совсем не критична, и вес у нее установлен минимальный. Но Free Buffer у нее стоит на максимальном значении — 2000%. Другая же виртуальная машина для нас очень важна, и мы дали ей максимальный вес, но Free Buffer — минимальный — 5%. Что же произойдет? А вот что: виртуальная машина с большим Free Buffer, несмотря на свой маленький вес, заберет себе практически всю доступную память, и, когда виртуальная машина с высоким приоритетом захочет получить дополнительную память, система не сможет ей эту память выделить. Чтобы избежать подобных ситуаций, нужно грамотно выставлять значение Free Buffer и увеличивать его только тогда, когда это реально необходимо. Например, если виртуальная машина может испытывать периодические пиковые нагрузки. Или, например, если требуется некоторый объем свободной памяти для файлового кэша. Ну а если не хочется «играть с настройками», всегда можно задать статический объем памяти.

Файлы подкачки. Для работы Dynamic Memory необходим файл подкачки гостевой операционной системы. Минимальный его размер должен «перекрывать» наиболее ресурсоемкие приложения. Что это означает? Допустим, у нашей виртуальной машины остается всего 100 Мбайт свободной памяти. И указан размер файла подкачки — 100 Мбайт. Если некое приложение попытается запросить за один раз 400 Мбайт памяти, система просто не сможет столько выделить: лимит выделения всего 200 Мбайт. Если же приложение будет запрашивать два раза по 200 Мбайт, то 200 Мбайт система выделит за счет файла подкачки, в это время виртуальной машине будет выделена дополнительная память и второй раз 200 Мбайт будет выделено приложению. Поэтому минимальный размер файла подкачки должен быть таким, чтобы перекрыть и «большие запросы».

Мониторинг

Как же понять, что именно происходит с нашими виртуальными машинами? Как уже было сказано, изнутри гостевой операционной системы ничего увидеть не возможно. Увидеть можно из базовой операционной системы — через консоль Hyper-V Manager и через счетчики производительности.

Hyper-V Manager

В оснастке Hyper-V Manager имеются следующие столбцы (рисунок 7).

 

Рисунок 7. Оснастка Hyper-V Manager

 

  • Assigned Memory — сколько памяти было фактически выделено виртуальной машине.
  • Memory Demand — сколько памяти виртуальная машина запрашивает у системы (та самая Ideal Target Memory).
  • Memory Status — состояние памяти: «ОК» — все в порядке, «Warning» — памяти не вполне достаточно (Memory Demand немного больше, чем Assigned Memory), «Low» — все плохо, памяти не хватает.

Счетчики производительности

Для более детального анализа можно использовать счетчики производительности из оснастки монитора производительности Perfmon. С Dynamic Memory связаны две группы счетчиков: Hyper-V Dynamic Memory Balancer и Hyper-V Dynamic Memory VM, как показано в таблице. Первая группа относится ко всему хосту в целом, а вторая позволяет отслеживать параметры отдельных виртуальных машин.

 

Таблица. Счетчики производительности Dynamic Memory

Заключение

Итак, мы разобрали, для чего нужна Dynamic Memory, чего можно достичь с ее помощью и как с этим вообще работать. Смею надеяться, что кому-то из читателей пригодятся советы, данные в этой статье. В любом случае, если у вас возникнут какие-либо вопросы, пишите мне на lcd.admin@gmail.com.

Александр Косивченко (lcd.admin@gmail.com) — системный администратор в компании «Эльдорадо». Круг профессиональных интересов: ИТ, преимущественно технологии Microsoft, виртуализация, Hyper-V