~/yazilar/hyper-v-ile-sanallastirmaya-giris

Hyper-V ile sanallaştırmaya giriş

9 dk okuma

Hyper-V rolünü kurmak tek satır. Asıl zaman alan, kurulumdan sonra verilen küçük kararlar: VM'ler hangi switch'e bağlanacak, diskler nerede duracak, checkpoint'ler ne kadar tutulacak, host yeniden başlarken VM'lere ne olacak. Bunları baştan düşünmezsen bir yıl sonra dolu bir sistem diski, kimsenin silmeye cesaret edemediği on tane checkpoint ve bir türlü ağa çıkamayan bir test VM'iyle uğraşıyorsun.

Örneklerde host'un adı hv01, yönetim IP'si 10.10.20.31. Komutlar host üzerinde ya da Enter-PSSession hv01 ile açılmış bir oturumda çalışıyor.

Donanım ve disk düzeni

Hyper-V, işlemcide donanım sanallaştırma desteği (Intel VT-x ya da AMD-V) ve SLAT istiyor. Bunların çoğu sunucuda var ama BIOS/UEFI'de kapalı gelebiliyor. Rol kurulmadan önce systeminfo çıktısının sonunda durumu görüyorsun:

systeminfo | Select-String -Pattern 'Hyper-V' -Context 0,4
> Hyper-V Requirements:      VM Monitor Mode Extensions: Yes
                             Virtualization Enabled In Firmware: Yes
                             Second Level Address Translation: Yes
                             Data Execution Prevention Available: Yes

"Virtualization Enabled In Firmware: No" görüyorsan sunucunun firmware ayarlarına girmen gerekiyor. Rol kurulduktan sonra aynı bölümde sadece "A hypervisor has been detected" yazıyor, gereksinimleri artık listelemiyor.

Host'u test için bir VM içinde çalıştırıyorsan (nested virtualization), dıştaki host'ta VM kapalıyken Set-VMProcessor -VMName hv01 -ExposeVirtualizationExtensions $true gerekiyor.

Disk tarafında tek bir kuralım var: VM dosyaları sistem diskinde durmasın. Ayrı bir volume (örneklerde D:) açıyorum. Dinamik büyüyen sanal diskler bir gün sistem diskini doldurursa host'un kendisi de sorun yaşıyor, ayrı bir volume'da ise en kötü ihtimalle sadece VM'ler etkileniyor.

Host'a Hyper-V dışında rol kurmuyorum. Aynı makine DC ya da dosya sunucusu da olursa, birinin bakımı için hepsini durdurmak gerekiyor. Hyper-V host'u Core olarak kurmak da burada çok mantıklı, host'ta ne kadar az bileşen varsa o kadar az yeniden başlatma var ve her yeniden başlatma üzerindeki bütün VM'leri etkiliyor.

Rolü kurmak

Install-WindowsFeature -Name Hyper-V -IncludeManagementTools -Restart

Uzaktan kuruyorsan -ComputerName hv01 eklemen yetiyor. Core'da -IncludeManagementTools sadece PowerShell modülünü kuruyor, grafik Hyper-V Manager host'ta yok. Onu yönetim makinende Windows özelliklerinden ekleyip hv01'e bağlanıyorsun ya da Windows Admin Center'daki Hyper-V bölümünü kullanıyorsun.

Host yeniden başladıktan sonra ilk iş varsayılan yolları değiştirmek:

Get-VMHost | Select-Object VirtualMachinePath, VirtualHardDiskPath
VirtualMachinePath                   VirtualHardDiskPath
------------------                   -------------------
C:\ProgramData\Microsoft\Windows\... C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks
New-Item -ItemType Directory -Path D:\Hyper-V\Disks, D:\ISO -Force | Out-Null
Set-VMHost -VirtualMachinePath 'D:\Hyper-V' -VirtualHardDiskPath 'D:\Hyper-V\Disks'

Bu sadece bundan sonra oluşturulacak VM'leri etkiliyor. Önceden oluşturduğun bir VM varsa onu Move-VMStorage ile taşıman gerekiyor.

Sanal switch türleri

VM'lerin ağa nasıl bağlanacağını sanal switch belirliyor. Üç tür var:

TürVM'ler kiminle konuşabiliyorNerede işe yarıyor
ExternalFiziksel ağ, host ve diğer VM'lerÜretimdeki neredeyse her VM
InternalHost ve aynı switch'teki VM'lerHost üzerinden NAT'lanan test ağı
PrivateSadece aynı switch'teki VM'lerDış dünyadan tamamen yalıtık laboratuvar

External switch

Bir fiziksel ağ kartına bağlanıyor. VM'ler o kartın bağlı olduğu ağda ayrı makineler gibi görünüyor.

Get-NetAdapter
New-VMSwitch -Name 'Dis-Ag' -NetAdapterName 'Ethernet 2' -AllowManagementOS $false

İdeal düzende host'un yönetim trafiği bir kartta, VM trafiği başka bir kartta. -AllowManagementOS $false bu yüzden: Ethernet 2 tamamen VM'lere ayrılıyor, host o karttan IP almıyor.

Tek kartlı bir sunucuda -AllowManagementOS $true kullanmak zorundasın. Bu durumda host'un IP ayarları fiziksel karttan vEthernet (Dis-Ag) adlı sanal karta taşınıyor ve bu sırada bağlantı birkaç saniye kopuyor. Uzaktan bağlıysan oturumun düşebiliyor, statik IP ayarları da her zaman sorunsuz taşınmıyor. Bu işlemi konsol erişimin varken yap.

İki ya da daha fazla kartı birleştirmek istiyorsan güncel yol Switch Embedded Teaming (SET). Eski NIC teaming (LBFO) üzerine sanal switch kurmak yeni sürümlerde desteklenmiyor:

New-VMSwitch -Name 'Dis-Ag' -NetAdapterName 'Ethernet 2', 'Ethernet 3' -EnableEmbeddedTeaming $true -AllowManagementOS $false

Fiziksel port trunk ise VM'leri VLAN'lara switch üzerinden değil, VM'in ağ kartından ayırıyorsun. Komut VM oluşturulduktan sonra çalışıyor, aşağıdaki VM örneğinde de yerini göreceksin:

Set-VMNetworkAdapterVlan -VMName web01 -Access -VlanId 20

Internal ve private

Laboratuvar için internal switch ile host üzerinden NAT'lanan küçük bir ağ kurmak pratik. VM'ler dışarı çıkabiliyor ama dışarıdan kimse onlara ulaşamıyor:

New-VMSwitch -Name 'Lab' -SwitchType Internal
New-NetIPAddress -InterfaceAlias 'vEthernet (Lab)' -IPAddress 192.168.100.1 -PrefixLength 24
New-NetNat -Name 'LabNAT' -InternalIPInterfaceAddressPrefix 192.168.100.0/24

Bu ağda DHCP yok, VM'lere 192.168.100.0/24 aralığından statik adres ve gateway olarak 192.168.100.1 veriyorsun. Private switch ise -SwitchType Private ile aynı şekilde oluşuyor, host'un bile içinde adresi olmuyor.

Generation 2 VM

Yeni VM oluştururken iki nesil seçeneği var. Generation 2 UEFI ile açılıyor, Secure Boot ve sanal TPM destekliyor, SCSI diskten boot edebiliyor ve eski donanım emülasyonunu taşımıyor. Generation 1'i sadece UEFI desteklemeyen eski ya da 32 bit bir işletim sistemi için seçiyorum. Nesil VM oluşturulduktan sonra değiştirilemiyor.

Bir Ubuntu sunucu VM'i:

New-VM -Name web01 -Generation 2 -MemoryStartupBytes 4GB `
    -NewVHDPath 'D:\Hyper-V\Disks\web01.vhdx' -NewVHDSizeBytes 60GB `
    -SwitchName 'Dis-Ag'

Set-VMProcessor -VMName web01 -Count 2
Add-VMDvdDrive  -VMName web01 -Path 'D:\ISO\ubuntu-server.iso'
Set-VMFirmware  -VMName web01 -FirstBootDevice (Get-VMDvdDrive -VMName web01) `
    -SecureBootTemplate MicrosoftUEFICertificateAuthority
Set-VMNetworkAdapterVlan -VMName web01 -Access -VlanId 20

Start-VM -Name web01

-SecureBootTemplate satırı Linux için. Generation 2 VM'ler varsayılan olarak sadece Windows'un imzasını kabul eden şablonla geliyor. Linux ISO'su bu şablonla açılmaya çalışınca VM konsolunda şuna benzer bir mesaj görüyorsun:

Boot Failed. SCSI DVD (0,1)
The image's hash and certificate are not allowed (DB).

Secure Boot'u kapatmak da çalışıyor ama gerek yok. MicrosoftUEFICertificateAuthority şablonu, imzalı shim kullanan yaygın dağıtımları açıyor ve Secure Boot korumasını yerinde bırakıyor. VM ayağa kalktıktan sonraki işler için Ubuntu sunucuda ilk işler yazısına bakabilirsin.

Windows VM'lerde varsayılan şablon doğru. Güncel Windows sürümleri TPM isteyebildiği için sanal TPM'i de açıyorum:

Set-VMKeyProtector -VMName srv02 -NewLocalKeyProtector
Enable-VMTPM -VMName srv02

Yerel key protector, VM'i bu host'a bağlıyor. VM'i başka bir host'a taşıyacaksan TPM'in koruyucu sertifikasının da taşınması gerekiyor, cluster ya da Host Guardian Service kullanmıyorsan bunu planla.

Dinamik disk mi sabit disk mi

-NewVHDPath ile oluşan VHDX varsayılan olarak dinamik: 60 GB'lık disk, içine yazıldıkça büyüyor. Eskiden performans için sabit boyutlu disk önerilirdi. Bugün fark çoğu iş yükünde küçük, asıl risk kapasite tarafında. Toplam boyutu volume'un kapasitesini aşan dinamik diskler verirsen ve hepsi aynı anda büyürse volume doluyor. Hyper-V bu durumda veri kaybetmemek için yazamayan VM'leri duraklatıyor, Hyper-V Manager'da durumları Paused-Critical oluyor. Yer açıp VM'leri devam ettirince düzeliyor ama o ana kadar hizmet durmuş oluyor.

Ne kadar söz verdiğini görmek için:

Get-VM | Get-VMHardDiskDrive | Get-VHD |
    Select-Object Path, VhdType, @{n='BoyutGB';e={[math]::Round($_.Size/1GB)}}, @{n='KullanilanGB';e={[math]::Round($_.FileSize/1GB)}}

Checkpoint ne yapıyor, ne yapmıyor

Checkpoint, VM'in bir andaki halini kaydediyor ve tek tıkla o ana dönebiliyorsun. Bu yüzden yedek gibi görünüyor. Değil.

Alındığı anda Hyper-V VM'in diskini salt okunur yapıyor ve bundan sonraki yazmaları yanına açtığı bir .avhdx farklılık diskine yönlendiriyor. Yani:

  • Checkpoint, asıl diskle aynı volume'da duruyor. O disk ya da storage giderse checkpoint de gidiyor.
  • Checkpoint tek başına bir şey ifade etmiyor, asıl VHDX olmadan açılamıyor.
  • Her checkpoint zincire bir disk daha ekliyor. Okumalar zincirin içinde aranıyor ve zincir uzadıkça disk performansı düşüyor.
  • Farklılık diski VM yazdıkça büyüyor. Unutulmuş bir checkpoint aylar içinde asıl disk kadar yer kaplayabiliyor.

İki tür checkpoint var. Production checkpoint, VM'in içinde VSS (Linux'ta dosya sistemi dondurma) kullanıyor ve uygulama açısından tutarlı bir an kaydediyor, ama belleği kaydetmiyor. Geri dönüldüğünde VM kapalı bir sistem gibi açılıyor. Standard checkpoint belleği de kaydediyor, çalışan halin birebir kopyası. Varsayılan Production, VSS başarısız olursa Standard'a düşüyor. Ben bu düşüşü kapatıyorum, sessizce farklı türde bir checkpoint almasını istemiyorum:

Set-VM -Name web01 -CheckpointType ProductionOnly

Domain controller'larda checkpoint'e dönmek ayrıca dikkat istiyor. Güncel sürümlerde AD, sanal makine kimliğindeki değişikliği fark edip kendini koruyor. Ama bir DC'yi haftalar önceki bir checkpoint'e döndürmek, o arada yapılmış değişikliklerin replikasyonunu karıştırabiliyor. DC'ler için geri dönüş yolu checkpoint değil, önceki yazıda bahsettiğim system state yedeği.

Checkpoint'i kullandığım yer belli: riskli bir değişiklikten hemen önce alıyorum, değişiklik tuttuysa aynı gün siliyorum.

Checkpoint-VM -Name web01 -SnapshotName 'guncelleme-oncesi'
# ... güncelleme, kontrol ...
Remove-VMSnapshot -VMName web01 -Name 'guncelleme-oncesi'
# Ya da işler kötü gittiyse:
Restore-VMSnapshot -VMName web01 -Name 'guncelleme-oncesi' -Confirm:$false

Remove-VMSnapshot checkpoint'i silerken farklılık diskini asıl diske birleştiriyor (merge). Bu arka planda sürüyor, büyük bir farklılık diskinde uzun sürebiliyor. .avhdx dosyalarını hiçbir zaman Explorer'dan ya da Remove-Item ile silme. Zincir kırılıyor ve VM açılmıyor.

Host'ta unutulmuş checkpoint'leri bulmak için ara sıra şunu çalıştırıyorum:

Get-VM | Get-VMSnapshot |
    Where-Object CreationTime -lt (Get-Date).AddDays(-7) |
    Select-Object VMName, Name, CreationTime

Gerçek yedek, VM'i başka bir diske ya da başka bir yere kopyalayan, geçmiş sürümleri tutan ve geri dönüşü test edilmiş bir şey. Hyper-V yedeklemesini destekleyen bir yedekleme yazılımı ya da Windows Server Backup bu işi yapabiliyor. Tek seferlik bir kopya için Export-VM de var, çalışan VM'i de dışa aktarabiliyor:

Export-VM -Name web01 -Path '\\yedek01\hyperv-export'

Dışa aktarılan klasör başka bir host'a Import-VM ile alınabiliyor. Yalnız bu bir yedekleme düzeni sayılmaz, el ile alınmış bir kopya.

İlk bakılacak performans ayarları

Varsayılanlar çoğu VM için idare ediyor. Benim yeni bir VM'de kontrol ettiğim birkaç ayar var.

Bellek. Dynamic Memory, VM'in o an ihtiyaç duyduğu kadar bellek almasını ve fazlasını host'a geri vermesini sağlıyor. Web sunucusu ya da küçük servisler için iyi çalışıyor. Bellek yönetimini kendisi yapan iş yükleri (veritabanı sunucuları gibi) için sabit bellek veriyorum, üreticinin önerisine bak. Ayar VM kapalıyken değişiyor:

Stop-VM -Name web01
Set-VMMemory -VMName web01 -DynamicMemoryEnabled $true `
    -MinimumBytes 2GB -StartupBytes 4GB -MaximumBytes 8GB
Start-VM -Name web01

İşlemci. Daha fazla vCPU her zaman daha hızlı demek değil. Host'taki fiziksel çekirdeklerden fazlasını VM'lere dağıtmak mümkün, ama her fazladan vCPU host'ta işlemci için sıraya giren bir iş parçacığı daha demek. VM'in içindeki iş yükü bu çekirdekleri kullanamıyorsa kazanç yok, sadece bekleme süreleri artıyor. İki vCPU ile başlıyorum, izleme gerçekten işlemci darboğazı gösterirse artırıyorum.

Host kapanırken ve açılırken. Varsayılan kapanma davranışı VM'in durumunu kaydetmek (Save). Bu, her VM için belleği kadar diski ayırıyor ve host açıldığında VM'ler kaldıkları yerden devam ediyor. Sunucu VM'leri için düzgün kapatıp düzgün açmayı tercih ediyorum. Açılışta da sıra veriyorum, önce DC'ler, sonra onlara bağımlı sunucular:

Set-VM -Name dc01  -AutomaticStartAction Start -AutomaticStartDelay 0   -AutomaticStopAction ShutDown
Set-VM -Name web01 -AutomaticStartAction Start -AutomaticStartDelay 120 -AutomaticStopAction ShutDown

Integration services. Host ile VM arasındaki sürücüler ve servisler (saat senkronizasyonu, düzgün kapatma, yedekleme için VSS). Güncel Linux çekirdeklerinde ve Windows'ta hazır geliyor, Windows'ta Windows Update ile güncelleniyor. Durumunu görmek için:

Get-VMIntegrationService -VMName web01

DC VM'lerinde saat senkronizasyonuna ayrıca bakmak gerekiyor. Domain'in saat kaynağı PDC Emulator olmalı, host değil. Microsoft'un önerisi, DC'nin içinde Hyper-V saat sağlayıcısını kapatmak:

# DC VM'inin içinde
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\VMICTimeProvider' -Name Enabled -Value 0
Restart-Service w32time
w32tm /query /source

Antivirüs. Hyper-V'nin işlemleri ve VM dosyaları taranırsa VM'ler yavaşlayabiliyor, bazı durumlarda başlamıyor. Microsoft Defender, sunucu rollerine göre gerekli istisnaları kendisi ekliyor. Üçüncü parti bir antivirüs kullanıyorsan üreticinin Hyper-V için verdiği istisna listesini uygula.

Tek host'la buraya kadar. Bir sonraki mantıklı adım ikinci bir host ve VM'leri host'lar arasında taşıyabilmek, o da failover cluster ve paylaşımlı depolama demek.

Sıradaki yazı: Docker'ı kurup ilk container'ı çalıştırmak