Pull to refresh

Xen Cloud Platform в условиях предприятия [3]

Virtualization *
Третья часть. Предыдущие части: Первая, вторая.

В этой теме: управление памятью и процессорами виртуальных машин.

Память


Для того, чтобы понять, как XCP работает с памятью, нужно понять, как с ней работает Xen. В отличие от OpenVZ, Xen всегда выделяет память виртуальной машине (точнее, домену) в монопольное пользование. Память домена — это память домена и только. Никакого оверселла, никаких shared pages, никакого hypervizor swap (виртуальные машины свопиться, разумеется, могут). Если у вас есть 4Гб, то примерно 3.5Гб вы можете разделить между гостевыми машинами (512 уйдёт на dom0). Как вы будете их делить — ваша свобода. Но дать машине больше памяти, чем есть в наличии вы не сможете. Нет. Точка.

Зато в управлении реально выделенной памятью всё очень хорошо. В Xen 3.4 механизм управления памятью (xenballoon) основан на довольно сложной для восприятия мозгом, но простой с точки зрения гипервизора, основе: страницы памяти передаются (transfer) между доменом и гипервизором. Передача означает, что у передающего памяти становится меньше, а у принимающего — больше. Этот механизм использует не только xenballoon, но и многие драйвера (чтобы не делать копирования, они просто передают страницы с данными друг другу), но только xenballoon им злоупотребляет в таких объёмах. Сам balloon работает именно так, как звучит его название — он «надувается» внутри домена, отдавая занятое место гипервизору. Когда домену отдают память, то шарик сдувается.

Управление памятью не бесплатное, оно берёт немного памяти домена на служебные расходы себе. В худшем случае это порядка 5%, чем больше памяти, тем меньший процент (к 16Гб памяти величина падает примерно до 1%).

Существуют два сценария управления памятью: добавление памяти в запущенную машину и удаление памяти из запущенной машины. С удалением всё просто — xenballoon отдаёт страницы гипервизору. С добавлением сложнее — ядро на самом деле не может расширять своё адресное пространство (в Xen 3.4 memory hotplug ещё не поддерживался), так что реализуется эта схема чуть иначе: при создании домена часть страниц помечается как выделенные домену и тут же отданные назад, гипервизору (т.е. balloon считается заранее надутым), а в нужный момент времени гипервизор возвращает страницы назад домену.

В силу этой модели существует теоретический потолок (задаваемый при создании домена, т.е. при старте виртуальной машины), до которого можно наращивать виртуальную память. Он влияет на размер служебных расходов, и искусственно ограничивает нижнюю границу памяти (для 16Гб это примерно 512Мб, для 2Гб, кажеся, 128Мб). Таким образом, мы получаем две границы, задаваемые при запуске домена — memory_static_min и memory_static_max. Не смотря на то, что пользователь может memory_static_min делать сколь угодно низким, величина памяти никогда не опустится ниже некоторой величины, высчитываемой из максимума. Это закодировано прямо в коде xenballloon.c и служит для защиты от OOM killer'а на ровном месте (чтобы было достаточно памяти для служебных данных ядра и минимального набора ПО для функционирования). В некоторых местах он слишком агрессивно задирает планку (особенно, в районе потолка в 2-4Гб), но в общем и целом, величины вполне разумные.

Дополнительно к этим ограничениям вводятся ещё две (искуственные) величины — memory_dynamic_max и memory_dynamic_min. Эти величины определяют границы, в которых можно регулировать память и могут меняться на ходу (т.е. это просто административная условность). Так же есть величина target (memory_target) — желаемый объём памяти. Чаще всего объём памяти делется таким, который нужен (т.е. memory=memory_target), но если запрос на target не может быть выполнен, то эти величины могут отличаться.

Существует два метода регуляции объёмов памяти виртуальной машины — ручной и автоматический. Ручной выставляет target в заданную величину. Автоматический задаёт границы (максимум/минимум) и предоставляет XCP возможность самому регулировать объём памяти каждого домена.

Регуляция памяти называется Dynamic Memory Control и представляет собой демон squeezed, работающий на каждом хосте пула (никакого отношения к Debian Squeeze не имеет, просто совпадение). Этот демон выделяет новым доменам максимум доступной памяти (но не более dynamic-max), а в случае потребности гипервизора в памяти (например, для запуска новой виртуальной машины) поджимает все машины (но не менее dynamic-min). Если squeezed не сумел освободить нужный объём памяти, то хост отказывается запускать новую виртуальную машину (если запуск осуществляется командой xe vm-start без указания где именно запускать, то машина запустится там, где получится, если будет указано «запустить тут», то будет отказ в запуске).

На ходу можно менять величины dynamic-min/max, разумеется, в пределах доступного. При смене величин возможность изменения не проверяется, и можно получить машину, у которой memory=512Mb, dynamic-min=2GiB, target=4GiB, dynamic-max=8GiB. (при перезагрузке, если условия нельзя выполнить, машина не запустится).

В любом случае для памяти при каждом изменении проверяется формула:

static-min ≤ dynamic_min ≤ target ≤ dynamic_max ≤ static-max


Процессор(ы)


Xen поддерживает динамическое подключение/отключение процессоров. (И да, отвечая на вопросы из комментариев — ядер может быть больше 4, лично я видел 16 ядер у одной виртуалки, число процессоров не лимитируется). По-умолчанию все машины делаются с одним процессором, для включения многопроцессорности их нужно выключить. Есть три величины, определяющие поведение:
  • VCPUs-max — максимальное число процессоров для домена (задаётся при создании домена, то есть при включении виртуальной машины).
  • VCPUs-number — текущее количество процессоров
  • VCPUs-at-startup — Количество процессоров при включении машины (создании домена)

Нужно сказать, что Xen нагло мухлюет, и никакого подключения процессоров на ходу он не умеет делать. На самом деле в виртуальную машину включается VCPUs-max процессоров, просто часть из них помечается выключенным. Таким образом, подключение/отключение процессоров это не их hotplug с точки зрения ОС, а просто «enable/disable». Впрочем, это не уменьшает сложности задачи для гостевых систем по смене числа процессоров, участвующих в планировании процессов. Некоторые программы бесятся от смены числа процесссоров (наиболее характерный — atop, который при подключении пары процессоров начинает считать, что они были всегда, но их «украл» гипервизор). Большинству же программ пофигу — ибо они не думают о числе процессоров. У «подключенных, но выключенных» процессоров есть небольшое пенальти — ядро всё-таки про них знает и резервирует память по количеству VCPUs-max ядер, а не по числу включенных.

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

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

Между друг другом виртуальные машины могут иметь лимиты на процессор и относительные приоритеты.

Лимит задаётся в виде величины cap, задающей в процентах максимальное разрешённое машинное время на каждый процессор (внимание, на каждое ядро, cap = 75% при двух ядрах это 150% машинного времени, в некоторой документации говорят о том, что cap — это суммарное потребление машины, то есть cap=150, cap=330 и т.д. — это неверно). cap=10 даст нам 10% машинного времени и превратит мощный Xeon в весьма прискорбный P2 (а то и P1), особенно остро это ощущается на этапе загрузки. В принципе, снижать cap ниже 25% не стоит, ибо машина может начать подтупливать даже в консольке (с развесистым bash competition запросто).

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

Соотношение строгое — машина с weight=20 получает не менее чем в два раза больше машинного времени, чем машина с weight=10 (при наличии желания потребить это машинное время, если «приоритетная» машина простаивает, то низкоприоритетная может есть сколько хочет). Числа эти спокойно масштабируются до десятков тысяч (т.е. может быть машина с weight=20000 и weight=1, в этом случае вторая, фактически, работает в idle приоритете).

Важно: все приоритеты, к сожалению, можно менять только при остановке домена.

Для особо тонких ценителей копания в потрохах предусмотрена возможность назначения виртуальной машине специфичных ядер (т.н. VCPU-pinning) и возможность маскирования (отключения) части возможностей процессора (VPCU-features).

Увидеть реальную ситуацию с виртуальными машинами можно с помощью xentop.
Tags:
Hubs:
Total votes 31: ↑28 and ↓3 +25
Views 3.8K
Comments Comments 25