Повышение доступности кластеров – эвакуация виртуальных машин при перезагрузке

Кластеризация виртуальных машин повышает их доступность. Технология Live Migration позволяет администратору планово перенести виртуальную машину с одного узла на другой без потери соединений к данной машине. SCVMM 2008 R2 позволяет администратору включить для узла режим обслуживания, что по очереди перенесёт все виртуальные машины на другие узлы, динамически распределив их в зависимости от текущей нагрузки на узлах кластера.

Это звучит замечательно, когда вы планируете сами перенести виртуальную машину или перезагрузить сервер виртуализации. Если вы, не предприняв особых действий, захотите перезагрузить узел кластера, то все виртуальные машины на этом узле сохранят своё состояние на жесткий диск и переедут на другие узлы при остановке службы кластера. По сути, можно сказать, что будет использоваться Quick Migration для данных машин с временем её недоступности от 30 до 90 секунд. Это уже не всегда приемлемо для продуктивных систем, так что администраторы пытаются по возможности не перезагружать узлы виртуализации. Вам интересно, как повысить доступность ваших виртуальных машин, настроив операционную систему на эвакуацию виртуальных машин при перезагрузке и выключении сервера виртуализации? Рассмотрим небольшой пример.

Небольшой скрипт PowerShell, который мы добавим в локальную или доменную политику на сервере виртуализации выполнит эвакуацию всех виртуальных машин при выключении или перезагрузке:

Сценарий PowerShell Evac-VMs.ps1

ImportSystemModules

$Computer = Get-Content env:ComputerName

Suspend-ClusterNode $Computer

$AvailNodes = (get-clusternode | Where-Object { $_.State -eq "Up" -and $_.Name -ne "$Computer" })

$i = 0

$VMGroups = Get-ClusterNode $Computer| Get-ClusterGroup | ?{ $_ | Get-ClusterResource | ?{ $_.ResourceType -like "Virtual Machine" } }

foreach ( $VMGroup in $VMGroups ) {

Move-ClusterVirtualMachineRole "$VMGroup" -Node $AvailNodes[$i].Name

$i = $i + 1

if ($i -eq $AvailNodes.Count) { $i = 0 }

}

Resume-ClusterNode $Computer

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

Далее мы составляем список всех доступных узлов нашего кластера. Получаем список всех групп виртуальных машин, запущенных на нашем узле и начинаем поочередно переносить их на другие узлы кластера используя Live Migration.

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

Имея данный скрипт, например в C:\Scripts\Evac-VMs.PS1 на каждом узле кластера, нам требуется сделать еще один шаг, чтобы скрипт мог выполняться. Есть два варианта:

  1. Подписать данный скрипт. Понадобится иметь Code Signing сертификат, возможно, самостоятельно сгенерированный на этом узле. Далее выполнить подписание: $cert = @(gci cert:\currentuser\CodeSigningCert)[0]; Set-AuthenticodeSignature Evac-VMs.ps1 $cert)
  2. Разрешить неограниченное исполнение неподписанных скриптов: Set-ExecutionPolicy -ExecutionPolicy Unrestricted

На самом деле PowerShell скрипты, исполняемые групповыми политиками не требуют обязательного подписания, поскольку всегда запускаются в неограниченной политике исполнения. При этом я всё-таки рекомендую вам подписывать скрипты, чтобы вы могли их вручную протестировать и быть уверенными, что они не были изменены после подписания.

В итоге нам остается добавить данный скрипт в локальную или доменную политику, определяющую скрипты, исполняющиеся при выключении/перезагрузке. Для этого в редакторе политик откроем раздел Computer Configuration\Windows Settings\Scripts:

В настройке Shutdown выберем закладку PowerShell Scripts (не перепутайте) и укажем, что они запускаются первыми:

Укажем путь до нашего скрипта:

К заметке прилагается неподписанный пример скрипта. Если у вас есть комментарии или идеи по оптимизации, буду рад их услышать.