Hyper-V ile Sanal Makine Oluşturma ve Yönetme

Hyper-V ortamında sanal makine yönetimi, çoğu sysadmin’in GUI üzerinden yapmaya alışık olduğu bir iş. Ama gerçek şu ki, Hyper-V Manager’a tıkla-tıkla derken saatlerce harcadığın zamanı, PowerShell ile birkaç dakikaya indirebilirsin. Üstelik onlarca makineyi tek seferde yönetmek, tekrarlayan görevleri otomatize etmek ve scriptleri CI/CD pipeline’larına entegre etmek istiyorsan, PowerShell’den başka seçeneğin yok. Bu yazıda sıfırdan sanal makine oluşturmaktan başlayıp, snapshot yönetimi, network konfigürasyonu ve toplu işlem senaryolarına kadar Hyper-V’yi PowerShell ile nasıl yöneteceğini detaylıca anlatacağım.

Hyper-V PowerShell Modülü Kurulumu

Başlamadan önce Hyper-V PowerShell modülünün sistemde yüklü olduğundan emin olman lazım. Windows Server üzerinde genellikle otomatik gelir ama kontrol etmek iyi alışkanlık.

# Modülün yüklü olup olmadığını kontrol et
Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Management-PowerShell

# Yoksa kur
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Management-PowerShell

# Windows Server üzerinde
Install-WindowsFeature -Name Hyper-V-PowerShell

# Mevcut Hyper-V komutlarını listele
Get-Command -Module Hyper-V | Measure-Object

Modül kurulduktan sonra Get-Command -Module Hyper-V ile 200’den fazla komutun seni beklediğini göreceksin. Hepsini ezberlemeye gerek yok, sık kullandıklarını zamanla öğrenirsin. Ama temel olanları bilmek şart.

Sanal Switch Oluşturma

Sanal makine oluşturmadan önce network altyapısını hazırlamak gerekiyor. Fiziksel bir sunucuya ağ kablosu takmadan önce switch’i kurmak gibi düşün.

# Mevcut sanal switchleri listele
Get-VMSwitch

# External switch oluştur (fiziksel ağa bağlantı için)
New-VMSwitch -Name "Production-External" -NetAdapterName "Ethernet" -AllowManagementOS $true

# Internal switch oluştur (VM'ler arası iletişim + host erişimi)
New-VMSwitch -Name "Internal-Lab" -SwitchType Internal

# Private switch oluştur (sadece VM'ler arası, host erişimi yok)
New-VMSwitch -Name "Private-Isolated" -SwitchType Private

# Switch detaylarını görüntüle
Get-VMSwitch -Name "Production-External" | Format-List *

Hangi switch tipini kullanacağına karar verirken şunu düşün: Production ortamında dışarıya çıkması gereken makineler için External, test ortamında birbirleriyle konuşan ama dışarıya çıkmaması gereken makineler için Private kullan. Internal ise host makineyle de konuşması gereken test senaryoları için ideal.

İlk Sanal Makineyi Oluşturma

Şimdi asıl konuya gelelim. Temel bir sanal makine oluşturmak için New-VM cmdlet’ini kullanıyoruz.

# Temel Windows Server VM oluşturma
New-VM -Name "WEB-SERVER-01" `
       -MemoryStartupBytes 4GB `
       -Generation 2 `
       -NewVHDPath "D:VMsWEB-SERVER-01WEB-SERVER-01.vhdx" `
       -NewVHDSizeBytes 80GB `
       -Path "D:VMsWEB-SERVER-01" `
       -SwitchName "Production-External"

# CPU core sayısını ayarla
Set-VMProcessor -VMName "WEB-SERVER-01" -Count 4

# Dynamic memory aktif et
Set-VMMemory -VMName "WEB-SERVER-01" `
             -DynamicMemoryEnabled $true `
             -MinimumBytes 2GB `
             -StartupBytes 4GB `
             -MaximumBytes 8GB

# ISO'yu DVD sürücüsüne bağla
Add-VMDvdDrive -VMName "WEB-SERVER-01" `
               -Path "C:ISOWindowsServer2022.iso"

# Secure Boot ayarla (Generation 2 için)
Set-VMFirmware -VMName "WEB-SERVER-01" `
               -SecureBootTemplate MicrosoftWindows

# Boot sırasını ayarla (DVD'den boot et)
$dvd = Get-VMDvdDrive -VMName "WEB-SERVER-01"
Set-VMFirmware -VMName "WEB-SERVER-01" -FirstBootDevice $dvd

Generation 2 mi Generation 1 mi sorusu sıkça karşıma çıkıyor. Eğer kurulum yapacağın OS Windows Server 2012 veya üzeriyse ya da modern bir Linux dağıtımıysa, kesinlikle Generation 2 kullan. Daha hızlı boot süresi, UEFI desteği ve daha iyi disk performansı elde edersin. Eski OS’ler için Generation 1 mecburiyet.

VM’i Başlatma ve Temel Yönetim

# VM'i başlat
Start-VM -Name "WEB-SERVER-01"

# VM durumunu kontrol et
Get-VM -Name "WEB-SERVER-01" | Select-Object Name, State, CPUUsage, MemoryAssigned

# Tüm VM'lerin durumunu listele
Get-VM | Select-Object Name, State, CPUUsage, MemoryAssigned, Uptime | Format-Table -AutoSize

# VM'i güvenli şekilde kapat (OS'e shutdown komutu gönderir)
Stop-VM -Name "WEB-SERVER-01" -Force:$false

# VM'i zorla kapat (güç kablosunu çekmeye eşdeğer, dikkatli kullan)
Stop-VM -Name "WEB-SERVER-01" -Force

# VM'i yeniden başlat
Restart-VM -Name "WEB-SERVER-01" -Force

# VM'i duraklat (Pause)
Suspend-VM -Name "WEB-SERVER-01"

# Duraklatılmış VM'i devam ettir
Resume-VM -Name "WEB-SERVER-01"

Gerçek dünya senaryosunda Stop-VM -Force kullanmaktan mümkün olduğunca kaçın. Özellikle SQL Server veya Exchange çalıştıran makinelerde ani kapanma veri bütünlüğünü bozabilir. Önce Shutdown-VM veya OS içinden kapamayı dene, olmuyorsa Force’a geç.

Snapshot (Checkpoint) Yönetimi

Snapshot yönetimi, Hyper-V’nin en çok kullanılan özelliklerinden biri. Özellikle patch uygulamadan veya büyük bir değişiklik yapmadan önce snapshot almak can kurtarıcı.

# Checkpoint oluştur
Checkpoint-VM -Name "WEB-SERVER-01" -SnapshotName "Pre-Patch-$(Get-Date -Format 'yyyy-MM-dd')"

# Tüm checkpointleri listele
Get-VMCheckpoint -VMName "WEB-SERVER-01"

# Belirli bir checkpoint'e geri dön
$checkpoint = Get-VMCheckpoint -VMName "WEB-SERVER-01" -Name "Pre-Patch-2024-01-15"
Restore-VMCheckpoint -VMCheckpoint $checkpoint -Confirm:$false

# VM'i restore ettikten sonra başlat
Start-VM -Name "WEB-SERVER-01"

# Checkpoint'i sil (işe yaramadıysa veya production'a aldıysan)
Remove-VMCheckpoint -VMName "WEB-SERVER-01" -Name "Pre-Patch-2024-01-15"

# Tüm checkpointleri temizle (disk alanı kurtarma)
Get-VMCheckpoint -VMName "WEB-SERVER-01" | Remove-VMCheckpoint

Bir uyarı: Snapshot’ları uzun süre tutmak disk I/O performansını ciddi etkiler. Ben genellikle şu kuralı uygularım: Patch veya değişiklik başarılıysa 24-48 saat içinde snapshot’ı sil. Production ortamında 7 günden uzun yaşayan snapshot görürsem alarm zilleri çalmaya başlar.

Toplu Sanal Makine Oluşturma Senaryosu

Gerçek dünyada tek tek VM oluşturmak yerine, bir template’den veya hazır parametrelerden onlarca makine oluşturman gerekebilir. İşte bunun için pratik bir script:

# Toplu VM oluşturma scripti
$VMConfigs = @(
    @{Name="WEB-01"; RAM=4GB; CPU=2; Disk=80GB; Switch="Production-External"},
    @{Name="WEB-02"; RAM=4GB; CPU=2; Disk=80GB; Switch="Production-External"},
    @{Name="DB-01";  RAM=16GB; CPU=8; Disk=200GB; Switch="Production-External"},
    @{Name="APP-01"; RAM=8GB; CPU=4; Disk=100GB; Switch="Production-External"}
)

$BasePath = "D:VMs"
$ISOPath = "C:ISOWindowsServer2022.iso"

foreach ($Config in $VMConfigs) {
    $VMPath = "$BasePath$($Config.Name)"
    $VHDPath = "$VMPath$($Config.Name)-OS.vhdx"
    
    Write-Host "Olusturuluyor: $($Config.Name)" -ForegroundColor Green
    
    # Klasor olustur
    New-Item -ItemType Directory -Path $VMPath -Force | Out-Null
    
    # VM olustur
    New-VM -Name $Config.Name `
           -MemoryStartupBytes $Config.RAM `
           -Generation 2 `
           -NewVHDPath $VHDPath `
           -NewVHDSizeBytes $Config.Disk `
           -Path $VMPath `
           -SwitchName $Config.Switch
    
    # CPU ayarla
    Set-VMProcessor -VMName $Config.Name -Count $Config.CPU
    
    # Dynamic memory
    Set-VMMemory -VMName $Config.Name `
                 -DynamicMemoryEnabled $true `
                 -MinimumBytes ($Config.RAM / 2) `
                 -MaximumBytes ($Config.RAM * 2)
    
    # ISO ekle
    Add-VMDvdDrive -VMName $Config.Name -Path $ISOPath
    
    # Boot sirasi
    $dvd = Get-VMDvdDrive -VMName $Config.Name
    Set-VMFirmware -VMName $Config.Name -FirstBootDevice $dvd
    
    Write-Host "$($Config.Name) basariyla olusturuldu." -ForegroundColor Cyan
}

Write-Host "Tum VM'ler olusturuldu!" -ForegroundColor Yellow
Get-VM | Select-Object Name, State | Format-Table

Bu scripti bir CSV dosyasından okuyacak şekilde genişletebilirsin. Büyük deployment’larda Excel’den export alınan CSV ile 50 VM’i 5 dakikada oluşturduğumu gördüm. Tıkla-tıkla yapsan saatlerin gider.

Disk Yönetimi ve VHD İşlemleri

VM’lere ek disk ekleme ve mevcut diskleri yönetme günlük işlerin önemli bir parçası.

# Mevcut VM disklerini listele
Get-VMHardDiskDrive -VMName "DB-01"

# Yeni VHD oluştur ve VM'e ekle
New-VHD -Path "D:VMsDB-01DB-01-Data.vhdx" `
        -SizeBytes 500GB `
        -Dynamic

Add-VMHardDiskDrive -VMName "DB-01" `
                    -Path "D:VMsDB-01DB-01-Data.vhdx" `
                    -ControllerType SCSI

# Mevcut diski genislet (VM kapaliyken)
Stop-VM -Name "DB-01" -Force
Resize-VHD -Path "D:VMsDB-01DB-01-Data.vhdx" -SizeBytes 1TB
Start-VM -Name "DB-01"

# VHD bilgilerini görüntüle
Get-VHD -Path "D:VMsDB-01DB-01-Data.vhdx" | Select-Object Path, VhdType, Size, FileSize

# Dynamic VHD'yi Fixed'a dönüştür (production için önerilir)
Convert-VHD -Path "D:VMsDB-01DB-01-Data.vhdx" `
            -DestinationPath "D:VMsDB-01DB-01-Data-Fixed.vhdx" `
            -VHDType Fixed

Production veritabanı sunucularında dynamic VHD yerine fixed VHD kullanmayı tercih ederim. Dynamic’in anlık büyüme sırasında yaşadığı I/O spike’ları SQL Server gibi hassas uygulamalarda sorun çıkarabilir. İlk kurulumda disk alanı tahsisatı yapmak uzun vadede daha az baş ağrısı demek.

Network Adaptör Yönetimi

VM’lere birden fazla network kartı eklemek veya mevcut adaptörleri yapılandırmak için:

# VM'in network adaptörlerini listele
Get-VMNetworkAdapter -VMName "DB-01"

# Yeni network adaptör ekle
Add-VMNetworkAdapter -VMName "DB-01" -SwitchName "Private-Isolated" -Name "DB-Replication"

# VLAN yapılandır
Set-VMNetworkAdapterVlan -VMName "DB-01" `
                         -VMNetworkAdapterName "DB-Replication" `
                         -Access `
                         -VlanId 100

# Bandwidth limiti koy (MB cinsinden)
Set-VMNetworkAdapter -VMName "WEB-01" `
                     -MaximumBandwidth 1000000000 `
                     -MinimumBandwidthAbsolute 500000000

# MAC adresini statik yap
Set-VMNetworkAdapter -VMName "WEB-01" `
                     -StaticMacAddress "00-15-5D-01-02-03"

# Network adaptörü kaldır
Remove-VMNetworkAdapter -VMName "DB-01" -Name "DB-Replication"

VLAN yapılandırması özellikle multi-tenant ortamlarda veya segment’lere ayrılmış ağ altyapılarında kritik. Her VM’e doğru VLAN ID’yi atamak, fiziksel switch üzerinde de buna göre trunk port ayarı yapmak gerekiyor. Bunu unutup neden bağlanamıyorum diye saatler geçirenlerden biri oldum, bir kez yaşaman yeter.

VM Dışa Aktarma ve İçe Aktarma

VM’leri başka bir Hyper-V host’a taşıma veya yedekleme senaryoları için export/import işlemleri çok işe yarıyor.

# VM'i export et (VM durdurulabilir veya çalışıyor olabilir)
Export-VM -Name "WEB-SERVER-01" -Path "E:BackupVMExports"

# Çalışan VM'i export et (Live Export)
# Not: VM durdurulmadan export edilir ama biraz daha uzun sürer
Export-VM -Name "WEB-SERVER-01" -Path "E:BackupVMExports" -CaptureLiveState

# Export edilen VM'i import et
Import-VM -Path "E:BackupVMExportsWEB-SERVER-01Virtual Machines*.vmcx"

# Yeni ID ile import et (aynı host'a kopyalamak için)
Import-VM -Path "E:BackupVMExportsWEB-SERVER-01Virtual Machines*.vmcx" `
          -GenerateNewId `
          -Copy `
          -VhdDestinationPath "D:VMsWEB-SERVER-01-Copy" `
          -VirtualMachinePath "D:VMsWEB-SERVER-01-Copy"

DR (Disaster Recovery) senaryolarında export/import yerine Hyper-V Replica kullanmak daha mantıklı. Ama bazen bir VM’i hızlıca başka ortama taşıman gerekiyorsa export/import en pratik yol.

Kaynak İzleme ve Performans Takibi

Sistemi izlemek, sorunları önceden yakalamak için şart:

# Tum VM'lerin anlık durum ozeti
Get-VM | Select-Object Name, State, CPUUsage, `
    @{N="RAM(GB)";E={[math]::Round($_.MemoryAssigned/1GB,2)}}, `
    @{N="Uptime";E={$_.Uptime}} | Format-Table -AutoSize

# Belirli bir VM'in detayli kaynak kullanimi
Get-VM -Name "DB-01" | Select-Object *Memory*, *CPU* | Format-List

# En cok CPU kullanan VM'leri bul
Get-VM | Where-Object {$_.State -eq "Running"} | 
    Sort-Object CPUUsage -Descending | 
    Select-Object -First 5 Name, CPUUsage, MemoryAssigned

# Disk kullanim bilgisi
Get-VMHardDiskDrive -VMName "DB-01" | ForEach-Object {
    $vhd = Get-VHD -Path $_.Path
    [PSCustomObject]@{
        VM = "DB-01"
        Disk = $_.Path
        AllocatedGB = [math]::Round($vhd.Size/1GB, 2)
        UsedGB = [math]::Round($vhd.FileSize/1GB, 2)
    }
}

# Host'un toplam kaynak durumu
Get-VMHost | Select-Object Name, LogicalProcessorCount, MemoryCapacity, `
    @{N="TotalRAM(GB)";E={[math]::Round($_.MemoryCapacity/1GB,2)}}

Bu monitöring scriptlerini Task Scheduler ile düzenli aralıklarda çalıştırıp sonuçları log dosyasına yazabilirsin. Basit ama etkili bir izleme altyapısı kurmak için yeterli.

Otomatik Snapshot ve Temizlik Scripti

Gerçek dünyadan bir senaryo: Her gece otomatik snapshot al, 3 günden eski olanları sil. Bunu elle yapmak yerine scriptleyelim:

# Otomatik snapshot ve temizlik scripti
# Bu script Task Scheduler ile her gece calistirilabilir

param(
    [int]$RetentionDays = 3,
    [string]$VMFilter = "*"  # Tum VM'ler icin *, spesifik icin isim ver
)

$LogFile = "C:LogsHyperV-Snapshot-$(Get-Date -Format 'yyyy-MM-dd').log"
$DateStamp = Get-Date -Format "yyyy-MM-dd HH:mm"

function Write-Log {
    param($Message)
    $LogEntry = "[$DateStamp] $Message"
    Write-Host $LogEntry
    Add-Content -Path $LogFile -Value $LogEntry
}

# Log klasorunu olustur
New-Item -ItemType Directory -Path "C:Logs" -Force | Out-Null

Write-Log "Snapshot islemi basliyor..."

# Calisir durumdaki VM'leri al
$RunningVMs = Get-VM -Name $VMFilter | Where-Object {$_.State -eq "Running"}

foreach ($VM in $RunningVMs) {
    $SnapshotName = "AutoSnapshot-$(Get-Date -Format 'yyyy-MM-dd-HHmm')"
    
    try {
        Checkpoint-VM -Name $VM.Name -SnapshotName $SnapshotName
        Write-Log "BASARILI: $($VM.Name) - $SnapshotName alindi"
    }
    catch {
        Write-Log "HATA: $($VM.Name) snapshot alinamadi - $($_.Exception.Message)"
    }
}

# Eski snapshot'lari temizle
Write-Log "Eski snapshot'lar temizleniyor (${RetentionDays} gundon eskiler)..."
$CutoffDate = (Get-Date).AddDays(-$RetentionDays)

Get-VM -Name $VMFilter | ForEach-Object {
    $VMName = $_.Name
    Get-VMCheckpoint -VMName $VMName | Where-Object {
        $_.CreationTime -lt $CutoffDate -and $_.Name -like "AutoSnapshot-*"
    } | ForEach-Object {
        try {
            Remove-VMCheckpoint -VMCheckpoint $_ -Confirm:$false
            Write-Log "SILINDI: $VMName - $($_.Name)"
        }
        catch {
            Write-Log "HATA: $VMName snapshot silinemedi - $($_.Exception.Message)"
        }
    }
}

Write-Log "Islem tamamlandi."

Bu scripti Task Scheduler’a eklerken dikkat etmen gereken nokta: Scripti çalıştıran hesabın Hyper-V yönetici yetkisi olması gerekiyor. Servis hesabı kullanıyorsan bunu kontrol et.

Uzak Hyper-V Host Yönetimi

Birden fazla Hyper-V host’unu yönetiyorsan, her birine tek tek bağlanmak yerine uzaktan yönetebilirsin:

# Uzak host'a baglan
$RemoteHost = "HYPERV-HOST-02"

# Uzak host'taki VM'leri listele
Get-VM -ComputerName $RemoteHost

# Uzak host'ta VM olustur
New-VM -ComputerName $RemoteHost `
       -Name "REMOTE-VM-01" `
       -MemoryStartupBytes 4GB `
       -Generation 2 `
       -NewVHDPath "D:VMsREMOTE-VM-01os.vhdx" `
       -NewVHDSizeBytes 80GB

# Live Migration ile VM'i baska host'a tas
Move-VM -Name "WEB-SERVER-01" `
        -DestinationHost "HYPERV-HOST-02" `
        -DestinationStoragePath "D:VMsWEB-SERVER-01"

# Storage Migration (VM kapali olmadan sadece diski tas)
Move-VMStorage -VMName "WEB-SERVER-01" `
               -DestinationStoragePath "E:VMsWEB-SERVER-01"

Live Migration için her iki host’un da aynı Active Directory domain’inde olması ve Kerberos delegation’ının doğru yapılandırılmış olması gerekiyor. Bunu atlayan ve saatlerce neden çalışmıyor diye bakanlar var. Önce bu gereksinimleri karşıla, sonra komutu çalıştır.

Sonuç

Hyper-V’yi PowerShell ile yönetmek başlangıçta biraz öğrenme eğrisi gerektiriyor, bunu inkar etmeyeyim. Ama bir kez alışınca GUI’ye dönmek istemiyorsun. 20 VM’i aynı anda güncellemek, otomatik snapshot almak, toplu konfigürasyon değişiklikleri yapmak; bunların hepsini GUI’de tıklayarak yapmayı hayal bile etmek istemiyorum.

Bu yazıda anlattıklarımı özetlersek:

  • Sanal Switch yönetimi: External, Internal ve Private switch tipleri ve ne zaman hangisini kullanacağın
  • VM oluşturma ve temel yönetim: Generation 2 tercih et, dynamic memory kullan, ISO bağlama ve boot sırası
  • Snapshot yönetimi: Değişiklik öncesi al, kısa süre tut, eski olanları temizle
  • Toplu işlemler: Foreach döngüsü ve parametre array’leriyle onlarca VM’i hızla oluştur
  • Disk ve network yönetimi: Ek disk ekleme, VHD dönüştürme, VLAN yapılandırması
  • Otomasyon: Task Scheduler ile çalışan log’lu scriptler

Bundan sonraki adım olarak Hyper-V Replica’yı PowerShell ile yönetmeyi araştırmanı öneririm. DR senaryoları için mükemmel bir araç ve tabii ki tamamen scriptlenebilir. İyi sanallaştırmalar!

Yorum yapın