Короткий ответ

Сначала разделите три вещи: (1) dynamic VHDX дорос до своего максимума (Size в Get-VHD), (2) рядом лежит цепочка .avhdx от checkpoint/backup, (3) забиты логи/ISO/хостовый dump, а не диск гостя. На C:\ClusterStorage\Volume1 удаление «большого vhdx» в Explorer — это уничтожение VM-APP01.

Compact (Optimize-VHD) не освободит том, пока внутри гостя не обнулили свободное место и пока висят checkpoint. Compact на работающей VM или на differencing — путь к порче.

Симптомы и как отличить

Типичная картина:

  • CSV Volume1 красный, VM падают в Saved;
  • в каталоге VM файл VM-APP01.vhdx + несколько *.avhdx;
  • в госте «диск C: свободен», на хосте файл всё равно большой — так и должен dynamic после записи;
  • backup породил production checkpoint и не слил.

Отличия:

Что видноКуда
Нужно штатно сжать после очистки гостяуменьшить VHDX
Delete checkpoint не идётcheckpoint
Диск не цепляетсяVHDX не подключается
Latency, не местонагрузка диска

Возможные причины

  1. Dynamic диск с потолком 2 ТБ на томе 800 ГБ: гость записал данные, файл догнал том.
  2. Checkpoint/Replica/backup оставили AVHDX; сумма цепочки > свободного места.
  3. Забыли ISO, export, старые копии VM-APP01-copy.vhdx на том же CSV.
  4. Smart paging / Saved State .bin разрослись при нехватке RAM.
  5. Hyper-V Replica initial copy на тот же том.
  6. Fixed VHDX изначально занял Size целиком — это не «рост», это тип диска.

Диагностика

Get-Volume | Format-Table DriveLetter, FileSystemLabel, FileSystem, @{N='FreeGB';E={[math]::Round($_.SizeRemaining/1GB,1)}}, @{N='SizeGB';E={[math]::Round($_.Size/1GB,1)}}
Get-ChildItem -Path 'C:\ClusterStorage\Volume1' -Recurse -ErrorAction SilentlyContinue |
  Sort-Object Length -Descending | Select-Object -First 30 FullName, @{N='GB';E={[math]::Round($_.Length/1GB,2)}}

По VM:

Get-VMHardDiskDrive -VMName 'VM-APP01' | ForEach-Object {
  Get-VHD -Path $_.Path | Select-Object Path, VhdType, @{N='FileGB';E={[math]::Round($_.FileSize/1GB,2)}}, @{N='MaxGB';E={[math]::Round($_.Size/1GB,2)}}, ParentPath
}
Get-VMCheckpoint -VMName 'VM-APP01'
Get-ChildItem 'C:\ClusterStorage\Volume1\VM-APP01' -Filter *.avhdx

VhdType : Differencing + ParentPath — вы смотрите не на «раздутый базовый диск», а на overlay. Место ест overlay + родитель.

Реплика и backup:

Get-VMReplication -VMName 'VM-APP01' -ErrorAction SilentlyContinue
Get-VM -Name 'VM-APP01' | Format-List CheckpointFileLocation, SnapshotFileLocation, SmartPagingFilePath

Решение

Сценарий A. Мусор на CSV, не диск гостя

Удалите ISO, старые Export, Copy of VM-APP01.vhdx, дампы MEMORY.DMP хоста. Не трогайте текущий Path из Get-VMHardDiskDrive.

Сценарий B. Checkpoint / AVHDX

Штатно удалите ненужные checkpoint в Hyper-V / Failover Cluster — это запустит merge. Дождитесь Get-StorageJob / исчезновения лишних avhdx. Если merge не идёт — статьи про checkpoint и AVHDX, не Disk Cleanup.

Production checkpoint от backup, который «залип»: дождитесь окончания job или разберите writer; не сносите recovery snapshot из Explorer.

Сценарий C. Dynamic дорос до Size, том хоста кончился

Варианты, не взаимозаменяемые:

  1. Расширить CSV/том (хранилище), если гостю данные нужны.
  2. Перенести VM на больший том (Move-VMStorage).
  3. В госте почистить данные, затем сжать VHDX в окно простоя — только после backup.
  4. Не «увеличить Size» если физически том меньше нового максимума — получите мгновенный 0 байт при следующей записи.

Расширение логического диска без места на CSV бессмысленно. Сначала хранилище, потом Resize-VHD.

Сценарий D. Saved State и paging

Перенесите SmartPagingFilePath на том с местом или освободите RAM (не держите десяток VM в Saved). Delete Saved State — только с пониманием потери памяти гостя.

Сценарий E. Fixed диск «съел всё с первого дня»

Это норма FileSize = Size. Лечение — другой том или конвертация в dynamic с местом и backup, не compact fixed тем же смыслом что dynamic.

Get-VHD -Path 'C:\ClusterStorage\Volume1\VM-APP01\VM-APP01.vhdx' | Format-List VhdType, FileSize, Size

Как проверить, что проблема устранена

Get-Volume -FileSystemLabel 'Volume1' | Format-List SizeRemaining, Size
Get-VHD -Path 'C:\ClusterStorage\Volume1\VM-APP01\VM-APP01.vhdx' | Format-List FileSize, Size, VhdType, ParentPath
Get-VM -Name 'VM-APP01' | Format-List State
Get-VMCheckpoint -VMName 'VM-APP01'

Свободные гигабайты на CSV с запасом под рост и merge. VM Running. Лишних checkpoint нет, либо они осознанные. Гость пишет данные без паузы Hyper-V «not enough space».

Если не помогло

  • Место освободили, VM всё равно не стартует: старт.
  • После compact гость в RAW: вы сжимали с checkpoint или без обнуления — restore из backup, не chkdsk хоста по VHDX.
  • Replica забивает второй том: ограничьте initial replication расписанием, не тем же CSV что прод-IO.
  • SQL в госте пишет тоннами в dynamic: планируйте Size и мониторинг FileSize, не «поставили 4 ТБ на всякий».

Профилактика

  • Алерт на свободное место CSV и на FileSize/Size ratio.
  • Запрет долгих production checkpoint.
  • Dynamic потолок не больше осмысленного объёма тома.
  • Отдельный том под Replica/backup.
  • Регулярный отчёт Get-VHD по всем VM на HV01.

FAQ

Почему в госте удалили 100 ГБ, а на хосте файл не уменьшился?

Dynamic VHDX не сжимается от Delete в NTFS гостя. Нужны обнуление свободного места и Optimize-VHD при Off, см. сжатие VHDX.

Можно ли Convert в dynamic на месте чтобы освободить?

Convert пишет новый файл. Нужно свободное место ≈ размера данных. На забитом томе Convert не старт, а финиш.

Checkpoint «на час» опасен для места?

Да. Overlay растёт со скоростью записи гостя. На busy SQL час — десятки гигабайт AVHDX плюс место под последующий merge.

Thin на SAN и dynamic VHDX — двойной thin?

Да, и оба могут внезапно закончиться. Мониторьте и SAN, и FileSize.

Стоит ли сразу ставить Fixed?

Предсказуемое место, хуже по начальному занятому объёму. Для прод-БД часто Fixed или dynamic с потолком и алертом. Не догма.

Удалить $Recycle.Bin на CSV?

Корзина хоста может держать гигабайты. Очистка Recycle Bin хоста на CSV допустима, если это не единственная копия VHDX. Не путать с удалением файлов VM.