Microsoft Azure/Tip

Azure Tip - Windows 대상의 Migration 준비 과정 스크립트

UnknownFolder 2022. 9. 1. 10:32

Vmware 상에 운영되는 Windows든,

Hyper-V에서 운영되는 WIndows든,

Physical에서 운영되는 Windows든..

 

모든 Windows는 Azure상에 Migration이 가능합니다. (아.. 2003은 쫌... ㅠ_ㅠ)

2003도 Migration을 못하는건 아니지만 각종 문제가 유발될 수 있습니다.

 

여튼!!

이 글에서는 Windows를 이야기하지만 거의 모든 운영환경에서의 Windows든 Linux든 Azure상으로 Migration이 가능합니다.

 

위에서 이야기한 Vmware, Hyper-V, Physical 환경에서의 Migration은 Azure Migrate를 통해 Migration이 가능하며 해당 Tool이 상당히 괜찮은 Tool 입니다. 무엇보다.. 무료!!!!!(180일 동안) 라는 점이 ㅎㅎ(단 Migration을 위한 저장소에 대한 과금은 나와요!)

 

180일 동안 무료라고 하면 흠.. 좀... 이라고 생각할 수 있겠지만 보통 Migration 프로젝트는 Migration의 환경 구성 제외하고는 실제 복제 및 배포는 180일이 넘어가는 경우가 드물죠. 단, 대수에 따라 다릅니다.

 

Azure Migrate가 좋은 이유는 간편하다는 겁니다. 예전에는 Azure Migrate를 쓰더라도 대상 서버 OS 내부에서 Azure에 맞게 설정같은 것들을 했었어야 했는데 지금은 복잡한 설정을 Azure에서 자동으로 해줍니다.(이 과정을 하이드레이션 과정이라고 합니다.) 해당 부분은 Azure Migrate에 대해 이야기 할 때 자세히 이야기해보도록 하죠.

 

여튼 Azure Migrate를 사용하면 손쉽게 Azure로의 Migration이 가능하지만 막상 Migration 프로젝트를 하다보면 인생과 같이 마음대로 되지 않을 때가 많습니다.

이럴때에는 조금은 다른 방법으로 Azure로 Migration이 되어야 합니다.

먼저 이야기드릴 부분은 Azure의 가상머신은 Microsoft에서 Azure에 맞게 변형한 Hyper-V로 운영 됩니다.

이것이 무엇을 의미하는것이냐!!!! 면 바로 VHD를 업로드 해서 Azure VM으로 만들 수 있다는 것이죠.

 

Migration 대상이 Hyper-V 라면 가상디스크가 VHD이기 해당 VHD를 업로드 하면 됩니다. Vmware같은 경우에 vmdk 파일을 vhd로 변환 후 업로드 하시면되고, Physical이라면 disk2vhd 라는 Tool등을 이용하여 VHD로 변환 후 Azure Blob으로 업로드 한 후 Managed disk로 변환하여 VM 생성이 가능합니다.

 

이럴경우에는 Migration 대상에 Windows OS에서 Azure에 맞게 설정을 변경해줘야 합니다.

뭐 RDP Port, 방화벽 정책, 프록시 제거 등등

자세한 내용은 아래 링크에서 확인이 가능합니다!

https://docs.microsoft.com/ko-kr/azure/virtual-machines/windows/prepare-for-upload-vhd-image

 

Azure에 업로드할 Windows VHD 준비 - Azure Virtual Machines

Windows VHD 또는 VHDX를 준비하여 Azure에 업로드하는 방법 알아보기

docs.microsoft.com

 

귀찮습니다.

적혀있는 모든 설정을 하려면...

그래서 만들었습니다. 위의 모든 작업들을 한꺼번에 처리하는 스크립트를!!! 

sysprep까지 진행되며 sysprep 전 Enter를 입력해야 sysprep이 진행됩니다.

그리고 시스템파일 검사는 일단 주석처리 되어 있습니다. 원하신다면 5번째 줄에 #을 제거해주시면 됩니다.

 

게다가! One More Thing!!!

Migration 대상의 Windows 라이선스 키를 제거하고 Azure에서 사용하는 KMS키를 입력하여 인증까지 받는 스크립트입니다. KMS키는 WIndows Server 2012 이상부터 가능합니다.

 

관련 스크립트는 Powershell에서 실행 가능하며 ps1 파일을 만드시거나 ISE에서 실행 가능합니다.

또한 Azure Migrate를 이용한다 하더라도 대상 Windows에 해당 스크립트를 돌리시는 것을 권장드립니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
## https://docs.microsoft.com/ko-kr/azure/virtual-machines/windows/prepare-for-upload-vhd-image
 
## System File Checker
# Write-Host "To verify and replace Windows system files"
# sfc.exe /scannow
 
## Set Windows configurations for Azure
Write-Host "1. Remove Proxy Server"
netsh.exe winhttp reset proxy
 
Write-Host "2. Set the disk SAN policy to Onlineall"
"san policy=onlineall" | Out-File -Encoding Ascii $env:TEMP\diskpart.txt
& diskpart /s $env:TEMP\diskpart.txt
 
Write-Host "3. Set Coordinated Universal Time (UTC) time for Windows. Also, set the startup type of the Windows time service w32time to Automatic"
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\TimeZoneInformation' -Name RealTimeIsUniversal -Value 1 -Type DWord -Force
Set-Service -Name w32time -StartupType Automatic
 
Write-Host "4. Set the power profile to high performance"
powercfg.exe /setactive SCHEME_MIN
 
Write-Host "5. Make sure the environmental variables TEMP and TMP are set to their default values"
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -Name TEMP -Value "%SystemRoot%\TEMP" -Type ExpandString -Force
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -Name TMP -Value "%SystemRoot%\TEMP" -Type ExpandString -Force
 
Write-Host "6. Check the windows services"
Get-Service -Name BFE, Dhcp, Dnscache, IKEEXT, iphlpsvc, nsi, mpssvc, RemoteRegistry |
    Where-Object StartType -ne Automatic |
    Set-Service -StartupType Automatic
Get-Service -Name Netlogon, Netman, TermService |
    Where-Object StartType -ne Manual |
    Set-Service -StartupType Manual
 
## Update remote desktop registry settings"
Write-Host "7. Remote Desktop Protocol (RDP) is enabled"
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' -Name fDenyTSConnections -Value 0 -Type DWord -Force
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' -Name fDenyTSConnections -Value 0 -Type DWord -Force
Write-Host "8. The RDP port is set up correctly using the default port of 3389"
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -Name PortNumber -Value 3389 -Type DWord -Force
Write-Host "9. The listener is listening on every network interface"
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -Name LanAdapter -Value 0 -Type DWord -Force
Write-Host "10. Configure network-level authentication (NLA) mode for the RDP connections"
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name UserAuthentication -Value 1 -Type DWord -Force
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name SecurityLayer -Value 1 -Type DWord -Force
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name fAllowSecProtocolNegotiation -Value 1 -Type DWord -Force
Write-Host "11. Set the keep-alive value"
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' -Name KeepAliveEnable -Value 1  -Type DWord -Force
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' -Name KeepAliveInterval -Value 1  -Type DWord -Force
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -Name KeepAliveTimeout -Value 1 -Type DWord -Force
Write-Host "12. Set the reconnect options"
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' -Name fDisableAutoReconnect -Value 0 -Type DWord -Force
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -Name fInheritReconnectSame -Value 1 -Type DWord -Force
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -Name fReconnectSame -Value 0 -Type DWord -Force
Write-Host "13. Limit the number of concurrent connections"
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\Winstations\RDP-Tcp' -Name MaxInstanceCount -Value 4294967295 -Type DWord -Force
Write-Host "14. Remove any self-signed certificates tied to the RDP listener"
if ((Get-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp').Property -contains 'SSLCertificateSHA1Hash')
{
    Remove-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name SSLCertificateSHA1Hash -Force
}
 
## Configure Windows Firewall rules"
Write-Host "15. Turn on Windows Firewall on the three profiles (domain, standard, and public)"
Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled True
Write-Host "16. Run the following example to allow WinRM through the three firewall profiles (domain, private, and public), and enable the PowerShell remote service"
Enable-PSRemoting -Force
Set-NetFirewallRule -Name WINRM-HTTP-In-TCP, WINRM-HTTP-In-TCP-PUBLIC -Enabled True
Write-Host "17. Enable the following firewall rules to allow the RDP traffic"
Set-NetFirewallRule -Group '@FirewallAPI.dll,-28752' -Enabled True
Write-Host "18. Enable the rule for file and printer sharing so the VM can respond to ping requests inside the virtual network"
Set-NetFirewallRule -Name FPS-ICMP4-ERQ-In -Enabled True
Write-Host "19. Create a rule for the Azure platform network"
New-NetFirewallRule -DisplayName AzurePlatform -Direction Inbound -RemoteAddress 168.63.129.16 -Profile Any -Action Allow -EdgeTraversalPolicy Allow
New-NetFirewallRule -DisplayName AzurePlatform -Direction Outbound -RemoteAddress 168.63.129.16 -Profile Any -Action Allow
 
## Verify the VM
Write-Host "20. To make sure the disk is healthy and consistent, check the disk at the next VM restart"
# chkdsk.exe /f
echo Y |chkdsk.exe /f
Write-Host "21. Set the Boot Configuration Data (BCD) settings"
bcdedit.exe /set "{bootmgr}" integrityservices enable
bcdedit.exe /set "{default}" device partition=C:
bcdedit.exe /set "{default}" integrityservices enable
bcdedit.exe /set "{default}" recoveryenabled Off
bcdedit.exe /set "{default}" osdevice partition=C:
bcdedit.exe /set "{default}" bootstatuspolicy IgnoreAllFailures
Write-Host "22. Enable Serial Console Feature"
bcdedit.exe /set "{bootmgr}" displaybootmenu yes
bcdedit.exe /set "{bootmgr}" timeout 5
bcdedit.exe /set "{bootmgr}" bootems yes
bcdedit.exe /ems "{current}" ON
bcdedit.exe /emssettings EMSPORT:1 EMSBAUDRATE:115200
Write-Host "23. The dump log can be helpful in troubleshooting Windows crash issues. Enable the dump log collection"
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\CrashControl' -Name CrashDumpEnabled -Type DWord -Force -Value 2
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\CrashControl' -Name DumpFile -Type ExpandString -Force -Value "%SystemRoot%\MEMORY.DMP"
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\CrashControl' -Name NMICrashDump -Type DWord -Force -Value 1
Write-Host "24. Set up the guest OS to collect user mode dumps on a service crash event"
$key = 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps'
if ((Test-Path -Path $key) -eq $false) {(New-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting' -Name LocalDumps)}
New-ItemProperty -Path $key -Name DumpFolder -Type ExpandString -Force -Value 'C:\CrashDumps'
New-ItemProperty -Path $key -Name CrashCount -Type DWord -Force -Value 10
New-ItemProperty -Path $key -Name DumpType -Type DWord -Force -Value 2
Set-Service -Name WerSvc -StartupType Manual
Write-Host "25. Verify that the Windows Management Instrumentation (WMI) repository is consistent"
winmgmt.exe /verifyrepository
 
 
# KMS 키 등록 및 인증
# Windows 2012, 2012 R2, 2016, 2019 KMS Key Change and activation Script
# Windows use on Auzre, AzureKMSUse setting 1
# KeyCheckMode is just check KMS Key Serial, not change key and activation
# Windows KMS Client key is public. url : https://docs.microsoft.com/ko-kr/windows-server/get-started/kms-client-activation-keys
 
# Options
$KeyCheckMode = 0 # 1=True, 0=False
$AuzreKMSUse = 1 # 1=True, 0=False
 
$WS2012Check_en = systeminfo | Select-String -pattern "OS Name:"
$WS2012Check_kr = systeminfo | Select-String -pattern "OS 이름:"
 
if ( $WS2012Check_en -eq $null) {
    write-host "WS2012Check_kr select"
    $OSLang = "kr"
    $WS2012Check = $WS2012Check_kr
}
else {
    write-host "WS2012Check_en select"
    $OSLang = "en"
    $WS2012Check = $WS2012Check_en
}
 
if ( $WS2012Check -like "*Microsoft Windows Server 2012*") {    
    switch ( $OSLang ) {
        'en' {
            $OsName = $WS2012Check -creplace 'OS Name:'''
            
        }
        'kr' {
            $OsName = $WS2012Check -creplace 'OS 이름:'''
        }
    }
    $OsName = $OsName.TrimStart()
    
}
else {
    $OsName = (get-computerinfo).OsName
}
 
# Windows Version Edition Check
Write-Host "OSName : ", $OsName
switch ( $OsName ) {
    # Windows Server 2012
    'Microsoft Windows Server 2012' {
        $kmskey = "BN3D2-R7TKB-3YPBD-8DRP2-27GG4"
    }
    'Microsoft Windows Server 2012 Standard' {
        $kmskey = "XC9B7-NBPP2-83J2H-RHMBY-92BT4"
    }
    'Microsoft Windows Server 2012 Datacenter' {
        $kmskey = "48HP8-DN98B-MYWDG-T2DCC-8W83P"
    }
    # Windows Server 2012 R2
    'Microsoft Windows Server 2012 R2 Standard' {
        $kmskey = "D2N9P-3P6X9-2R39C-7RTCD-MDVJX"
    }
    'Microsoft Windows Server 2012 R2 Datacenter' {
        $kmskey = "W3GGN-FT8W3-Y4M27-J84CP-Q3VJ9"
    }
    'Microsoft Windows Server 2012 R2 Essentials' {
        $kmskey = "KNC87-3J2TX-XB4WP-VCPJV-M4FWM"
    }
    # Windows Server 2016
    'Microsoft Windows Server 2016 Datacenter' {
        $kmskey = "CB7KF-BWN84-R7R2Y-793K2-8XDDG"
    }
    'Microsoft Windows Server 2016 Standard' {
        $kmskey = "WC2BQ-8NRM3-FDDYY-2BFGV-KHKQY"
    }
    'Microsoft Windows Server 2016 Essentials' {
        $kmskey = "JCKRF-N37P4-C2D82-9YXRT-4M63B"
    }
    # Windows Server 2019
    'Microsoft Windows Server 2019 Datacenter' {
        $kmskey = "WMDGN-G9PQG-XVVXX-R3X43-63DFG"
    }
    'Microsoft Windows Server 2019 Standard' {
        $kmskey = "N69G4-B89J2-4G8F4-WWYCC-J464C"
    }
    'Microsoft Windows Server 2019 Essentials' {
        $kmskey = "WVDHN-86M7X-466P6-VHXV7-YY726"
    }
}
 
if ( $KeyCheckMode -eq 0 ) {
    if ( $AuzreKMSUse -eq 1 ) {
        write-host "### KMS Server Change (Azure)"
        Invoke-Expression "$env:windir\system32\cscript.exe $env:windir\system32\slmgr.vbs /skms kms.core.windows.net:1688"
    }
 
    write-host "### Insert KMS Key"
    Invoke-Expression "$env:windir\system32\cscript.exe $env:windir\system32\slmgr.vbs /ipk $kmskey"
 
    write-host "### KMS Key Activation"
    sleep 10
    Invoke-Expression "$env:windir\system32\cscript.exe $env:windir\system32\slmgr.vbs /ato"
    Read-Host -Prompt "Press any key to continue"       
}
else {
    write-host ""
    write-host "#########################################################"
    write-host "###########           KEY CHECK MODE          ###########"
    write-host "########### KMS NOT ACTIVATE, JUST KEY CHECK  ###########"
    write-host "#########################################################"
    write-host "OSName  : " $OsName
    write-host "KMS Key : " $kmskey
}
#인증안될 시 cscript c:\windows\system32\slmgr.vbs /dlv 확인 후 cscript c:\windows\system32\slmgr.vbs /ato 로 강제 인증 시도
 
# sysprep 명령어
 
$sysprep = 'C:\Windows\System32\Sysprep\Sysprep.exe'
 
$arg = '/generalize /oobe /shutdown /quiet'
 
Invoke-Command -ScriptBlock {
 
param($sysprep,$arg) Start-Process -FilePath $sysprep -ArgumentList $arg
 
-ArgumentList $sysprep,$arg
 
cs