現実の問題:HA Clusterは「順調稼働中」なのにダウンタイムが発生
去年、自分のvSphereクラスターには4台のESXiホストがあり、約60台の本番VMを稼働させていた。ある朝、1台のホストが電源障害で完全に停止した。HAが残りのホストにVMを再起動しようとしたが、8台のVMが起動できなかった。ログには「Insufficient resources to satisfy HA failover level for cluster」と記録されていた。
実はHA Clusterは正しく動作していた — Admission Controlがフェイルオーバー用にリソースを「確保」しているため、VMの起動を拒否していたのだ。しかし設定しきい値が実態に対して高すぎ、逆説的な状況が生まれていた:見た目上はクラスターにリソースが余っているのに、VMは起動をブロックされ続ける。
それだけではなかった。DRSはaggressiveに設定されており、数分ごとにVMをvMotionし続け、storage I/Oが急増していた。最も被害を受けたのはデータベースVMで、移動されるたびにlatencyの急激な悪化が顕著に見られた。
原因分析:誤解されがちな2つのメカニズム
Admission Controlとデフォルトのスロットポリシーの落とし穴
Admission Controlはシンプルなロジックで動作している:VMの追加起動を許可する前に、今この瞬間ホストが1台停止した場合に、クラスターが全VMを再起動するのに十分なCPUとRAMを持っているかチェックする。不足していれば → ブロック。理にかなっている。問題は「十分」の計算方法にある。
計算モードは3種類ある:
- Cluster resource percentage:クラスター全体のCPUとRAMの合計のX%を確保する
- Slot policy(レガシー):リソースを均等な「スロット」に分割し、N個の空きスロットを確保する
- Dedicated failover hosts:1〜2台のホストを常時スタンバイ専用とし、通常のVMは稼働させない
私の問題はデフォルトのスロットポリシーにあった。スロットサイズはクラスター内で最も高いreservationを持つVMに基づいて計算される — あるSQL Serverが32 GB RAMをreserveしていた。結果:1スロット = 32 GB RAM。60台のVMがある場合、確保すべきスロット数は膨大になり、実際にはクラスターに空きRAMが多く残っているにもかかわらず、「予備」リソースのほぼ全てを占有してしまっていた。
DRS aggressiveモード:頻繁なvMotionは常に良いわけではない
DRS(Distributed Resource Scheduler)はvMotionを使って自動的に負荷分散を行い、Migration Thresholdは1(Conservative)から5(Aggressive)まで設定できる。レベル4〜5では、わずかなimbalanceが発生しただけでDRSがVMをvMotionし、数分後に逆方向へvMotionし直すこともある。vMotionを意識していないワークロードのデータベースVMは移動するたびにlatencyが急悪化する。
Admission Control問題の解決策
方法1:Cluster resource percentage(大多数のケースに最適)
総リソースのパーセンテージで計算する方式に切り替える。シンプルな計算式:クラスターにNホストがあり1台の障害に耐える必要がある場合、1/N × 100%のリソースを確保する。4台のホストの場合:CPU 25%とRAM 25%を確保する。
# vCenterに接続
Connect-VIServer -Server vcenter.lab.local -User [email protected]
$cluster = Get-Cluster -Name "Production-Cluster"
# 現在のAdmission Control設定を確認
$cluster.ExtensionData.Configuration.DasConfig.AdmissionControlPolicy
# Percentage-basedに更新:CPU 25%、RAM 25%
$spec = New-Object VMware.Vim.ClusterConfigSpecEx
$spec.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo
$spec.dasConfig.admissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy
$spec.dasConfig.admissionControlPolicy.cpuFailoverResourcesPercent = 25
$spec.dasConfig.admissionControlPolicy.memoryFailoverResourcesPercent = 25
$spec.dasConfig.admissionControlPolicy.autoComputePercentages = $false
$cluster.ExtensionData.ReconfigureComputeResource($spec, $true)
Write-Host "Admission Control更新完了:CPU 25%、RAM 25%"
方法2:Dedicated failover host(余裕のあるホストがある場合)
計算不要で、最もシンプルな設定 — 1台のホストを通常のVM稼働には使わず、フェイルオーバー時専用に指定する。明らかな欠点:そのホストが99%の時間アイドル状態であればリソースの無駄遣いとなる。
$failoverHost = Get-VMHost -Name "esxi-04.lab.local"
$spec = New-Object VMware.Vim.ClusterConfigSpecEx
$spec.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo
$spec.dasConfig.admissionControlPolicy = New-Object VMware.Vim.ClusterFailoverHostAdmissionControlPolicy
$spec.dasConfig.admissionControlPolicy.failoverHosts = @($failoverHost.ExtensionData.MoRef)
$cluster.ExtensionData.ReconfigureComputeResource($spec, $true)
方法3:Admission Controlを無効化 — 非推奨
より「柔軟な」運用のため完全に無効化するチームもある。しかし実際のフェイルオーバーが発生した際、クラスターがVMを再起動するのに十分なリソースを持っていない可能性があり、VMは別のホストへ再起動される代わりに永続的に停止してしまう。リスクを冒す価値はない。
DRS Migration Thresholdの最適化
本番環境で数週間かけて各レベルを順番に試した結果:
- Level 1〜2:ほぼvMotionが発生せず、imbalanceが長期化。あるホストが80%稼働している一方で別のホストは30%という状態。
- Level 3:imbalanceが顕著な場合(差異12%超)にのみvMotionを実行。大半のワークロードに適している。
- Level 4〜5:vMotionが頻発し、storage I/Oが高くなり、DB VMに影響が出る。
Level 3が最も良いバランスポイントだ。さらに重要なのは、DRSが勝手に移動しないようにデータベースVMに対してVM Overrideを設定することだ:
# latency敏感なVMにDRS Manualを設定
$vm = Get-VM -Name "sql-server-01"
$clusterSpec = New-Object VMware.Vim.ClusterConfigSpecEx
$vmOverride = New-Object VMware.Vim.ClusterDrsVmConfigSpec
$vmOverride.operation = [VMware.Vim.ArrayUpdateOperation]::add
$vmOverride.info = New-Object VMware.Vim.ClusterDrsVmConfig
$vmOverride.info.key = $vm.ExtensionData.MoRef
$vmOverride.info.enabled = $true
$vmOverride.info.behavior = [VMware.Vim.DrsBehavior]::manual
$clusterSpec.drsVmConfigSpec = @($vmOverride)
$cluster.ExtensionData.ReconfigureComputeResource($clusterSpec, $true)
Write-Host "$($vm.Name): DRS Manualに設定 — 自動vMotionは行われません"
最善策:両方を組み合わせて定期的に監視する
6ヶ月間安定稼働した後の最終設定:
- Admission Control:Percentage-based、CPU 25% + RAM 25%
- DRS Level:3(Balanced)
- データベースVM:DRS Manual override
overloadが始まったホストを早期検知するためのヘルスチェックスクリプト(毎日実行):
# health-check-cluster.ps1
Connect-VIServer -Server vcenter.lab.local -User [email protected] -Password $env:VCENTER_PASS
$cluster = Get-Cluster -Name "Production-Cluster"
$hosts = Get-VMHost -Location $cluster
Write-Host "=== Cluster Health Check ===" -ForegroundColor Cyan
Write-Host "HA: $($cluster.HAEnabled) | DRS: $($cluster.DrsEnabled)"
foreach ($vmhost in $hosts) {
$cpuPct = [math]::Round(($vmhost.CpuUsageMhz / $vmhost.CpuTotalMhz) * 100, 1)
$memPct = [math]::Round(($vmhost.MemoryUsageMB / $vmhost.MemoryTotalMB) * 100, 1)
$warn = if ($cpuPct -gt 80 -or $memPct -gt 85) { "[WARN]" } else { "[OK] " }
Write-Host "$warn $($vmhost.Name) | CPU: $cpuPct% | RAM: $memPct%"
}
# HA再起動が無効化されたVMを確認
$dasConfigs = $cluster.ExtensionData.Configuration.DasVmConfig
$disabledCount = ($dasConfigs | Where-Object { $_.DasSettings.RestartPriority -eq 'disabled' }).Count
Write-Host "`nHA再起動が無効化されたVM数:$disabledCount"
Proxmox HAとのクイック比較
その後、個人用ラボでProxmoxを使ったが、すぐ目についたのは:Admission Controlがなく、DRSもない。HAグループを作成してVMを追加するだけで完了。はるかにシンプルで、細かい制御が不要なラボや小規模SMBに向いている。
VMwareが優れているのは、VMを特定のホストに固定し、reservationとlimitを設定した上でDRSにその枠内で最適化させられる点だ。一方、Proxmoxはvisibilityで勝っている — HAログが明確で、VMの再起動に失敗した際のデバッグが容易だ。vSphereのイベントログを漁るのは…楽しい体験とは言えない。
要約すると必要な変更は2つだけだ:reservationの高いVMがクラスターに存在する場合は、Admission ControlをデフォルトのSlot Policyのままにせず、1/N × 100%のしきい値でPercentage-basedに切り替える。そしてlatency敏感なワークロードにはManual overrideを付けたDRS Level 3を設定する。この2つで、本来発生すべきでないインシデントをかなり防ぐことができる。
