This commit is contained in:
Yagmur Sahin 2021-02-02 14:48:43 +03:00
Коммит a271090fe5
23 изменённых файлов: 4154 добавлений и 0 удалений

2
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
DSC/.files/
scripts/ignore/

Двоичные данные
.images/ARM-akshcionAzureStackHCICluster.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 41 KiB

Двоичные данные
.images/ARM-akshcionAzureVM.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 40 KiB

Двоичные данные
.images/AksHciOnAzureStackHci.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 62 KiB

Двоичные данные
.images/AksHcionAzureVM.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 55 KiB

894
DSC/AzureStackHCIHost.ps1 Normal file
Просмотреть файл

@ -0,0 +1,894 @@
configuration AzureStackHCIHost
{
param
(
[Parameter(Mandatory)]
[String]$DomainName,
[Parameter(Mandatory)]
[System.Management.Automation.PSCredential]$Admincreds,
[Int]$RetryCount=20,
[Int]$RetryIntervalSec=30,
[String]$targetDrive = "V:",
[String]$sourcePath = "$targetDrive\source",
[String]$targetVMPath = "$targetDrive\VMs",
[String]$baseVHDFolderPath = "$targetVMPath\base",
[String]$azsHCIISOLocalPath = "$sourcePath\AzSHCI.iso",
[String]$wacLocalPath = "$sourcePath\WACLatest.msi",
[String]$azsHCIIsoUri = "https://aka.ms/2CNBagfhSZ8BM7jyEV8I",
[String]$azsHciVhdPath = "$baseVHDFolderPath\AzSHCI.vhdx",
[String]$ws2019IsoUri = "https://software-download.microsoft.com/download/pr/17763.737.190906-2324.rs5_release_svc_refresh_SERVER_EVAL_x64FRE_en-us_1.iso",
[String]$ws2019IsoLocalPath = "$sourcePath\ws2019.iso",
[String]$ws2019VhdPath = "$baseVHDFolderPath\ws2019.vhdx",
[String]$wacUri = "https://aka.ms/wacdownload",
[Int]$azsHostCount = 2,
[Int]$azsHostDataDiskCount = 3,
[Int64]$dataDiskSize = 500GB,
[string]$natPrefix = "AzSHCI",
[string]$vSwitchNameMgmt = "Management",
[string]$vSwitchNameConverged = "Default Switch",
[string]$HCIvmPrefix = "hpv",
[string]$wacVMName = "wac",
[int]$azsHCIHostMemory,
[string]$branch = "master",
[string]$aksHciScenario
)
Import-DscResource -ModuleName 'xActiveDirectory'
Import-DscResource -ModuleName 'xStorage'
Import-DscResource -ModuleName 'NetworkingDSC'
Import-DscResource -ModuleName 'PSDesiredStateConfiguration'
Import-DscResource -ModuleName 'ComputerManagementDsc'
Import-DscResource -ModuleName 'xHyper-v'
Import-DscResource -ModuleName 'cHyper-v'
Import-DscResource -ModuleName 'xPSDesiredStateConfiguration'
Import-DscResource -ModuleName 'xDHCpServer'
Import-DscResource -ModuleName 'cChoco'
Import-DscResource -ModuleName 'DSCR_Shortcut'
$repoName = "AzureStackHCIonAzure"
$repoBaseUrl = "https://github.com/yagmurs/$repoName"
$branchFiles = "$repoBaseUrl/archive/$branch.zip"
if ($aksHciScenario -eq 'onAzureVMDirectly') {
$labScript = "Deploy-AksHciOnAzureVM.ps1"
}
else
{
$labScript = "Deploy-AksHciOnNestedAzureAzureStackHCI.ps1"
}
[System.Management.Automation.PSCredential]$DomainCreds = New-Object System.Management.Automation.PSCredential ("${DomainName}\$($Admincreds.UserName)", $Admincreds.Password)
$ipConfig = (Get-NetAdapter -Physical | Get-NetIPConfiguration | Where-Object IPv4DefaultGateway)
$netAdapters = Get-NetAdapter -Name ($ipConfig.InterfaceAlias) | Select-Object -First 1
$InterfaceAlias=$($netAdapters.Name)
Node localhost
{
LocalConfigurationManager {
RebootNodeIfNeeded = $true
ActionAfterReboot = 'ContinueConfiguration'
ConfigurationMode = 'ApplyOnly'
}
xWaitforDisk Disk1
{
DiskID = 1
RetryIntervalSec =$RetryIntervalSec
RetryCount = $RetryCount
}
xDisk ADDataDisk
{
DiskID = 1
DriveLetter = "F"
DependsOn = "[xWaitForDisk]Disk1"
}
xWaitforDisk Disk2
{
DiskID = 2
RetryIntervalSec =$RetryIntervalSec
RetryCount = $RetryCount
}
xDisk hpvDataDisk
{
DiskID = 2
DriveLetter = $targetDrive
DependsOn = "[xWaitForDisk]Disk2"
}
File "source"
{
DestinationPath = $sourcePath
Type = 'Directory'
Force = $true
DependsOn = "[xDisk]hpvDataDisk"
}
File "folder-vms"
{
Type = 'Directory'
DestinationPath = $targetVMPath
DependsOn = "[xDisk]hpvDataDisk"
}
File "VM-base"
{
Type = 'Directory'
DestinationPath = $baseVHDFolderPath
DependsOn = "[File]folder-vms"
}
Registry "Disable Internet Explorer ESC for Admin"
{
Key = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}"
ValueName = "IsInstalled"
ValueData = "0"
ValueType = "Dword"
}
Registry "Disable Internet Explorer ESC for User"
{
Key = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A8-37EF-4b3f-8CFC-4F3A74704073}"
ValueName = "IsInstalled"
ValueData = "0"
ValueType = "Dword"
}
Registry "Add Wac to Intranet zone for SSO"
{
Key = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\EscDomains\wac'
ValueName = "https"
ValueData = 1
ValueType = 'Dword'
}
ScheduledTask "Disable Server Manager at Startup"
{
TaskName = 'ServerManager'
Enable = $false
TaskPath = '\Microsoft\Windows\Server Manager'
}
script "Download branch files for $branch"
{
GetScript = {
$result = Test-Path -Path "$using:sourcePath\$using:branch.zip"
return @{ 'Result' = $result }
}
SetScript = {
Invoke-WebRequest -Uri $using:branchFiles -OutFile "$using:sourcePath\$using:branch.zip"
#Start-BitsTransfer -Source $using:branchFiles -Destination "$using:sourcePath\$using:branch.zip"
}
TestScript = {
# Create and invoke a scriptblock using the $GetScript automatic variable, which contains a string representation of the GetScript.
$state = [scriptblock]::Create($GetScript).Invoke()
return $state.Result
}
DependsOn = "[File]source"
}
archive "Extract branch files"
{
Ensure = 'Present'
Path = "$sourcePath\$branch.zip"
Destination = "$sourcePath\branchData"
Validate = $true
Checksum = 'SHA-1'
DependsOn = "[script]Download branch files for $branch"
}
script "Download AzureStack HCI bits"
{
GetScript = {
$result = Test-Path -Path $using:azsHCIISOLocalPath
return @{ 'Result' = $result }
}
SetScript = {
Start-BitsTransfer -Source $using:azsHCIIsoUri -Destination $using:azsHCIISOLocalPath
}
TestScript = {
# Create and invoke a scriptblock using the $GetScript automatic variable, which contains a string representation of the GetScript.
$state = [scriptblock]::Create($GetScript).Invoke()
return $state.Result
}
DependsOn = "[File]source"
}
WindowsFeature DNS
{
Ensure = "Present"
Name = "DNS"
}
WindowsFeature "Enable Deduplication"
{
Ensure = "Present"
Name = "FS-Data-Deduplication"
}
Script EnableDNSDiags
{
SetScript = {
Set-DnsServerDiagnostics -All $true
Write-Verbose -Verbose "Enabling DNS client diagnostics"
}
GetScript = { @{} }
TestScript = { $false }
DependsOn = "[WindowsFeature]DNS"
}
WindowsFeature DnsTools
{
Ensure = "Present"
Name = "RSAT-DNS-Server"
DependsOn = "[WindowsFeature]DNS"
}
DnsServerAddress "DnsServerAddress for $InterfaceAlias"
{
Address = '127.0.0.1'
InterfaceAlias = $InterfaceAlias
AddressFamily = 'IPv4'
DependsOn = "[WindowsFeature]DNS"
}
WindowsFeature ADDSInstall
{
Ensure = "Present"
Name = "AD-Domain-Services"
DependsOn="[WindowsFeature]DNS"
}
WindowsFeature ADDSTools
{
Ensure = "Present"
Name = "RSAT-ADDS-Tools"
DependsOn = "[WindowsFeature]ADDSInstall"
}
WindowsFeature ADAdminCenter
{
Ensure = "Present"
Name = "RSAT-AD-AdminCenter"
DependsOn = "[WindowsFeature]ADDSInstall"
}
xADDomain FirstDS
{
DomainName = $DomainName
DomainAdministratorCredential = $DomainCreds
SafemodeAdministratorPassword = $DomainCreds
DatabasePath = "F:\NTDS"
LogPath = "F:\NTDS"
SysvolPath = "F:\SYSVOL"
DependsOn = @("[xDisk]ADDataDisk", "[WindowsFeature]ADDSInstall")
}
WindowsFeature "Install DHCPServer"
{
Name = 'DHCP'
Ensure = 'Present'
}
WindowsFeature DHCPTools
{
Ensure = "Present"
Name = "RSAT-DHCP"
DependsOn = "[WindowsFeature]Install DHCPServer"
}
WindowsFeature "Hyper-V"
{
Name = "Hyper-V"
Ensure = "Present"
}
WindowsFeature "RSAT-Hyper-V-Tools"
{
Name = "RSAT-Hyper-V-Tools"
Ensure = "Present"
DependsOn = "[WindowsFeature]Hyper-V"
}
WindowsFeature "RSAT-Clustering"
{
Name = "RSAT-Clustering"
Ensure = "Present"
}
xVMHost "hpvHost"
{
IsSingleInstance = 'yes'
EnableEnhancedSessionMode = $true
VirtualHardDiskPath = $targetVMPath
VirtualMachinePath = $targetVMPath
DependsOn = "[WindowsFeature]Hyper-V"
}
xVMSwitch "$vSwitchNameMgmt"
{
Name = $vSwitchNameMgmt
Type = "Internal"
DependsOn = "[WindowsFeature]Hyper-V"
}
xVMSwitch "$vSwitchNameConverged"
{
Name = $vSwitchNameConverged
Type = "Internal"
DependsOn = "[WindowsFeature]Hyper-V"
}
IPAddress "New IP for vEthernet $vSwitchNameMgmt"
{
InterfaceAlias = "vEthernet `($vSwitchNameMgmt`)"
AddressFamily = 'IPv4'
IPAddress = '192.168.0.1/24'
DependsOn = "[xVMSwitch]$vSwitchNameMgmt"
}
NetIPInterface "Enable IP forwarding on vEthernet $vSwitchNameMgmt"
{
AddressFamily = 'IPv4'
InterfaceAlias = "vEthernet `($vSwitchNameMgmt`)"
Forwarding = 'Enabled'
DependsOn = "[IPAddress]New IP for vEthernet $vSwitchNameMgmt"
}
NetAdapterRdma "Enable RDMA on vEthernet $vSwitchNameMgmt"
{
Name = "vEthernet `($vSwitchNameMgmt`)"
Enabled = $true
DependsOn = "[NetIPInterface]Enable IP forwarding on vEthernet $vSwitchNameMgmt"
}
DnsServerAddress "DnsServerAddress for vEthernet $vSwitchNameMgmt"
{
Address = '127.0.0.1'
InterfaceAlias = "vEthernet `($vSwitchNameMgmt`)"
AddressFamily = 'IPv4'
DependsOn = "[IPAddress]New IP for vEthernet $vSwitchNameMgmt"
}
IPAddress "New IP for vEthernet $vSwitchNameConverged"
{
InterfaceAlias = "vEthernet `($vSwitchNameConverged`)"
AddressFamily = 'IPv4'
IPAddress = '192.168.100.1/24'
DependsOn = "[xVMSwitch]$vSwitchNameConverged"
}
NetIPInterface "Enable IP forwarding on vEthernet $vSwitchNameConverged"
{
AddressFamily = 'IPv4'
InterfaceAlias = "vEthernet `($vSwitchNameConverged`)"
Forwarding = 'Enabled'
DependsOn = "[IPAddress]New IP for vEthernet $vSwitchNameConverged"
}
NetAdapterRdma "Enable RDMA on vEthernet $vSwitchNameConverged"
{
Name = "vEthernet `($vSwitchNameConverged`)"
Enabled = $true
DependsOn = "[NetIPInterface]Enable IP forwarding on vEthernet $vSwitchNameConverged"
}
DnsServerAddress "DnsServerAddress for vEthernet $vSwitchNameConverged"
{
Address = '127.0.0.1'
InterfaceAlias = "vEthernet `($vSwitchNameConverged`)"
AddressFamily = 'IPv4'
DependsOn = "[IPAddress]New IP for vEthernet $vSwitchNameConverged"
}
xDhcpServerAuthorization "Authorize DHCP"
{
Ensure = 'Present'
DependsOn = @('[WindowsFeature]Install DHCPServer')
DnsName = [System.Net.Dns]::GetHostByName($env:computerName).hostname
IPAddress = '192.168.100.1'
}
xDhcpServerScope "Scope 192.168.0.0"
{
Ensure = 'Present'
IPStartRange = '192.168.0.150'
IPEndRange = '192.168.0.240'
ScopeId = '192.168.0.0'
Name = 'Management Address Range for VMs on AzSHCI Cluster'
SubnetMask = '255.255.255.0'
LeaseDuration = '02.00:00:00'
State = 'Active'
AddressFamily = 'IPv4'
DependsOn = @("[WindowsFeature]Install DHCPServer", "[IPAddress]New IP for vEthernet $vSwitchNameMgmt")
}
xDhcpServerScope "Scope 192.168.100.0"
{
Ensure = 'Present'
IPStartRange = '192.168.100.21'
IPEndRange = '192.168.100.254'
ScopeId = '192.168.100.0'
Name = 'Client Address Range for Nested VMs on AzSHCI Cluster'
SubnetMask = '255.255.255.0'
LeaseDuration = '02.00:00:00'
State = 'Active'
AddressFamily = 'IPv4'
DependsOn = @("[WindowsFeature]Install DHCPServer", "[IPAddress]New IP for vEthernet $vSwitchNameConverged")
}
xDhcpServerOption "Option 192.168.0.0"
{
Ensure = 'Present'
ScopeID = '192.168.0.0'
DnsDomain = $DomainName
DnsServerIPAddress = '192.168.0.1'
AddressFamily = 'IPv4'
Router = '192.168.0.1'
DependsOn = @("[WindowsFeature]Install DHCPServer", "[IPAddress]New IP for vEthernet $vSwitchNameMgmt")
}
xDhcpServerOption "Option 192.168.100.0"
{
Ensure = 'Present'
ScopeID = '192.168.100.0'
DnsDomain = $DomainName
DnsServerIPAddress = '192.168.100.1'
AddressFamily = 'IPv4'
Router = '192.168.100.1'
DependsOn = @("[WindowsFeature]Install DHCPServer", "[IPAddress]New IP for vEthernet $vSwitchNameConverged")
}
script "New Nat rule for Management Network"
{
GetScript = {
$nat = $($using:natPrefix + "-Management")
$result = if (Get-NetNat -Name $nat -ErrorAction SilentlyContinue) {$true} else {$false}
return @{ 'Result' = $result }
}
SetScript = {
$nat = $($using:natPrefix + "-Management")
New-NetNat -Name $nat -InternalIPInterfaceAddressPrefix "192.168.0.0/24"
}
TestScript = {
# Create and invoke a scriptblock using the $GetScript automatic variable, which contains a string representation of the GetScript.
$state = [scriptblock]::Create($GetScript).Invoke()
return $state.Result
}
DependsOn = "[IPAddress]New IP for vEthernet $vSwitchNameMgmt"
}
script "New Nat rule for Nested Network"
{
GetScript = {
$nat = $($using:natPrefix + "-Nested")
$result = if (Get-NetNat -Name $nat -ErrorAction SilentlyContinue) {$true} else {$false}
return @{ 'Result' = $result }
}
SetScript = {
$nat = $($using:natPrefix + "-Nested")
New-NetNat -Name $nat -InternalIPInterfaceAddressPrefix "192.168.100.0/24"
}
TestScript = {
# Create and invoke a scriptblock using the $GetScript automatic variable, which contains a string representation of the GetScript.
$state = [scriptblock]::Create($GetScript).Invoke()
return $state.Result
}
DependsOn = "[IPAddress]New IP for vEthernet $vSwitchNameConverged"
}
script "prepareVHDX"
{
GetScript = {
$result = Test-Path -Path $using:azsHciVhdPath
return @{ 'Result' = $result }
}
SetScript = {
#Create Azure Stack HCI Host Image
Convert-Wim2Vhd -DiskLayout UEFI -SourcePath $using:azsHCIISOLocalPath -Path $using:azsHciVhdPath -Size 100GB -Dynamic -Index 1 -ErrorAction SilentlyContinue
#Enable Hyper-v role on the Azure Stack HCI Host Image
Install-WindowsFeature -Vhd $using:azsHciVhdPath -Name Hyper-V
}
TestScript = {
# Create and invoke a scriptblock using the $GetScript automatic variable, which contains a string representation of the GetScript.
$state = [scriptblock]::Create($GetScript).Invoke()
return $state.Result
}
DependsOn = "[file]VM-Base", "[script]Download AzureStack HCI bits"
}
if ($aksHciScenario -eq 'onNestedAzureStackHciClusteronAzureVM')
{
for ($i = 1; $i -lt $azsHostCount + 1; $i++)
{
$suffix = '{0:D2}' -f $i
$vmname = $($HCIvmPrefix + $suffix)
$memory = $azsHCIHostMemory * 1gb
file "VM-Folder-$vmname"
{
Ensure = 'Present'
DestinationPath = "$targetVMPath\$vmname"
Type = 'Directory'
DependsOn = "[File]folder-vms"
}
xVhd "NewOSDisk-$vmname"
{
Ensure = 'Present'
Name = "$vmname-OSDisk.vhdx"
Path = "$targetVMPath\$vmname"
Generation = 'vhdx'
ParentPath = $azsHciVhdPath
Type = 'Differencing'
DependsOn = "[xVMSwitch]$vSwitchNameMgmt", "[script]prepareVHDX", "[file]VM-Folder-$vmname"
}
xVMHyperV "VM-$vmname"
{
Ensure = 'Present'
Name = $vmname
VhdPath = "$targetVMPath\$vmname\$vmname-OSDisk.vhdx"
Path = $targetVMPath
Generation = 2
StartupMemory = $memory
ProcessorCount = 4
DependsOn = "[xVhd]NewOSDisk-$vmname"
}
xVMProcessor "Enable NestedVirtualization-$vmname"
{
VMName = $vmname
ExposeVirtualizationExtensions = $true
DependsOn = "[xVMHyperV]VM-$vmname"
}
script "remove default Network Adapter on VM-$vmname"
{
GetScript = {
$VMNetworkAdapter = Get-VMNetworkAdapter -VMName $using:vmname -Name 'Network Adapter' -ErrorAction SilentlyContinue
$result = if ($VMNetworkAdapter) {$false} else {$true}
return @{
VMName = $VMNetworkAdapter.VMName
Name = $VMNetworkAdapter.Name
Result = $result
}
}
SetScript = {
$state = [scriptblock]::Create($GetScript).Invoke()
Remove-VMNetworkAdapter -VMName $state.VMName -Name $state.Name
}
TestScript = {
# Create and invoke a scriptblock using the $GetScript automatic variable, which contains a string representation of the GetScript.
$state = [scriptblock]::Create($GetScript).Invoke()
return $state.Result
}
DependsOn = "[xVMHyperV]VM-$vmname"
}
for ($k = 1; $k -le 2; $k++)
{
$mgmtNicName = "$vmname-Management$k"
xVMNetworkAdapter "New Network Adapter $mgmtNicName $vmname DHCP"
{
Id = $mgmtNicName
Name = $mgmtNicName
SwitchName = $vSwitchNameMgmt
VMName = $vmname
Ensure = 'Present'
DependsOn = "[xVMHyperV]VM-$vmname"
}
cVMNetworkAdapterSettings "Enable $vmname $mgmtNicName Mac address spoofing and Teaming"
{
Id = $mgmtNicName
Name = $mgmtNicName
SwitchName = $vSwitchNameMgmt
VMName = $vmname
AllowTeaming = 'on'
MacAddressSpoofing = 'on'
DependsOn = "[xVMNetworkAdapter]New Network Adapter $mgmtNicName $vmname DHCP"
}
}
for ($l = 1; $l -le 4; $l++)
{
$ipAddress = $('192.168.25' + $l + '.1' + $suffix)
$nicName = "$vmname-Converged-Nic$l"
xVMNetworkAdapter "New Network Adapter Converged $vmname $nicName $ipAddress"
{
Id = $nicName
Name = $nicName
SwitchName = $vSwitchNameConverged
VMName = $vmname
NetworkSetting = xNetworkSettings {
IpAddress = $ipAddress
Subnet = "255.255.255.0"
}
Ensure = 'Present'
DependsOn = "[xVMHyperV]VM-$vmname"
}
cVMNetworkAdapterSettings "Enable $vmname $nicName Mac address spoofing and Teaming"
{
Id = $nicName
Name = $nicName
SwitchName = $vSwitchNameConverged
VMName = $vmname
AllowTeaming = 'on'
MacAddressSpoofing = 'on'
DependsOn = "[xVMNetworkAdapter]New Network Adapter Converged $vmname $nicName $ipAddress"
}
}
for ($j = 1; $j -lt $azsHostDataDiskCount + 1 ; $j++)
{
xvhd "$vmname-DataDisk$j"
{
Ensure = 'Present'
Name = "$vmname-DataDisk$j.vhdx"
Path = "$targetVMPath\$vmname"
Generation = 'vhdx'
Type = 'Dynamic'
MaximumSizeBytes = $dataDiskSize
DependsOn = "[xVMHyperV]VM-$vmname"
}
xVMHardDiskDrive "$vmname-DataDisk$j"
{
VMName = $vmname
ControllerType = 'SCSI'
ControllerLocation = $j
Path = "$targetVMPath\$vmname\$vmname-DataDisk$j.vhdx"
Ensure = 'Present'
DependsOn = "[xVMHyperV]VM-$vmname"
}
}
script "UnattendXML for $vmname"
{
GetScript = {
$name = $using:VmName
$result = Test-Path -Path "$using:targetVMPath\$name\Unattend.xml"
return @{ 'Result' = $result }
}
SetScript = {
try
{
$name = $using:VmName
$mount = Mount-VHD -Path "$using:targetVMPath\$name\$name-OSDisk.vhdx" -Passthru -ErrorAction Stop
Start-Sleep -Seconds 2
$driveLetter = $mount | Get-Disk | Get-Partition | Get-Volume | Where-Object DriveLetter | Select-Object -ExpandProperty DriveLetter
New-Item -Path $("$driveLetter" + ":" + "\Temp") -ItemType Directory -Force -ErrorAction Stop
Copy-Item -Path "$using:sourcePath\branchData\$using:repoName-$using:branch\helpers\Install-AzsRolesandFeatures.ps1" -Destination $("$driveLetter" + ":" + "\Temp") -Force -ErrorAction Stop
New-BasicUnattendXML -ComputerName $name -LocalAdministratorPassword $($using:Admincreds).Password -Domain $using:DomainName -Username $using:Admincreds.Username `
-Password $($using:Admincreds).Password -JoinDomain $using:DomainName -AutoLogonCount 1 -OutputPath "$using:targetVMPath\$name" -Force `
-PowerShellScriptFullPath 'c:\temp\Install-AzsRolesandFeatures.ps1' -ErrorAction Stop
Copy-Item -Path "$using:targetVMPath\$name\Unattend.xml" -Destination $("$driveLetter" + ":" + "\Windows\system32\SysPrep") -Force -ErrorAction Stop
Start-Sleep -Seconds 2
}
finally
{
DisMount-VHD -Path "$using:targetVMPath\$name\$name-OSDisk.vhdx"
}
Start-VM -Name $name
}
TestScript = {
# Create and invoke a scriptblock using the $GetScript automatic variable, which contains a string representation of the GetScript.
$state = [scriptblock]::Create($GetScript).Invoke()
return $state.Result
}
DependsOn = "[xVhd]NewOSDisk-$vmname", "[archive]Extract branch files"
}
}
}
file "VM-Folder-$wacVMName"
{
Ensure = 'Present'
DestinationPath = "$targetVMPath\$wacVMName"
Type = 'Directory'
DependsOn = "[File]folder-vms"
}
xVhd "NewOSDisk-$wacVMName"
{
Ensure = 'Present'
Name = "$wacVMName-OSDisk.vhdx"
Path = "$targetVMPath\$wacVMName"
Generation = 'vhdx'
ParentPath = $azsHciVhdPath
Type = 'Differencing'
DependsOn = "[xVMSwitch]$vSwitchNameMgmt", "[script]prepareVHDX", "[file]VM-Folder-$wacVMName"
}
xVMHyperV "VM-$wacVMName"
{
Ensure = 'Present'
Name = $wacVMName
VhdPath = "$targetVMPath\$wacVMName\$wacVMName-OSDisk.vhdx"
Path = $targetVMPath
Generation = 2
StartupMemory = 2GB
MinimumMemory = 2GB
MaximumMemory = 8GB
ProcessorCount = 2
DependsOn = "[xVhd]NewOSDisk-$wacVMName"
}
xVMNetworkAdapter "remove default Network Adapter on VM-$wacVMName"
{
Ensure = 'Absent'
Id = "Network Adapter"
Name = "Network Adapter"
SwitchName = $vSwitchNameMgmt
VMName = $wacVMName
DependsOn = "[xVMHyperV]VM-$wacVMName"
}
xVMNetworkAdapter "New Network Adapter Management for VM-$wacVMName"
{
Id = "$wacVMName-Management"
Name = "$wacVMName-Management"
SwitchName = $vSwitchNameMgmt
VMName = $wacVMName
NetworkSetting = xNetworkSettings {
IpAddress = "192.168.0.100"
Subnet = "255.255.255.0"
DefaultGateway = "192.168.0.1"
DnsServer = "192.168.0.1"
}
Ensure = 'Present'
DependsOn = "[xVMHyperV]VM-$wacVMName"
}
Script "UnattendXML for $wacVMName"
{
GetScript = {
$name = $using:wacVMName
$result = Test-Path -Path "$using:targetVMPath\$name\Unattend.xml"
return @{ 'Result' = $result }
}
SetScript = {
try
{
$name = $using:wacVMName
$mount = Mount-VHD "$using:targetVMPath\$name\$name-OSDisk.vhdx" -Passthru -ErrorAction Stop
Start-Sleep -Seconds 2
$driveLetter = $mount | Get-Disk | Get-Partition | Get-Volume | Where-Object DriveLetter | Select-Object -ExpandProperty DriveLetter
New-Item -Path $("$driveLetter" + ":" + "\Temp") -ItemType Directory -Force -ErrorAction Stop
Copy-Item -Path "$using:sourcePath\branchData\$using:repoName-$using:branch\helpers\Install-WacUsingChoco.ps1" -Destination $("$driveLetter" + ":" + "\Temp") -Force -ErrorAction Stop
New-BasicUnattendXML -ComputerName $name -LocalAdministratorPassword $($using:Admincreds).Password -Domain $using:DomainName -Username $using:Admincreds.Username `
-Password $($using:Admincreds).Password -JoinDomain $using:DomainName -AutoLogonCount 1 -OutputPath "$using:targetVMPath\$name" -Force `
-IpCidr "192.168.0.100/24" -DnsServer '192.168.0.1' -NicNameForIPandDNSAssignments 'Ethernet' -PowerShellScriptFullPath 'c:\temp\Install-WacUsingChoco.ps1' -ErrorAction Stop
Copy-Item -Path "$using:targetVMPath\$name\Unattend.xml" -Destination $("$driveLetter" + ":" + "\Windows\system32\SysPrep") -Force -ErrorAction Stop
Copy-Item -Path "C:\Program Files\WindowsPowerShell\Modules\cChoco" -Destination $("$driveLetter" + ":" + "\Program Files\WindowsPowerShell\Modules") -Recurse -Force -ErrorAction Stop
Copy-Item -Path "C:\Program Files\WindowsPowerShell\Modules\ComputerManagementDsc" -Destination $("$driveLetter" + ":" + "\Program Files\WindowsPowerShell\Modules") -Recurse -Force -ErrorAction Stop
Start-Sleep -Seconds 2
}
finally
{
DisMount-VHD "$using:targetVMPath\$name\$name-OSDisk.vhdx"
}
Start-VM -Name $name
}
TestScript = {
# Create and invoke a scriptblock using the $GetScript automatic variable, which contains a string representation of the GetScript.
$state = [scriptblock]::Create($GetScript).Invoke()
return $state.Result
}
DependsOn = "[xVhd]NewOSDisk-$wacVMName", "[archive]Extract branch files"
}
cChocoInstaller InstallChoco
{
InstallDir = "c:\choco"
}
cChocoFeature allowGlobalConfirmation
{
FeatureName = "allowGlobalConfirmation"
Ensure = 'Present'
DependsOn = '[cChocoInstaller]installChoco'
}
cChocoFeature useRememberedArgumentsForUpgrades
{
FeatureName = "useRememberedArgumentsForUpgrades"
Ensure = 'Present'
DependsOn = '[cChocoInstaller]installChoco'
}
cChocoPackageInstaller "Install Chromium Edge"
{
Name = 'microsoft-edge'
Ensure = 'Present'
AutoUpgrade = $true
DependsOn = '[cChocoInstaller]installChoco'
}
cShortcut "Wac Shortcut"
{
Path = 'C:\Users\Public\Desktop\Windows Admin Center.lnk'
Target = 'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe'
Arguments = 'https://wac'
Icon = 'shell32.dll,34'
}
cShortcut "Document Shortcut"
{
Path = 'C:\Users\Public\Desktop\Poc Guide.lnk'
Target = 'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe'
Arguments = "https://yagmurs.github.io/$repoName"
Icon = 'shell32.dll,74'
}
cShortcut "Lab Guide Shortcut"
{
Path = 'C:\Users\Public\Desktop\Lab Script.lnk'
Target = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell_ise.exe'
Arguments = "$sourcePath\branchData\$repoName-$branch\scripts\$labScript"
}
}
}

Двоичные данные
DSC/AzureStackHCIHost.zip Normal file

Двоичный файл не отображается.

618
azuredeploy.json Normal file
Просмотреть файл

@ -0,0 +1,618 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"adminUsername": {
"type": "string",
"metadata": {
"description": "The name of the administrator account of nested VMs and domain"
}
},
"adminPassword": {
"type": "securestring",
"metadata": {
"description": "The password for the administrator account of nested VMs and domain"
}
},
"domainName": {
"type": "string",
"defaultValue": "corp.contoso.com",
"metadata": {
"description": "The FQDN of the Active Directory Domain to be created"
}
},
"dnsPrefix": {
"type": "string",
"metadata": {
"description": "The DNS prefix for the public IP address used by the Load Balancer"
}
},
"vmSize": {
"type": "string",
"defaultValue": "Standard_E16s_v4",
"allowedValues": [
"Standard_E8s_v4",
"Standard_E8ds_v4",
"Standard_E16s_v4",
"Standard_E16ds_v4",
"Standard_E20s_v4",
"Standard_E20ds_v4",
"Standard_E32s_v4",
"Standard_E32ds_v4",
"Standard_E48s_v4",
"Standard_E48ds_v4",
"Standard_E64s_v4",
"Standard_E64ds_v4",
"Standard_E8s_v3",
"Standard_E16s_v3",
"Standard_E20s_v3",
"Standard_E32s_v3",
"Standard_E48s_v3",
"Standard_E64s_v3",
"Standard_D16s_v4",
"Standard_D16ds_v4",
"Standard_D32s_v4",
"Standard_D32ds_v4",
"Standard_D48s_v4",
"Standard_D48ds_v4",
"Standard_D64s_v4",
"Standard_D64ds_v4",
"Standard_D16s_v3",
"Standard_D32s_v3",
"Standard_D48s_v3",
"Standard_D64s_v3"
],
"metadata": {
"description": "Size of the VM that supports Nested virtualization"
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
},
"virtualMachineName": {
"type": "string",
"defaultValue": "dcVM",
"metadata": {
"description": "Virtual machine name."
}
},
"privateIPAddress": {
"type": "string",
"defaultValue": "10.0.0.4",
"metadata": {
"description": "Private IP address for Azure VM, will be used as DNS address for vNet."
}
},
"virtualNetworkAddressRange": {
"type": "string",
"defaultValue": "10.0.0.0/16",
"metadata": {
"description": "Virtual network address range."
}
},
"subnetRange": {
"type": "string",
"defaultValue": "10.0.0.0/24",
"metadata": {
"description": "Subnet IP range."
}
},
"vmStoreDiskSize": {
"type": "int",
"defaultValue": 512,
"metadata": {
"description": "Azure VM additional disk size for hosting Azure Stack HCI VMs amount in GB"
}
},
"aksHciScenario": {
"type": "string",
"defaultValue": "onAzureVMDirectly",
"allowedValues": [
"onAzureVMDirectly",
"onNestedAzureStackHciClusteronAzureVM"
],
"metadata": {
"description": "Select the scenario if Aks Hci will be deployed on a nested cluster or on top of Azure VM"
}
},
"azsHCIHostCount": {
"type": "int",
"defaultValue": 3,
"metadata": {
"description": "How many Azure Stack HCI nested hosts to be created within the Azure VM."
}
},
"azsHCIHostMemory": {
"type": "int",
"defaultValue": 32,
"metadata": {
"description": "Azure Stack HCI memory amount in GB"
}
},
"autoShutdown": {
"type": "string",
"defaultValue": "Enabled",
"allowedValues": [
"Enabled",
"Disabled"
],
"metadata": {
"description": "Configure Auto shutdown state"
}
},
"autoShutdownTime": {
"type": "string",
"defaultValue": "0200",
"minLength": 4,
"maxLength": 4,
"metadata": {
"description": "The time at which VMs will be automatically shutdown (24h HHmm format)."
}
},
"autoShutdownTimeZone": {
"type": "string",
"defaultValue": "UTC",
"allowedValues": [
"Dateline Standard Time",
"UTC-11",
"Aleutian Standard Time",
"Hawaiian Standard Time",
"Marquesas Standard Time",
"Alaskan Standard Time",
"UTC-09",
"Pacific Standard Time (Mexico)",
"UTC-08",
"Pacific Standard Time",
"US Mountain Standard Time",
"Mountain Standard Time (Mexico)",
"Mountain Standard Time",
"Central America Standard Time",
"Central Standard Time",
"Easter Island Standard Time",
"Central Standard Time (Mexico)",
"Canada Central Standard Time",
"SA Pacific Standard Time",
"Eastern Standard Time (Mexico)",
"Eastern Standard Time",
"Haiti Standard Time",
"Cuba Standard Time",
"US Eastern Standard Time",
"Turks And Caicos Standard Time",
"Paraguay Standard Time",
"Atlantic Standard Time",
"Venezuela Standard Time",
"Central Brazilian Standard Time",
"SA Western Standard Time",
"Pacific SA Standard Time",
"Newfoundland Standard Time",
"Tocantins Standard Time",
"E. South America Standard Time",
"SA Eastern Standard Time",
"Argentina Standard Time",
"Greenland Standard Time",
"Montevideo Standard Time",
"Magallanes Standard Time",
"Saint Pierre Standard Time",
"Bahia Standard Time",
"UTC-02",
"Mid-Atlantic Standard Time",
"Azores Standard Time",
"Cape Verde Standard Time",
"UTC",
"GMT Standard Time",
"Greenwich Standard Time",
"Sao Tome Standard Time",
"Morocco Standard Time",
"W. Europe Standard Time",
"Central Europe Standard Time",
"Romance Standard Time",
"Central European Standard Time",
"W. Central Africa Standard Time",
"Jordan Standard Time",
"GTB Standard Time",
"Middle East Standard Time",
"Egypt Standard Time",
"E. Europe Standard Time",
"Syria Standard Time",
"West Bank Standard Time",
"South Africa Standard Time",
"FLE Standard Time",
"Israel Standard Time",
"Kaliningrad Standard Time",
"Sudan Standard Time",
"Libya Standard Time",
"Namibia Standard Time",
"Arabic Standard Time",
"Turkey Standard Time",
"Arab Standard Time",
"Belarus Standard Time",
"Russian Standard Time",
"E. Africa Standard Time",
"Iran Standard Time",
"Arabian Standard Time",
"Astrakhan Standard Time",
"Azerbaijan Standard Time",
"Russia Time Zone 3",
"Mauritius Standard Time",
"Saratov Standard Time",
"Georgian Standard Time",
"Volgograd Standard Time",
"Caucasus Standard Time",
"Afghanistan Standard Time",
"West Asia Standard Time",
"Ekaterinburg Standard Time",
"Pakistan Standard Time",
"Qyzylorda Standard Time",
"India Standard Time",
"Sri Lanka Standard Time",
"Nepal Standard Time",
"Central Asia Standard Time",
"Bangladesh Standard Time",
"Omsk Standard Time",
"Myanmar Standard Time",
"SE Asia Standard Time",
"Altai Standard Time",
"W. Mongolia Standard Time",
"North Asia Standard Time",
"N. Central Asia Standard Time",
"Tomsk Standard Time",
"China Standard Time",
"North Asia East Standard Time",
"Singapore Standard Time",
"W. Australia Standard Time",
"Taipei Standard Time",
"Ulaanbaatar Standard Time",
"Aus Central W. Standard Time",
"Transbaikal Standard Time",
"Tokyo Standard Time",
"North Korea Standard Time",
"Korea Standard Time",
"Yakutsk Standard Time",
"Cen. Australia Standard Time",
"AUS Central Standard Time",
"E. Australia Standard Time",
"AUS Eastern Standard Time",
"West Pacific Standard Time",
"Tasmania Standard Time",
"Vladivostok Standard Time",
"Lord Howe Standard Time",
"Bougainville Standard Time",
"Russia Time Zone 10",
"Magadan Standard Time",
"Norfolk Standard Time",
"Sakhalin Standard Time",
"Central Pacific Standard Time",
"Russia Time Zone 11",
"New Zealand Standard Time",
"UTC+12",
"Fiji Standard Time",
"Kamchatka Standard Time",
"Chatham Islands Standard Time",
"UTC+13",
"Tonga Standard Time",
"Samoa Standard Time",
"Line Islands Standard Time"
],
"minLength": 2,
"metadata": {
"description": "Time zone of the virtual machines. Type \"[TimeZoneInfo]::GetSystemTimeZones().Id\" in PowerShell to get the list."
}
},
"enableHybridBenefitServerLicenses": {
"type": "string",
"allowedValues": [
"Yes",
"No"
],
"defaultValue": "No",
"metadata": {
"description": "Enable Azure Hybrid Benefit to use your on-premises Windows Server licenses and reduce cost. See https://docs.microsoft.com/en-us/azure/virtual-machines/windows/hybrid-use-benefit-licensing for more information."
}
},
"branch": {
"type": "string",
"defaultValue": "master",
"metadata": {
"description": "for branch selection leave master if you are not the contributor and developing the ARM template"
}
}
},
"variables": {
"dscUri": "[concat('https://github.com/Azure/AksHcionAzureVM/raw/', parameters('branch'), '/DSC/AzureStackHCIHost.zip')]",
"_artifactsLocation": "[concat('https://raw.githubusercontent.com/', 'Azure/AksHcionAzureVM/', parameters('branch'), '/')]",
"networkSecurityGroupName": "[concat(parameters('virtualMachineName'),'-nsg')]",
"publicIpAddressName": "[concat(parameters('virtualMachineName'),'-pip')]",
"virtualNetworkName": "[concat(parameters('virtualMachineName'),'-vnet')]",
"networkInterfaceName": "[concat(parameters('virtualMachineName'),'-nic')]",
"subnetName": "[concat(parameters('virtualMachineName'),'-subnet')]"
},
"resources": [
{
"type": "Microsoft.Network/publicIPAddresses",
"apiVersion": "2020-05-01",
"name": "[variables('publicIPAddressName')]",
"location": "[parameters('location')]",
"properties": {
"publicIPAllocationMethod": "Dynamic",
"dnsSettings": {
"domainNameLabel": "[parameters('dnsPrefix')]"
}
}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-06-01",
"name": "VNet",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[uri(variables('_artifactsLocation'), concat('nestedtemplates/vnet.json'))]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"virtualNetworkName": {
"value": "[variables('virtualNetworkName')]"
},
"virtualNetworkAddressRange": {
"value": "[parameters('virtualNetworkAddressRange')]"
},
"subnetName": {
"value": "[variables('subnetName')]"
},
"subnetRange": {
"value": "[parameters('subnetRange')]"
},
"location": {
"value": "[parameters('location')]"
}
}
}
},
{
"type": "Microsoft.Network/networkInterfaces",
"apiVersion": "2020-05-01",
"name": "[variables('networkInterfaceName')]",
"location": "[parameters('location')]",
"dependsOn": [
"VNet",
"[concat('Microsoft.Network/publicIpAddresses/', variables('publicIpAddressName'))]",
"[concat('Microsoft.Network/networkSecurityGroups/', variables('networkSecurityGroupName'))]"
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"privateIPAllocationMethod": "Static",
"privateIPAddress": "[parameters('privateIPAddress')]",
"subnet": {
"id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('virtualNetworkName'), variables('subnetName'))]"
},
"publicIPAddress": {
"id": "[resourceId(resourceGroup().name,'Microsoft.Network/publicIpAddresses', variables('publicIpAddressName'))]"
}
}
}
],
"networkSecurityGroup": {
"id": "[resourceId(resourceGroup().name, 'Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
}
}
},
{
"type": "Microsoft.Network/networkSecurityGroups",
"name": "[variables('networkSecurityGroupName')]",
"apiVersion": "2020-05-01",
"location": "[parameters('location')]",
"properties": {
"securityRules": [
{
"name": "default-allow-rdp",
"properties": {
"priority": 1000,
"sourceAddressPrefix": "*",
"protocol": "Tcp",
"destinationPortRange": "3389",
"access": "Allow",
"direction": "Inbound",
"sourcePortRange": "*",
"destinationAddressPrefix": "*"
}
}
]
}
},
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-06-01",
"name": "[parameters('virtualMachineName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[variables('networkInterfaceName')]"
],
"properties": {
"licenseType": "[if(equals(parameters('enableHybridBenefitServerLicenses'), 'Yes'), 'Windows_Server', json('null'))]",
"hardwareProfile": {
"vmSize": "[parameters('vmSize')]"
},
"osProfile": {
"computerName": "[parameters('virtualMachineName')]",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "MicrosoftWindowsServer",
"offer": "WindowsServer",
"sku": "2019-Datacenter",
"version": "latest"
},
"osDisk": {
"name": "[concat(parameters('virtualMachineName'),'-OSDisk')]",
"caching": "ReadOnly",
"createOption": "FromImage",
"managedDisk": {
"storageAccountType": "Standard_LRS"
}
},
"dataDisks": [
{
"name": "[concat(parameters('virtualMachineName'), '-DataDisk1')]",
"caching": "ReadWrite",
"createOption": "Empty",
"diskSizeGB": 20,
"managedDisk": {
"storageAccountType": "Standard_LRS"
},
"lun": 0
},
{
"name": "[concat(parameters('virtualMachineName'), '-DataDisk2')]",
"caching": "ReadWrite",
"createOption": "Empty",
"diskSizeGB": "[parameters('vmStoreDiskSize')]",
"managedDisk": {
"storageAccountType": "Premium_LRS"
},
"lun": 1
}
]
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces', variables('networkInterfaceName'))]"
}
]
},
"diagnosticsProfile": {
"bootDiagnostics": {
"enabled": true
}
}
},
"resources": [
{
"name": "AzureStackHCIHost",
"type": "extensions",
"apiVersion": "2019-07-01",
"location": "[parameters('location')]",
"dependsOn": [
"[parameters('virtualMachineName')]"
],
"properties": {
"publisher": "Microsoft.Powershell",
"type": "DSC",
"typeHandlerVersion": "2.19",
"autoUpgradeMinorVersion": true,
"settings": {
"ModulesUrl": "[variables('dscUri')]",
"ConfigurationFunction": "AzureStackHCIHost.ps1\\AzureStackHCIHost",
"Properties": {
"DomainName": "[parameters('domainName')]",
"AdminCreds": {
"UserName": "[parameters('adminUsername')]",
"Password": "PrivateSettingsRef:AdminPassword"
},
"azsHostCount": "[parameters('azsHCIHostCount')]",
"azsHCIHostMemory": "[parameters('azsHCIHostMemory')]",
"branch": "[parameters('branch')]",
"aksHciScenario": "[parameters('aksHciScenario')]"
}
},
"protectedSettings": {
"Items": {
"AdminPassword": "[parameters('adminPassword')]"
}
}
}
}
]
},
{
"condition": "[equals(parameters('autoShutdown'), 'Enabled')]",
"name": "autoshutdown",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-06-01",
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), 'AzureStackHCIHost')]"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[uri(variables('_artifactsLocation'), 'nestedtemplates/autoshutdown.json')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"location": {
"value": "[parameters('location')]"
},
"virtualMachineName": {
"value": "[parameters('virtualMachineName')]"
},
"autoShutdown": {
"value": "[parameters('autoShutdown')]"
},
"autoShutdownTime": {
"value": "[parameters('autoShutdownTime')]"
},
"autoShutdownTimeZone": {
"value": "[parameters('autoShutdownTimeZone')]"
}
}
}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-06-01",
"name": "UpdateVNetDNS",
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), 'AzureStackHCIHost')]"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[uri(variables('_artifactsLocation'), concat('nestedtemplates/vnet-with-dns-server.json'))]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"virtualNetworkName": {
"value": "[variables('virtualNetworkName')]"
},
"virtualNetworkAddressRange": {
"value": "[parameters('virtualNetworkAddressRange')]"
},
"subnetName": {
"value": "[variables('subnetName')]"
},
"subnetRange": {
"value": "[parameters('subnetRange')]"
},
"DNSServerAddress": {
"value": [
"[parameters('privateIPAddress')]"
]
},
"location": {
"value": "[parameters('location')]"
}
}
}
}
],
"outputs": {
"dscUri": {
"type": "string",
"value": "[variables('dscUri')]"
},
"branch": {
"type": "string",
"value": "[parameters('branch')]"
}
}
}

Просмотреть файл

@ -0,0 +1,60 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"adminUsername": {
"value": "adm01"
},
"domainName": {
"value": "corp.msft.fun"
},
"dnsPrefix": {
"value": "msftfundc"
},
"vmSize": {
"value": "Standard_E8s_v4"
},
"location": {
"value": "germanywestcentral"
},
"virtualMachineName": {
"value": "dc01"
},
"azsHCIHostCount": {
"value": 2
},
"virtualNetworkAddressRange": {
"value": "172.31.0.0/16"
},
"privateIPAddress": {
"value": "172.31.1.4"
},
"subnetRange": {
"value": "172.31.1.0/24"
},
"branch": {
"value": "master"
},
"azsHCIHostMemory": {
"value": 22
},
"vmStoreDiskSize": {
"value": 512
},
"enableHybridBenefitServerLicenses": {
"value": "Yes"
},
"autoShutdown": {
"value": "Enabled"
},
"autoShutdownTime": {
"value": "0200"
},
"autoShutdownTimeZone": {
"value": "UTC"
},
"aksHciScenario": {
"value": "onAzureVMDirectly"
}
}
}

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,992 @@
function Cleanup-VMs
{
[CmdletBinding(
DefaultParameterSetName = 'default',
SupportsShouldProcess,
ConfirmImpact = 'High'
)]
Param
(
[Parameter(ParameterSetName = 'default')]
[Parameter(Mandatory=$false)]
[Switch]
$AzureStackHciHostVMs,
[Parameter(ParameterSetName = 'default')]
[Parameter(Mandatory=$false)]
[Switch]
$WindowsAdminCenterVM,
[Parameter(ParameterSetName = 'default')]
[Parameter(Mandatory=$false)]
[Switch]
$DoNotRedeploy,
[Parameter(ParameterSetName = 'default')]
[Parameter(Mandatory=$false)]
[Switch]
$RemoveAllSourceFiles
)
Begin
{
#initializing variables
$domainName = (Get-ADDomain).DnsRoot
$dhcpScopeString = '192.168.0.0'
$sleep = 300
}
Process
{
if ($AzureStackHciHostVMs)
{
$AzureStackHCIClusterName = 'hci01'
$AzureStackHCIHosts = Get-VM "hpv*" -ErrorAction SilentlyContinue
$ouName = $AzureStackHCIClusterName
$servers = $AzureStackHCIHosts.Name + $AzureStackHCIClusterName
if ($AzureStackHCIHosts)
{
if ($PSCmdlet.ShouldProcess($AzureStackHCIHosts,'Turn off and Remove'))
{
Write-Verbose "[Cleanup-VMs]: Removing Azure Stack HCI hosts, cluster and related DHCP, DNS records and computer accounts"
#remove Azure Stack HCI hosts
$AzureStackHCIHosts | Stop-VM -TurnOff -Passthru | Remove-VM -Force
Remove-Item -Path $AzureStackHCIHosts.ConfigurationLocation -Recurse -Force
#remove Azure Stack HCI hosts DNS records, DHCP leases and Disable Computer Accounts
Write-Verbose "[Cleanup-VMs]: Removing Dns Records for $($AzureStackHCIHosts.Name + "." + "$domainname")"
$AzureStackHCIHosts.Name | ForEach-Object {Get-DnsServerResourceRecord -ZoneName $domainName -Name $_ -ErrorAction SilentlyContinue | Remove-DnsServerResourceRecord -ZoneName $domainName -Force}
Write-Verbose "[Cleanup-VMs]: Removing Dhcp lease for $($AzureStackHCIHosts.Name)"
$AzureStackHCIHosts.Name | ForEach-Object {Get-DhcpServerv4Lease -ScopeId $dhcpScopeString -ErrorAction SilentlyContinue | Where-Object hostname -like $_* | Remove-DhcpServerv4Lease}
Write-Verbose "[Cleanup-VMs]: Removing Dns Records for $($AzureStackHCIClusterName + "." + "$domainname")"
$AzureStackHCIClusterName | ForEach-Object {Get-DnsServerResourceRecord -ZoneName $domainName -Name $_ -ErrorAction SilentlyContinue | Remove-DnsServerResourceRecord -ZoneName $domainName -Force}
Write-Verbose "[Cleanup-VMs]: Removing Dhcp lease for $AzureStackHCIClusterName"
$AzureStackHCIClusterName | ForEach-Object {Get-DhcpServerv4Lease -ScopeId $dhcpScopeString -ErrorAction SilentlyContinue | Where-Object hostname -like $_* | Remove-DhcpServerv4Lease}
Write-Verbose "[Cleanup-VMs]: Removing AD Computer for $servers"
$servers | Get-ADComputer -ErrorAction SilentlyContinue | Remove-ADObject -Recursive -Confirm:$false
Write-Verbose "[Cleanup-VMs]: Removing the OU: $ouName"
Get-ADOrganizationalUnit -Filter * | where-object name -eq $ouName | Set-ADOrganizationalUnit -ProtectedFromAccidentalDeletion $false -PassThru | Remove-ADOrganizationalUnit -Recursive -Confirm:$false
}
}
}
if ($WindowsAdminCenterVM)
{
$wac = Get-VM wac -ErrorAction SilentlyContinue
if ($wac)
{
if ($PSCmdlet.ShouldProcess($wac,'Turn off and Remove'))
{
Write-Verbose "[Cleanup-VMs]: Removing Windows Center VM and related DHCP, DNS records and computer account"
#remove Windows Admin Center host
$wac | Stop-VM -TurnOff -Passthru | Remove-VM -Force
Remove-Item -Path $wac.ConfigurationLocation -Recurse -Force
#remove Windows Admin Center host DNS record, DHCP lease
Write-Verbose "[Cleanup-VMs]: Removing Dns Records for $($wac.Name + "." + "$domainname")"
Get-DnsServerResourceRecord -ZoneName $domainName -Name $wac.Name -ErrorAction SilentlyContinue | Remove-DnsServerResourceRecord -ZoneName $domainName -Force
Write-Verbose "[Cleanup-VMs]: Removing Dhcp lease for $($wac.Name)"
Get-DhcpServerv4Lease -ScopeId $dhcpScopeString -ErrorAction SilentlyContinue | Where-Object hostname -like $wac.Name | Remove-DhcpServerv4Lease
Write-Verbose "[Cleanup-VMs]: Removing AD Computer for $($wac.Name)"
$wac.name | Get-ADComputer | Remove-ADObject -Recursive -Confirm:$false
}
}
}
if ($RemoveAllSourceFiles) {
if ($PSCmdlet.ShouldProcess('PoC Source files','Remove'))
{
Remove-Item v:\ -Recurse -Force
}
}
if (-not ($DoNotRedeploy))
{
if ($PSCmdlet.ShouldProcess('Re-Apply DSC configuration to restore VMs','Apply'))
{
Write-Verbose "[Cleanup-VMs]: Recalling DSC config to restore default state."
Start-DscConfiguration -UseExisting -Wait -Force
Write-Verbose "[Cleanup-VMs]: DSC config re-applied, check for any error!"
if ($AzureStackHciHostVMs -or $WindowsAdminCenterVM)
{
Write-Verbose "[Cleanup-VMs]: Sleeping for $sleep seconds to make sure Azure Stack HCI hosts are reachable"
Start-Sleep -Seconds $sleep
Clear-DnsClientCache
}
}
}
Write-Verbose "[Prepare AD]: Creating computer accounts in AD if not exist and configuring delegations for Windows Admin Center"
Prepare-AdforAzsHciDeployment
}
End
{
}
}
function Prepare-AzsHciPackage
{
[CmdletBinding()]
Param
(
)
Begin
{
#variables
$targetDrive = "V:"
$sourcePath = "$targetDrive\source"
$aksSource = "$sourcePath\aksHciSource"
}
Process
{
#create source folder for AKS bits
New-Item -Path $aksSource -ItemType Directory -Force
#Download AKS on Azure Stack HCI tools if no exist
if (-not (Test-Path -Path "$aksSource\aks-hci-tools.zip" -ErrorAction SilentlyContinue))
{
Write-Verbose "[Prepare-AzsHciPackage]: Downloading AKS on Azure Stack HCI tools from https://aka.ms/aks-hci-download"
Start-BitsTransfer -Source https://aka.ms/aks-hci-download -Destination "$aksSource\aks-hci-tools.zip" -Confirm:$false
}
#unblock download file
Unblock-File -Path "$aksSource\aks-hci-tools.zip"
#Unzip download file if not unzipped
if (-not (Test-Path -Path "$aksSource\aks-hci-tools" -ErrorAction SilentlyContinue))
{
Write-Verbose "[Prepare-AzsHciPackage]: Unzip downloaded file: aks-hci-tools.zip"
Expand-Archive -Path "$aksSource\aks-hci-tools.zip" -DestinationPath "$aksSource\aks-hci-tools" -Force
}
#Unzip Powershell modules if not unzipped
if (-not (Test-Path -Path "$aksSource\aks-hci-tools\Powershell\Modules" -ErrorAction SilentlyContinue))
{
Write-Verbose "[Prepare-AzsHciPackage]: Unzip Aks Hci PowerShell module"
Expand-Archive -Path "$aksSource\aks-hci-tools\AksHci.Powershell.zip" -DestinationPath "$aksSource\aks-hci-tools\Powershell\Modules" -Force
}
}
End
{
}
}
function Prepare-AzureVMforAksHciDeployment
{
[CmdletBinding()]
Param
(
)
Begin
{
#variables
$targetDrive = "V:"
$sourcePath = "$targetDrive\source"
$aksSource = "$sourcePath\aksHciSource"
$aksHCITargetPath = "$targetDrive\AksHciMain"
}
Process
{
Prepare-AzsHciPackage
#Copy AksHCI modules to Azure Stack HCI hosts
$AzureStackHCIHosts.Name | ForEach-Object {Copy-Item "$aksSource\aks-hci-tools\Powershell\Modules" "c:\Program Files\WindowsPowershell\" -Recurse -Force}
New-Item -Path $aksHCITargetPath -ItemType Directory -Force
}
End
{
}
}
function Prepare-AdforAzsHciDeployment
{
[CmdletBinding()]
Param
(
)
Begin
{
#variables
$wac = "wac"
$AzureStackHCIHosts = Get-VM hpv*
$AzureStackHCIClusterName = "hci01"
$ouName = "hci01"
}
Process
{
#New organizational Unit for cluster
$dn = Get-ADOrganizationalUnit -Filter * | Where-Object name -eq $ouName
if (-not ($dn))
{
$dn = New-ADOrganizationalUnit -Name $ouName -PassThru
}
#Get Wac Computer Object
$wacObject = Get-ADComputer -Filter * | Where-Object name -eq wac
if (-not ($wacObject))
{
$wacObject = New-ADComputer -Name $wac -Enabled $false -PassThru
}
#Creates Azure Stack HCI hosts if not exist
if ($AzureStackHCIHosts.Name)
{
$AzureStackHCIHosts.Name | ForEach-Object {
$comp = Get-ADComputer -Filter * | Where-Object name -eq $_
if (-not ($comp))
{
New-ADComputer -Name $_ -Enabled $false -Path $dn -PrincipalsAllowedToDelegateToAccount $wacObject
}
else
{
$comp | Set-ADComputer -PrincipalsAllowedToDelegateToAccount $wacObject
$comp | Move-AdObject -TargetPath $dn
}
}
}
#Creates Azure Stack HCI Cluster CNO if not exist
$AzureStackHCIClusterObject = Get-ADComputer -Filter * | Where-Object name -eq $AzureStackHCIClusterName
if (-not ($AzureStackHCIClusterObject))
{
$AzureStackHCIClusterObject = New-ADComputer -Name $AzureStackHCIClusterName -Enabled $false -Path $dn -PrincipalsAllowedToDelegateToAccount $wacObject -PassThru
}
else
{
$AzureStackHCIClusterObject | Set-ADComputer -PrincipalsAllowedToDelegateToAccount $wacObject
$AzureStackHCIClusterObject | Move-AdObject -TargetPath $dn
}
#read OU DACL
$acl = Get-Acl -Path "AD:\$dn"
# Set properties to allow Cluster CNO to Full Control on the new OU
$principal = New-Object System.Security.Principal.SecurityIdentifier ($AzureStackHCIClusterObject).SID
$ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule($principal, [System.DirectoryServices.ActiveDirectoryRights]::GenericAll, [System.Security.AccessControl.AccessControlType]::Allow, [DirectoryServices.ActiveDirectorySecurityInheritance]::All)
#modify DACL
$acl.AddAccessRule($ace)
#Re-apply the modified DACL to the OU
Set-ACL -ACLObject $acl -Path "AD:\$dn"
}
End
{
}
}
Function Configure-AzsHciClusterRoles
{
[CmdletBinding()]
Param
(
)
begin
{
#initializing variables
$AzureStackHCIHosts = Get-VM hpv*
#Enable Roles
$rolesToEnable = @("File-Services", "FS-FileServer", "FS-Data-Deduplication", "BitLocker", "Data-Center-Bridging", "EnhancedStorage", "Failover-Clustering", "RSAT", "RSAT-Feature-Tools", "RSAT-DataCenterBridging-LLDP-Tools", "RSAT-Clustering", "RSAT-Clustering-PowerShell", "RSAT-Role-Tools", "RSAT-AD-Tools", "RSAT-AD-PowerShell", "RSAT-Hyper-V-Tools", "Hyper-V-PowerShell")
$rolesToDisable = @("telnet-client")
#new PsSession to
$psSession = New-PSSession -ComputerName $AzureStackHCIHosts.Name
}
process
{
Write-Verbose "Enabling/Disabling Roles and Features required on Azure Stack HCI Hosts"
Invoke-Command -Session $psSession -ScriptBlock {
$VerbosePreference=$using:VerbosePreference
if ($using:rolesToEnable.Count -gt 0)
{
Write-Verbose "Installing following required roles/features to Azure Stack HCI hosts"
$using:rolesToEnable | Write-Verbose
Install-WindowsFeature -Name $using:rolesToEnable
}
if ($using:rolesToDisable.Count -gt 0)
{
Write-Verbose "Removing following unnecessary roles/features from Azure Stack HCI hosts"
$using:rolesToDisable | Write-Verbose
Remove-WindowsFeature -Name $using:rolesToDisable
}
}
}
end
{
Remove-PSSession -Session $psSession
Remove-Variable -Name psSession
}
}
Function Configure-AzsHciClusterNetwork
{
[CmdletBinding(DefaultParameterSetName='Configure', SupportsShouldProcess=$true)]
param (
[Parameter(ParameterSetName='Configure')]
[Parameter(Mandatory=$false)]
[ValidateSet("HighAvailable","SingleAdapter","Dummy")]
[string]
$ManagementInterfaceConfig = "HighAvailable",
[Parameter(ParameterSetName='Configure')]
[Parameter(Mandatory=$false)]
[ValidateSet("OneVirtualSwitchforAllTraffic","OneVirtualSwitchforComputeOnly","TwoVirtualSwitches","Dummy")]
[string]
$ComputeAndStorageInterfaceConfig = "OneVirtualSwitchforAllTraffic",
[Parameter(ParameterSetName='Cleanup')]
[Parameter(Mandatory=$false)]
[switch]
$CleanupConfiguration,
[Parameter(ParameterSetName='Configure')]
[Parameter(Mandatory=$false)]
[switch]
$ForceCleanup
)
begin
{
#initializing variables
$AzureStackHCIHosts = Get-VM hpv*
$vSwitchNameMgmt = 'Management'
$vSwitchNameConverged = "Default Switch"
$vSwitchNameCompute = "Default Switch"
$vSwitchNameStorage = "StorageSwitch"
#Enable Roles
$rolesToEnable = @("File-Services", "FS-FileServer", "FS-Data-Deduplication", "BitLocker", "Data-Center-Bridging", "EnhancedStorage", "Failover-Clustering", "RSAT", "RSAT-Feature-Tools", "RSAT-DataCenterBridging-LLDP-Tools", "RSAT-Clustering", "RSAT-Clustering-PowerShell", "RSAT-Role-Tools", "RSAT-AD-Tools", "RSAT-AD-PowerShell", "RSAT-Hyper-V-Tools", "Hyper-V-PowerShell")
$rolesToDisable = @()
Clear-DnsClientCache
#Disable DHCP Scope to prevent IP address from DHCP
Set-DhcpServerv4Scope -ScopeId 192.168.100.0 -State InActive
#new PsSession to
$psSession = New-PSSession -ComputerName $AzureStackHCIHosts.Name
}
process
{
if ($cleanupConfiguration)
{
Write-Verbose "[Cleanup]: Current network configuration"
Invoke-Command -Session $psSession -ScriptBlock {
$vSwitch = Get-VMSwitch
$VerbosePreference=$using:VerbosePreference
Write-Verbose "[Cleanup]: Following vSwitch/es will be removed from Azure Stack HCI hosts"
if ($vSwitch)
{
$vSwitch.Name | Write-Verbose
}
if ($vSwitch.Name -contains $using:vSwitchNameMgmt)
{
Write-Warning -Message "[Cleanup]: $env:COMPUTERNAME Network connection will be interupted for couple of minutes, be patient!!"
}
$vSwitch | Remove-VMSwitch -Force
}
Clear-DnsClientCache
Write-Verbose "[Cleanup]: Scramble Nic names to prevent name conflict"
Invoke-Command -Session $psSession -ScriptBlock {
$i = get-random -Minimum 100000 -max 999999
Get-NetAdapter | foreach {Rename-NetAdapter -Name $_.Name -NewName $i; $i++}
}
Invoke-Command -Session $psSession -ScriptBlock {
$adapter = Get-NetAdapter | Where-Object status -eq "disabled"
$VerbosePreference=$using:VerbosePreference
if ($adapter)
{
Write-Verbose "[Cleanup]: Following adapters will be enabled on Azure Stack HCI hosts"
$adapter.Name | Write-Verbose
$adapter | Enable-NetAdapter -Confirm:$false -Passthru
}
}
Write-Verbose "[Cleanup]: Recalling DSC config to restore default state"
Start-DscConfiguration -UseExisting -Wait -Verbose:$false
}
else
{
$state = Invoke-Command -Session $psSession -ScriptBlock {
Get-NetAdapter -Name Management*
}
if ($ForceCleanup)
{
Write-Warning "Current configuration detected! ForceCleanup switch Enabled. Cleaning up"
Configure-AzsHciClusterNetwork -CleanupConfiguration
}
elseif ($state)
{
Write-Warning "Current configuration detected! Cleanup required"
Write-Host "Continue cleanup ? Continue without cleanup, recommended though 'n'o!!! Default action is cleanup. : " -Foregroundcolor Yellow -Nonewline
$continue = Read-Host
if ($continue -ne 'n' )
{
Configure-AzsHciClusterNetwork -CleanupConfiguration
}
else
{
Write-Warning "Current configuration detected however no Cleanup option is selected. You may face some errors"
Write-Warning "Sleep for 10 seconds to make sure it is not accidentialy entered. You can break execution using 'Crtl + C' to cancel configuration"
Start-Sleep 10
}
}
#Configure Management Network adapters
switch ($ManagementInterfaceConfig) {
"HighAvailable" {
Write-Verbose "[Configure ManagementInterfaceConfig]: HighAvailable - Configuring Management Interface"
Write-Warning -Message "[Configure ManagementInterfaceConfig]: Network connection will be interupted for couple of minutes, be patient!!"
Invoke-Command -Session $psSession -ScriptBlock {
$ipConfig = (
Get-NetAdapter -Physical | Get-NetAdapterBinding | Where-Object {$_.enabled -eq $true -and $_.DisplayName -eq 'Internet Protocol Version 4 (TCP/IPv4)'} |
Get-NetIPConfiguration | Where-Object IPv4DefaultGateway | Sort-Object IPv4Address
)
$netAdapters = Get-NetAdapter -Name ($ipConfig.InterfaceAlias)
$VerbosePreference=$using:VerbosePreference
$newAdapterNames = @()
for ($i = 1; $i -lt $netAdapters.count + 1; $i++)
{
$netAdapterName = $netAdapters[$i - 1].Name
if ($netAdapterName -ne $($using:vSwitchNameMgmt + " $i"))
{
$newAdapterNames += $($using:vSwitchNameMgmt + " $i")
Rename-NetAdapter -Name $netAdapterName -NewName $($using:vSwitchNameMgmt + " $i")
}
}
#try to suppress error message
New-VMSwitch -Name $using:vSwitchNameMgmt -AllowManagementOS $true -NetAdapterName $newAdapterNames -EnableEmbeddedTeaming $true
Rename-NetAdapter -Name "vEthernet `($using:vSwitchNameMgmt`)" -NewName $using:vSwitchNameMgmt
}
$mgmtSwitchName = $vSwitchNameMgmt
}
"SingleAdapter" {
Write-Verbose "[Configure ManagementInterfaceConfig]: SingleAdapter - Configuring Management Interface"
Invoke-Command -Session $psSession -ScriptBlock {
$ipConfig = (
Get-NetAdapter -Physical | Get-NetAdapterBinding | Where-Object {$_.enabled -eq $true -and $_.DisplayName -eq 'Internet Protocol Version 4 (TCP/IPv4)'} |
Get-NetIPConfiguration | Where-Object IPv4DefaultGateway | Sort-Object IPv4Address
)
$netAdapters = Get-NetAdapter -Name ($ipConfig.InterfaceAlias)
$VerbosePreference=$using:VerbosePreference
Rename-NetAdapter -Name "$($netAdapters[0].Name)" -NewName $($using:vSwitchNameMgmt + " 1")
Rename-NetAdapter -Name "$($netAdapters[1].Name)" -NewName $($using:vSwitchNameMgmt + " 2")
Disable-NetAdapter -Name $($using:vSwitchNameMgmt + " 2") -Confirm:$false
}
$mgmtSwitchName = $null
}
}
#Configure Compute And Storage Network adapters
switch ($ComputeAndStorageInterfaceConfig) {
"OneVirtualSwitchforAllTraffic" {
Write-Verbose "[Configure ComputeAndStorageInterfaces]: OneVirtualSwitchforAllTraffic - Configuring ComputeAndStorageInterfaces"
Invoke-Command -Session $psSession -ScriptBlock {
$ipConfig = (
Get-NetAdapter -Physical | Where-Object status -ne disabled | Get-NetAdapterBinding | Where-Object {$_.enabled -eq $true -and $_.DisplayName -eq 'Internet Protocol Version 4 (TCP/IPv4)'} |
Get-NetIPConfiguration | Where-Object {$_.IPv4DefaultGateway -eq $null -and $_.IPv4Address.Ipaddress -like "192.168.25*"} | Sort-Object IPv4Address
)
$netAdapters = Get-NetAdapter -Name ($ipConfig.InterfaceAlias)
$VerbosePreference=$using:VerbosePreference
New-VMSwitch -Name $using:vSwitchNameConverged -NetAdapterName $netAdapters.Name -EnableEmbeddedTeaming $true -AllowManagementOS $false
for ($i = 1; $i -lt $netAdapters.Count + 1; $i++)
{
$adapterName = "smb " + $i
Add-VMNetworkAdapter -ManagementOS -SwitchName $using:vSwitchNameConverged -Name $adapterName
$vNic = Rename-NetAdapter -Name "vEthernet `($adapterName`)" -NewName $adapterName -PassThru
$pNic = Rename-NetAdapter -Name $netAdapters[$i - 1].Name -NewName $($using:vSwitchNameConverged + " $i") -PassThru
New-NetIPAddress -IPAddress $ipconfig[$i - 1].ipv4Address.Ipaddress -InterfaceAlias $vNic.Name -AddressFamily IPv4 -PrefixLength $ipconfig[$i - 1].ipv4Address.prefixlength | Out-Null
$sleep = 5
do
{
Write-Verbose "Waiting for NICs $($vNic.Name) and $($pNic.Name) to come 'up' for $sleep seconds"
Start-Sleep -Seconds $sleep
}
until ((Get-NetAdapter -Name $vNic.Name | Where-Object status -eq "up") -and (Get-NetAdapter -Name $pNic.Name | Where-Object status -eq "up"))
Write-Verbose "Setting up $($vNic.Name) and $($pNic.Name) for VMNetworkAdapterTeamMapping"
Set-VMNetworkAdapterTeamMapping -ManagementOS -VMNetworkAdapterName $vnic.Name -PhysicalNetAdapterName $pNic.Name
}
}
$computeSwitchName = $vSwitchNameConverged
}
"OneVirtualSwitchforComputeOnly" {
Write-Verbose "[Configure ComputeAndStorageInterfaces]: OneVirtualSwitchforComputeOnly - Configuring ComputeAndStorageInterfaces"
Invoke-Command -Session $psSession -ScriptBlock {
$ipConfigCompute = (
Get-NetAdapter -Physical | Where-Object status -ne disabled | Get-NetAdapterBinding | ? {$_.enabled -eq $true -and $_.DisplayName -eq 'Internet Protocol Version 4 (TCP/IPv4)'} |
Get-NetIPConfiguration | Where-Object {($_.IPv4DefaultGateway -eq $null) -and ($_.IPv4Address.Ipaddress -like "192.168.251.*" -or $_.IPv4Address.Ipaddress -like "192.168.252.*")} |
Sort-Object IPv4Address
)
$netAdaptersCompute = Get-NetAdapter -Name ($ipConfigCompute.InterfaceAlias)
$ipConfigStorage = (
Get-NetAdapter -Physical | Where-Object status -ne disabled | Get-NetAdapterBinding | ? {$_.enabled -eq $true -and $_.DisplayName -eq 'Internet Protocol Version 4 (TCP/IPv4)'} |
Get-NetIPConfiguration | Where-Object {($_.IPv4DefaultGateway -eq $null) -and ($_.IPv4Address.Ipaddress -like "192.168.253.*" -or $_.IPv4Address.Ipaddress -like "192.168.254.*")} |
Sort-Object IPv4Address
)
#$ipConfigStorage = (Get-NetAdapter -Physical | Where-Object status -ne disabled | Get-NetIPConfiguration | Where-Object {($_.IPv4DefaultGateway -eq $null) -and ($_.IPv4Address.Ipaddress -like "192.168.253.*" -or $_.IPv4Address.Ipaddress -like "192.168.254.*")})
$netAdaptersStorage = Get-NetAdapter -Name ($ipConfigStorage.InterfaceAlias)
$VerbosePreference=$using:VerbosePreference
Write-Verbose "[New SET switch]: $($using:vSwitchNameCompute) with following members"
Write-Verbose "$($netAdaptersCompute.Name)"
New-VMSwitch -Name $using:vSwitchNameCompute -NetAdapterName $netAdaptersCompute.Name -EnableEmbeddedTeaming $true -AllowManagementOS $false
for ($i = 1; $i -lt $netAdaptersCompute.Count + 1; $i++){
Write-Verbose "[Rename NIC]: $($netAdaptersCompute[$i - 1].Name) to $($using:vSwitchNameCompute + " $i")"
$pNic = Rename-NetAdapter -Name $netAdaptersCompute[$i - 1].Name -NewName $($using:vSwitchNameCompute + " $i") -PassThru
}
for ($i = 1; $i -lt $netAdaptersStorage.Count + 1; $i++)
{
$adapterName = "smb " + $i
Write-Verbose "[Rename NIC]: $($netAdaptersStorage[$i - 1].Name) to $adapterName"
$pNic = Rename-NetAdapter -Name $netAdaptersStorage[$i - 1].Name -NewName $adapterName -PassThru
}
}
$computeSwitchName = $vSwitchNameCompute
}
"TwoVirtualSwitches" {
Write-Verbose "[Configure ComputeAndStorageInterfaces]: TwoVirtualSwitches - Configuring ComputeAndStorageInterfaces"
Invoke-Command -Session $psSession -ScriptBlock {
$ipConfigCompute = (
Get-NetAdapter -Physical | Where-Object status -ne disabled | Get-NetAdapterBinding | Where-Object {$_.enabled -eq $true -and $_.DisplayName -eq 'Internet Protocol Version 4 (TCP/IPv4)'} |
Get-NetIPConfiguration | Where-Object {($_.IPv4DefaultGateway -eq $null) -and ($_.IPv4Address.Ipaddress -like "192.168.251.*" -or $_.IPv4Address.Ipaddress -like "192.168.252.*")} |
Sort-Object IPv4Address
)
$netAdaptersCompute = Get-NetAdapter -Name ($ipConfigCompute.InterfaceAlias)
$ipConfigStorage = (
Get-NetAdapter -Physical | Where-Object status -ne disabled | Get-NetAdapterBinding | ? {$_.enabled -eq $true -and $_.DisplayName -eq 'Internet Protocol Version 4 (TCP/IPv4)'} |
Get-NetIPConfiguration | Where-Object {($_.IPv4DefaultGateway -eq $null) -and ($_.IPv4Address.Ipaddress -like "192.168.253.*" -or $_.IPv4Address.Ipaddress -like "192.168.254.*")} |
Sort-Object IPv4Address
)
$netAdaptersStorage = Get-NetAdapter -Name ($ipConfigStorage.InterfaceAlias)
$VerbosePreference=$using:VerbosePreference
Write-Verbose "[New SET switch]: $($using:vSwitchNameCompute) with following members"
New-VMSwitch -Name $using:vSwitchNameCompute -NetAdapterName $netAdaptersCompute.Name -EnableEmbeddedTeaming $true -AllowManagementOS $false
for ($i = 1; $i -lt $netAdaptersCompute.Count + 1; $i++)
{
Write-Verbose "[Rename NIC]: $($netAdaptersCompute[$i - 1].Name) to $adapterName"
$pNic = Rename-NetAdapter -Name $netAdaptersCompute[$i - 1].Name -NewName $($using:vSwitchNameCompute + " $i") -PassThru
}
Write-Verbose "[New SET switch]: $($using:vSwitchNameStorage) with following members"
New-VMSwitch -Name $using:vSwitchNameStorage -NetAdapterName $netAdaptersStorage.Name -EnableEmbeddedTeaming $true -AllowManagementOS $false
for ($i = 1; $i -lt $netAdaptersStorage.Count + 1; $i++)
{
$adapterName = "smb " + $i
Add-VMNetworkAdapter -ManagementOS -SwitchName $using:vSwitchNameStorage -Name $adapterName
#Start-Sleep 4
Write-Verbose "[Rename NIC]: $($netAdaptersStorage[$i - 1].Name) to $adapterName"
$vNic = Rename-NetAdapter -Name "vEthernet `($adapterName`)" -NewName $adapterName -PassThru
$pNic = Rename-NetAdapter -Name $netAdaptersStorage[$i - 1].Name -NewName $($using:vSwitchNameStorage + " $i") -PassThru
New-NetIPAddress -IPAddress $ipConfigStorage[$i - 1].ipv4Address.Ipaddress -InterfaceAlias $vNic.Name -AddressFamily IPv4 -PrefixLength $ipConfigStorage[$i - 1].ipv4Address.prefixlength | Out-Null
$sleep = 5
do
{
Write-Verbose "Waiting for NICs $($vNic.Name) and $($pNic.Name) to come 'up' for $sleep seconds"
Start-Sleep -Seconds $sleep
}
until ((Get-NetAdapter -Name $vNic.Name | Where-Object status -eq "up") -and (Get-NetAdapter -Name $pNic.Name | Where-Object status -eq "up"))
Write-Verbose "Setting up vNIC: $($vNic.Name) and pNIC: $($pNic.Name) for VMNetworkAdapterTeamMapping"
Set-VMNetworkAdapterTeamMapping -ManagementOS -VMNetworkAdapterName $vnic.Name -PhysicalNetAdapterName $pNic.Name
}
}
$computeSwitchName = $vSwitchNameCompute
}
}
}
}
end
{
#Re-Enable DHCP Scope
Set-DhcpServerv4Scope -ScopeId 192.168.100.0 -State Active
Remove-PSSession -Session $psSession
Remove-Variable -Name psSession
@{
ManagementSwitch = $mgmtSwitchName
ComputeSwitch = $computeSwitchName
}
}
}
function Erase-AzsHciClusterDisks
{
[CmdletBinding()]
Param
(
)
Begin
{
#initializing variables
$AzureStackHCIHosts = Get-VM hpv*
$psSession = New-PSSession -ComputerName $AzureStackHCIHosts.Name
}
Process
{
Write-Verbose "Cleaning up previously configured S2D Disks"
Invoke-Command -Session $psSession -ScriptBlock {
Update-StorageProviderCache
Get-StoragePool | Where-Object IsPrimordial -eq $false | Set-StoragePool -IsReadOnly:$false -ErrorAction SilentlyContinue
Get-StoragePool | Where-Object IsPrimordial -eq $false | Get-VirtualDisk | Remove-VirtualDisk -Confirm:$false -ErrorAction SilentlyContinue
Get-StoragePool | Where-Object IsPrimordial -eq $false | Remove-StoragePool -Confirm:$false -ErrorAction SilentlyContinue
Get-PhysicalDisk | Reset-PhysicalDisk -ErrorAction SilentlyContinue
Get-Disk | Where-Object Number -ne $null | Where-Object IsBoot -ne $true | Where-Object IsSystem -ne $true | Where-Object PartitionStyle -ne RAW | Foreach-Object {
$_ | Set-Disk -isoffline:$false
$_ | Set-Disk -isreadonly:$false
$_ | Clear-Disk -RemoveData -RemoveOEM -Confirm:$false
$_ | Set-Disk -isreadonly:$true
$_ | Set-Disk -isoffline:$true
}
Get-Disk | Where-Object Number -Ne $Null | Where-Object IsBoot -Ne $True | Where-Object IsSystem -Ne $True | Where-Object PartitionStyle -Eq RAW | Group -NoElement -Property FriendlyName
} | Sort-Object -Property PsComputerName, Count
}
End
{
Remove-PSSession -Session $psSession
Remove-Variable -Name psSession
}
}
function Configure-AzsHciCluster
{
[CmdletBinding()]
Param
(
# Param1 help description
[Parameter(Mandatory=$true)]
$ClusterName
)
Begin
{
#initializing variables
$AzureStackHCIHosts = Get-VM hpv*
$cimSession = New-CimSession -ComputerName $AzureStackHCIHosts[0].Name
}
Process
{
Write-Verbose "Enabling Cluster: $ClusterName"
New-Cluster -Name $ClusterName -Node $AzureStackHCIHosts.Name -NoStorage -Force
Write-Verbose "Enabling Storage Spaces Direct on Cluster: $ClusterName"
Enable-ClusterStorageSpacesDirect -PoolFriendlyName "Cluster Storage Pool" -CimSession $cimSession -Confirm:$false -SkipEligibilityChecks -ErrorAction SilentlyContinue
}
End
{
#clean up variables
Remove-CimSession -CimSession $cimSession
Remove-Variable -Name cimSession
}
}
function Prepare-AzsHciClusterforAksHciDeployment
{
[CmdletBinding()]
Param
(
)
Begin
{
#variables
$targetDrive = "V:"
$sourcePath = "$targetDrive\source"
$aksSource = "$sourcePath\aksHciSource"
$AzureStackHCIHosts = Get-VM hpv*
$AzureStackHCIClusterName = 'Hci01'
$azSHCICSV = "AksHCIMain"
$azSHCICSVPath = "c:\ClusterStorage\$azSHCICSV"
}
Process
{
Prepare-AzsHciPackage
#Update NuGet Package provider on AzsHci Host
Invoke-Command -ComputerName $AzureStackHCIHosts.Name -ScriptBlock {
Install-PackageProvider -Name NuGet -Force
Install-Module -Name PowershellGet -Force -Confirm:$false -SkipPublisherCheck
}
#Copy AksHCI modules to Azure Stack HCI hosts
$AzureStackHCIHosts.Name | ForEach-Object {Copy-Item "$aksSource\aks-hci-tools\Powershell\Modules" "\\$_\c$\Program Files\WindowsPowershell\" -Recurse -Force}
#create Cluster Shared Volume for AksHCI and Enable Deduplication
#New-Volume -CimSession "$($AzureStackHCIHosts[0].Name)" -FriendlyName $azSHCICSV -FileSystem CSVFS_ReFS -StoragePoolFriendlyName S2D* -Size 1.3TB
New-Volume -CimSession $AzureStackHCIClusterName -FriendlyName $azSHCICSV -FileSystem CSVFS_ReFS -StoragePoolFriendlyName cluster* -Size 1.3TB
Enable-DedupVolume -CimSession $AzureStackHCIClusterName -Volume $azSHCICSVPath
Enable-DedupVolume -CimSession $AzureStackHCIClusterName -Volume $azSHCICSVPath -UsageType HyperV -DataAccess
}
End
{
}
}
function Start-AksHciPoC
{
param (
)
begin
{
#Initialize variables
$AzureStackHCIHosts = Get-VM -Name hpv*
$sleep = 20
}
process
{
$CleanupVMsSelection = Show-Menu -Items @(
'Do NOT Cleanup ( !!Default selection!! )',
'Yes, Cleanup Azure Stack HCI host VMs and Wac VMs',
'Yes, Cleanup Windows Admin Center VM Only!',
'Yes, Cleanup Azure Stack HCI host VMs Only!',
'Yes, Cleanup All VMs for both HCI host VMs, Aks Hci VMs!'
) -Title 'Cleanup VMs option to start from scratch?' -Description 'This option will destroy All VMs or selected VMs.'
$RolesConfigurationProfileSelection = Show-Menu -Items @(
'Do NOT install any Roles ( !!Default selection!! )',
'Install required roles to Azure Stack HCI Hosts'
) -Title 'Azure Stack HCI Roles and Features Installation optionssndklajsdkljasdjasjdljasd' -Description 'Roles are installed by default. (Optional)'
$NetworkConfigurationProfileSelection = Show-Menu -Items @(
'High-available Management & One Virtual Switch for All Traffic ( !!Default selection!! )',
'High-available networks for Management & One Virtual Switch for Compute Only',
'High-available networks for Managament & Two Virtual Switches',
'Single Network Adapter for Management & One Virtual Switch for All Traffic',
'Single Network Adapter for Management & One Virtual Switch for Compute Only',
'Single Network Adapter for Management & Two Virtual Switches for Compute and Storage',
'High-available networks for Management & One Virtual Switch for All Traffic ( !!Also reset network config!! )',
'Single Network Adapter for Management & One Virtual Switch for Compute Only ( !!Also reset network config!! )',
'High-available networks for Managament & Two Virtual Switches ( !!Also reset network config!! )',
'Do NOT configure networks'
) -Title 'Azure Stack HCI Network Adapter Configuration options (SET Switch)' -Description ""
$DisksConfigurationProfileSelection = Show-Menu -Items @(
'Do NOT erase and cleanup ( !!Default selection!! )',
'Erase all drives'
) -Title 'Azure Stack HCI Disks cleanup options' -Description 'Please do so, if this is NOT first installation on top of clean environment. (Optional)'
$ClusterConfigurationProfileSelection = Show-Menu -Items @(
'Enable Cluster using default Name (Cluster Name: hci01) ( !!Default selection!! )',
'Do NOT Create Cluster yet.'
) -Title 'Azure Stack HCI Cluster options' -Description 'Install cluster using default name to prevent any misconfigurations'
$AksHciConfigurationProfileSelection = Show-Menu -Items @(
'Prepare for Aks Hci Deployment ( !!Default selection!! )',
'Do NOT Prepare for Aks Hci Deployment yet.'
) -Title 'Azure Stack HCI Cluster Aks Hci preparation options' -Description 'Prepare Azure Stack HCI Cluster with Aks Hci pre-requisites'
switch ($CleanupVMsSelection)
{
1 {Cleanup-VMs -AzureStackHciHostVMs -WindowsAdminCenterVM -Verbose; Prepare-AdforAzsHciDeployment}
2 {Cleanup-VMs -WindowsAdminCenterVM -Verbose}
3 {Cleanup-VMs -AzureStackHciHostVMs -Verbose; Prepare-AdforAzsHciDeployment}
4 {if ((Get-Vm * | Where-Object name -ne 'wac').count -gt 0){Uninstall-AksHci}; Cleanup-VMs -AzureStackHciHostVMs -Verbose; Prepare-AdforAzsHciDeployment}
Default {Write-Warning "[Cleanup-VMs]: No Cleanup selected."}
}
$cimSession = New-CimSession -ComputerName $AzureStackHCIHosts.name
do
{
Clear-DnsClientCache
Write-Verbose "Waiting for Azure Stack HCI hosts to finish initial DSC configuration for $sleep seconds" -Verbose
Start-Sleep -Seconds $sleep
}
while (((Get-DscLocalConfigurationManager -CimSession $cimSession -ErrorAction SilentlyContinue | Select-Object -ExpandProperty lcmstate) -contains "busy" -or (Get-DscLocalConfigurationManager -CimSession $cimSession -ErrorAction SilentlyContinue | Select-Object -ExpandProperty lcmstate) -contains "PendingConfiguration"))
switch ($RolesConfigurationProfileSelection)
{
1 {Configure-AzsHciClusterRoles -Verbose}
Default {Write-Warning "[Configure-AzsHciClusterRoles]: Not installing Roles and Features, assuming All Roles and Features required are already installed. Subsequent process may rely on Roles and Features Installation."}
}
switch ($NetworkConfigurationProfileSelection)
{
1 {Configure-AzsHciClusterNetwork -ManagementInterfaceConfig HighAvailable -Verbose -ComputeAndStorageInterfaceConfig OneVirtualSwitchforComputeOnly}
2 {Configure-AzsHciClusterNetwork -ManagementInterfaceConfig HighAvailable -Verbose -ComputeAndStorageInterfaceConfig TwoVirtualSwitches}
3 {Configure-AzsHciClusterNetwork -ManagementInterfaceConfig SingleAdapter -Verbose -ComputeAndStorageInterfaceConfig OneVirtualSwitchforAllTraffic}
4 {Configure-AzsHciClusterNetwork -ManagementInterfaceConfig SingleAdapter -Verbose -ComputeAndStorageInterfaceConfig OneVirtualSwitchforComputeOnly}
5 {Configure-AzsHciClusterNetwork -ManagementInterfaceConfig SingleAdapter -Verbose -ComputeAndStorageInterfaceConfig TwoVirtualSwitches}
6 {Configure-AzsHciClusterNetwork -ManagementInterfaceConfig HighAvailable -Verbose -ComputeAndStorageInterfaceConfig OneVirtualSwitchforAllTraffic -ForceCleanup}
7 {Configure-AzsHciClusterNetwork -ManagementInterfaceConfig SingleAdapter -Verbose -ComputeAndStorageInterfaceConfig OneVirtualSwitchforComputeOnly -ForceCleanup}
8 {Configure-AzsHciClusterNetwork -ManagementInterfaceConfig HighAvailable -Verbose -ComputeAndStorageInterfaceConfig TwoVirtualSwitches -ForceCleanup}
9 {Write-Warning "[Configure-AzsHciClusterNetwork]: Assuming Networks are already configured!"}
Default {Configure-AzsHciClusterNetwork -ManagementInterfaceConfig HighAvailable -Verbose -ComputeAndStorageInterfaceConfig OneVirtualSwitchforAllTraffic}
}
switch ($DisksConfigurationProfileSelection)
{
1 {Erase-AzsHciClusterDisks -Verbose}
default {Write-Warning "[Erase-AzsHciClusterDisks]: Assuming this is first installation on top of clean environment. Otherwise subsequent process may fail."}
}
switch ($ClusterConfigurationProfileSelection)
{
1 {Write-Warning "You may need to configure cluster manually!"}
Default {Configure-AzsHciCluster -ClusterName hci01 -Verbose}
}
switch ($AksHciConfigurationProfileSelection)
{
1 {Write-Warning "You may need to prepare Azure Stack HCI cluster for Aks Hci pre-requisites manually!"}
Default {Prepare-AzsHciClusterforAksHciDeployment -Verbose}
}
}
end
{
Remove-CimSession $cimSession
Remove-variable cimsession
}
}
function Show-Menu
{
[CmdletBinding()]
[OutputType([string])]
Param
(
[parameter(Mandatory=$true)]
[string[]]
$Items,
[parameter(Mandatory=$true)]
[string]
$Title,
[string]
$Description,
[int]
[ValidateRange(4,10)]
$MenuIndent = 4,
[System.ConsoleColor]
$ColorTitle = 'Green',
[System.ConsoleColor]
$ColorDescription = 'Yellow'
)
Begin
{
$titleLength = [math]::Round($Title.Length / 2)
$longest = [math]::Round(($items | ForEach-Object {$_.length} | Sort-Object -Descending | Select-Object -First 1) / 2)
if ($longest -lt $titleLength)
{
$longest = $titleLength
}
}
Process
{
Clear-Host
Write-Host $('=' * $(($longest + $MenuIndent) - $titleLength) + " " + "$Title" + " " + '=' * $(($longest + $MenuIndent) - $titleLength) ) -ForegroundColor Green
Write-Host ""
if ($Description)
{
Write-Host $(" " * $($MenuIndent - 2) + $Description) -ForegroundColor Yellow
Write-Host ""
}
for ($i = 0; $i -lt $items.count; $i++)
{
Write-Host "$(" " * $MenuIndent + "$i" + '. ' + $items[$i])"
}
Write-Host ""
Write-Host "Selection: " -ForegroundColor Green -NoNewline
$selection = Read-Host
if ([string]::IsNullOrEmpty($selection))
{
$selection = 0
}
return $selection
}
End
{
}
}

Просмотреть файл

@ -0,0 +1,38 @@
configuration AzSHciHost
{
Import-DscResource -ModuleName 'PSDesiredStateConfiguration'
node localhost
{
LocalConfigurationManager {
RebootNodeIfNeeded = $true
ActionAfterReboot = 'ContinueConfiguration'
ConfigurationMode = 'ApplyAndAutoCorrect'
ConfigurationModeFrequencyMins = 1440
}
WindowsFeatureSet "AzsHci Required Roles"
{
Ensure = 'Present'
Name = @("File-Services", "FS-FileServer", "FS-Data-Deduplication", "BitLocker", "Data-Center-Bridging", "EnhancedStorage", "Failover-Clustering", "RSAT", "RSAT-Feature-Tools", "RSAT-DataCenterBridging-LLDP-Tools", "RSAT-Clustering", "RSAT-Clustering-PowerShell", "RSAT-Role-Tools", "RSAT-AD-Tools", "RSAT-AD-PowerShell", "RSAT-Hyper-V-Tools", "Hyper-V-PowerShell")
}
}
}
$date = get-date -f yyyy-MM-dd
$logFile = Join-Path -Path "C:\temp" -ChildPath $('AzSHciHost-Transcipt-' + $date + '.log')
$DscConfigLocation = "c:\temp\AzSHciHost"
Start-Transcript -Path $logFile
Remove-DscConfigurationDocument -Stage Current, Previous, Pending -Force
AzSHciHost -OutputPath $DscConfigLocation
Set-DscLocalConfigurationManager -Path $DscConfigLocation -Verbose
Start-DscConfiguration -Path $DscConfigLocation -Wait -Verbose
Stop-Transcript
Logoff

Просмотреть файл

@ -0,0 +1,134 @@
configuration WindowsAdminCenter
{
Import-DscResource -ModuleName 'cChoco'
Import-DscResource -ModuleName 'ComputerManagementDsc'
node localhost
{
LocalConfigurationManager {
RebootNodeIfNeeded = $true
ActionAfterReboot = 'ContinueConfiguration'
ConfigurationMode = 'ApplyAndAutoCorrect'
ConfigurationModeFrequencyMins = 1440
}
cChocoInstaller InstallChoco
{
InstallDir = "c:\choco"
}
cChocoFeature allowGlobalConfirmation
{
FeatureName = "allowGlobalConfirmation"
Ensure = 'Present'
DependsOn = '[cChocoInstaller]installChoco'
}
cChocoFeature useRememberedArgumentsForUpgrades
{
FeatureName = "useRememberedArgumentsForUpgrades"
Ensure = 'Present'
DependsOn = '[cChocoInstaller]installChoco'
}
cChocoPackageInstaller "Install Windows Admin Center on 443"
{
Name = 'windows-admin-center'
Ensure = 'Present'
AutoUpgrade = $true
DependsOn = '[cChocoInstaller]installChoco'
Params = "'/Port:443'"
}
PendingReboot "reboot"
{
Name = 'reboot'
}
Script "Fake reboot"
{
TestScript = {
return (Test-Path HKLM:\SOFTWARE\RebootKey)
}
SetScript = {
New-Item -Path HKLM:\SOFTWARE\RebootKey -Force
$global:DSCMachineStatus = 1
}
GetScript = {
return @{result = 'result'}
}
DependsOn = "[cChocoPackageInstaller]Install Windows Admin Center on 443"
}
script "Windows Admin Center updater"
{
GetScript = {
# Specify the WAC gateway
$wac = "https://$env:COMPUTERNAME"
# Add the module to the current session
$module = "$env:ProgramFiles\Windows Admin Center\PowerShell\Modules\ExtensionTools\ExtensionTools.psm1"
Import-Module -Name $module -Verbose -Force
# List the WAC extensions
$extensions = Get-Extension $wac | Where-Object {$_.isLatestVersion -like 'False'}
$result = if ($extensions.count -gt 0) {$false} else {$true}
return @{
Wac = $WAC
extensions = $extensions
result = $result
}
}
TestScript = {
# Create and invoke a scriptblock using the $GetScript automatic variable, which contains a string representation of the GetScript.
$state = [scriptblock]::Create($GetScript).Invoke()
return $state.Result
}
SetScript = {
$state = [scriptblock]::Create($GetScript).Invoke()
$date = get-date -f yyyy-MM-dd
$logFile = Join-Path -Path "C:\Users\Public" -ChildPath $('WACUpdateLog-' + $date + '.log')
New-Item -Path $logFile -ItemType File -Force
ForEach($extension in $state.extensions)
{
Update-Extension $state.wac -ExtensionId $extension.Id -Verbose | Out-File -Append -FilePath $logFile -Force
}
# Delete log files older than 30 days
Get-ChildItem -Path "C:\Users\Public\WACUpdateLog*" -Recurse -Include @("*.log") | Where-Object { $_.CreationTime -lt (Get-Date).AddDays(-30)} | Remove-Item
}
DependsOn = "[Script]Fake reboot"
}
}
}
$date = get-date -f yyyy-MM-dd
$logFile = Join-Path -Path "C:\temp" -ChildPath $('WindowsAdminCenter-Transcipt-' + $date + '.log')
$DscConfigLocation = "c:\temp\WindowsAdminCenter"
Start-Transcript -Path $logFile
Remove-DscConfigurationDocument -Stage Current, Previous, Pending -Force
WindowsAdminCenter -OutputPath $DscConfigLocation
Set-DscLocalConfigurationManager -Path $DscConfigLocation -Verbose
Start-DscConfiguration -Path $DscConfigLocation -Wait -Verbose
Start-DscConfiguration -UseExisting -Wait -Verbose -Force
Stop-Transcript
Logoff

Двоичные данные
helpers/WindowsDeploymentHelper/0.0.1/WindowsDeploymentHelper.psd1 Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,371 @@
function New-BasicUnattendXML
{
[CmdletBinding(DefaultParameterSetName='basic')]
Param (
[Parameter(Mandatory=$true, ParameterSetName='print')]
[Parameter(Mandatory=$true, ParameterSetName='basic')]
[Parameter(Mandatory=$true, ParameterSetName='Join Domain')]
[String]$ComputerName,
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$true, ParameterSetName='Join Domain')]
[String]$Domain,
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$true, ParameterSetName='Join Domain')]
[String]$Username,
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$true, ParameterSetName='Join Domain')]
[SecureString]$Password,
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$true, ParameterSetName='basic')]
[Parameter(Mandatory=$true, ParameterSetName='Join Domain')]
[SecureString]$LocalAdministratorPassword,
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$true, ParameterSetName='Join Domain')]
[String]$JoinDomain,
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[validatescript({(([system.net.ipaddress]($_ -split '/' | Select-Object -First 1)).AddressFamily -match 'InterNetwork') -and (0..32 -contains ([int]($_ -split '/' | Select-Object -Last 1) )) })]
[String]$IpCidr,
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[String]$DefaultGateway,
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[String]$DnsServer,
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[String]$NicNameForIPandDNSAssignments,
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$true, ParameterSetName='basic')]
[Parameter(Mandatory=$true, ParameterSetName='Join Domain')]
[String]$OutputPath,
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[Switch]$Force,
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[System.Globalization.CultureInfo]$InputLocale = 'en-us',
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[System.Globalization.CultureInfo]$SystemLocale = 'en-us',
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[System.Globalization.CultureInfo]$UILanguage = 'en-us',
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[System.Globalization.CultureInfo]$UserLocale = 'en-us',
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[bool]$HideEULAPage = $true,
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[ValidateScript({$_ -in (Get-TimeZone -ListAvailable | Select-Object -ExpandProperty standardname)})]
[String]$TimeZone = 'GMT Standard Time',
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[ValidateRange(0,100)]
[int]$AutoLogonCount = 0,
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[String]$RegisteredOrganization = 'Azure Stack HCI on Azure VM',
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[String]$RegisteredOwner = 'Azure Stack HCI on Azure VM',
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[String]$PowerShellScriptFullPath,
[Parameter(Mandatory=$false, ParameterSetName='print')]
[Parameter(Mandatory=$false, ParameterSetName='basic')]
[Parameter(Mandatory=$false, ParameterSetName='Join Domain')]
[Switch]$PrintScreenOnly
)
$localAdministratorCreds = New-Object pscredential -ArgumentList Administrator, $LocalAdministratorPassword
$domainAdministratorCreds = New-Object pscredential -ArgumentList $Username, $Password
$LocalAdministratorPasswordClearText = $localAdministratorCreds.GetNetworkCredential().password
$domainAdministratorPasswordClearText = $domainAdministratorCreds.GetNetworkCredential().password
$encodedAdministratorPassword = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes(('{0}AdministratorPassword' -f $LocalAdministratorPasswordClearText)))
if ($JoinDomain)
{
$domainJoinerCreds = New-Object pscredential -ArgumentList Administrator, $LocalAdministratorPassword
$domainJoinerPasswordClearText = $domainJoinerCreds.GetNetworkCredential().password
$domainJoinXMLString = @"
<component name="Microsoft-Windows-UnattendedJoin" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Identification>
<Credentials>
<Domain>$Domain</Domain>
<Password>$domainJoinerPasswordClearText</Password>
<Username>$username</Username>
</Credentials>
<JoinDomain>$joinDomain</JoinDomain>
</Identification>
</component>
"@
}
else
{
$domainJoinXMLString = $null
}
$PowerShellStartupCmd = "%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -File $PowerShellScriptFullPath"
if ($AutoLogonCount -gt 0)
{
Write-Warning -Message '-AutoLogonCount places the password in plain txt'
if ($JoinDomain)
{
$autoLogonXMLString = @"
<AutoLogon>
<Password>
<Value>$domainAdministratorPasswordClearText</Value>
</Password>
<Domain>$JoinDomain</Domain>
<LogonCount>$AutoLogonCount</LogonCount>
<Username>$Username</Username>
<Enabled>true</Enabled>
</AutoLogon>
"@
}
else
{
$autoLogonXMLString = @"
<AutoLogon>
<Password>
<Value>$LocalAdministratorPasswordClearText</Value>
</Password>
<LogonCount>$AutoLogonCount</LogonCount>
<Username>Administrator</Username>
<Enabled>true</Enabled>
</AutoLogon>
"@
}
}
else
{
$autoLogonXMLString = $null
}
if ($IpCidr){
$IPAddressXMLString = @"
<component name="Microsoft-Windows-TCPIP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Interfaces>
<Interface wcm:action="add">
<Identifier>$NicNameForIPandDNSAssignments</Identifier>
<UnicastIPAddresses>
<IpAddress wcm:action="add" wcm:keyValue="1">$IpCidr</IpAddress>
</UnicastIPAddresses>
<Routes>
<Route wcm:action="add">
<Identifier>1</Identifier>
<Prefix>0.0.0.0/0</Prefix>
<Metric>10</Metric>
<NextHopAddress>$DefaultGateway</NextHopAddress>
</Route>
</Routes>
<IPv4Settings>
<DhcpEnabled>false</DhcpEnabled>
</IPv4Settings>
</Interface>
</Interfaces>
</component>
"@
}
else
{
$IPAddressXMLString = $null
}
if ($DnsServer)
{
$DnsAddressXMLString = @"
<component name="Microsoft-Windows-DNS-Client" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Interfaces>
<Interface wcm:action="add">
<Identifier>$NicNameForIPandDNSAssignments</Identifier>
<DNSServerSearchOrder>
<IpAddress wcm:action="add" wcm:keyValue="1">$DnsServer</IpAddress>
</DNSServerSearchOrder>
<EnableAdapterDomainNameRegistration>true</EnableAdapterDomainNameRegistration>
<DisableDynamicUpdate>false</DisableDynamicUpdate>
</Interface>
</Interfaces>
</component>
"@
}
else
{
$DnsAddressXMLString = $null
}
if ($PowerShellScriptFullPath)
{
$logonScriptXMLString = @"
<FirstLogonCommands>
<SynchronousCommand wcm:action="add">
<Description>PowerShell First logon script</Description>
<Order>1</Order>
<CommandLine>$PowerShellStartupCmd</CommandLine>
<RequiresUserInput>false</RequiresUserInput>
</SynchronousCommand>
</FirstLogonCommands>
"@
}
else
{
$logonScriptXMLString = $null
}
$unattend = @"
<unattend xmlns="urn:schemas-microsoft-com:unattend">
<settings pass="specialize">
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
</component>
<component name="Microsoft-Windows-Deployment" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
</component>
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ComputerName>$computerName</ComputerName>
</component>
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ComputerName>$computerName</ComputerName>
</component>$IPAddressXMLString$DnsAddressXMLString$domainJoinXMLString
</settings>
<settings pass="oobeSystem">
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<InputLocale>$InputLocale</InputLocale>
<SystemLocale>$SystemLocale</SystemLocale>
<UILanguage>$UILanguage</UILanguage>
<UserLocale>$UserLocale</UserLocale>
</component>
<component name="Microsoft-Windows-International-Core" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<InputLocale>$InputLocale</InputLocale>
<SystemLocale>$SystemLocale</SystemLocale>
<UILanguage>$UILanguage</UILanguage>
<UserLocale>$UserLocale</UserLocale>
</component>
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<OOBE>
<HideEULAPage>$HideEULAPage</HideEULAPage>
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
<NetworkLocation>Work</NetworkLocation>
<ProtectYourPC>1</ProtectYourPC>
<SkipUserOOBE>true</SkipUserOOBE>
<SkipMachineOOBE>true</SkipMachineOOBE>
</OOBE>
<TimeZone>$TimeZone</TimeZone>
<UserAccounts>
<AdministratorPassword>
<Value>$encodedAdministratorPassword</Value>
<PlainText>false</PlainText>
</AdministratorPassword>
</UserAccounts>
<RegisteredOrganization>$RegisteredOrganization</RegisteredOrganization>
<RegisteredOwner>$RegisteredOrganization</RegisteredOwner>$autoLogonXMLString$logonScriptXMLString
</component>
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<OOBE>
<HideEULAPage>$HideEULAPage</HideEULAPage>
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
<NetworkLocation>Work</NetworkLocation>
<ProtectYourPC>1</ProtectYourPC>
<SkipUserOOBE>true</SkipUserOOBE>
<SkipMachineOOBE>true</SkipMachineOOBE>
</OOBE>
<TimeZone>$TimeZone</TimeZone>
<UserAccounts>
<AdministratorPassword>
<Value>$encodedAdministratorPassword</Value>
<PlainText>false</PlainText>
</AdministratorPassword>
</UserAccounts>
<RegisteredOrganization>$RegisteredOrganization</RegisteredOrganization>
<RegisteredOwner>$RegisteredOrganization</RegisteredOwner>$autoLogonXMLString$logonScriptXMLString
</component>
</settings>
</unattend>
"@
try
{
$path = Resolve-Path -Path $OutputPath -ErrorAction Stop
$file = (Join-Path -Path $path -ChildPath 'Unattend.xml')
$fileExist = Test-Path -Path $file
if ($fileExist -and $Force)
{
Write-Verbose -Message "Overwriting $file, Force switch was enabled."
$confirm = $false
$operation = 'Overridden'
}
elseif ($fileExist)
{
Write-Verbose -Message "$file deletion will be prompted."
$confirm = $true
$operation = 'Overridden'
}
else
{
Write-Verbose -Message "Creating Unattend.xml file in $OutputPath"
$confirm = $false
$operation = 'created'
}
if ($PrintScreenOnly)
{
return $unattend
}
Remove-Item -Path $file -Confirm:$confirm -ErrorAction SilentlyContinue
Set-Content -Path $file -Value $unattend
Write-Output "File $($operation): $file"
}
finally
{
Remove-Variable -Name unattend, LocalAdministratorPasswordClearText, encodedAdministratorPassword, domainJoinerPasswordClearText -ErrorAction SilentlyContinue
}
}
Export-ModuleMember -Function New-BasicUnattendXML

Просмотреть файл

@ -0,0 +1,212 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string",
"metadata": {
"description": "Location for all resources."
}
},
"virtualMachineName": {
"type": "string",
"metadata": {
"description": "Virtual machine name."
}
},
"autoShutdown": {
"type": "string",
"defaultValue": "Enabled",
"allowedValues": [
"Enabled",
"Disabled"
],
"metadata": {
"description": "Configure Auto shutdown state"
}
},
"autoShutdownTime": {
"type": "string",
"defaultValue": "0200",
"minLength": 4,
"maxLength": 4,
"metadata": {
"description": "The time at which VMs will be automatically shutdown (24h HHmm format)."
}
},
"autoShutdownTimeZone": {
"type": "string",
"defaultValue": "UTC",
"allowedValues": [
"Dateline Standard Time",
"UTC-11",
"Aleutian Standard Time",
"Hawaiian Standard Time",
"Marquesas Standard Time",
"Alaskan Standard Time",
"UTC-09",
"Pacific Standard Time (Mexico)",
"UTC-08",
"Pacific Standard Time",
"US Mountain Standard Time",
"Mountain Standard Time (Mexico)",
"Mountain Standard Time",
"Central America Standard Time",
"Central Standard Time",
"Easter Island Standard Time",
"Central Standard Time (Mexico)",
"Canada Central Standard Time",
"SA Pacific Standard Time",
"Eastern Standard Time (Mexico)",
"Eastern Standard Time",
"Haiti Standard Time",
"Cuba Standard Time",
"US Eastern Standard Time",
"Turks And Caicos Standard Time",
"Paraguay Standard Time",
"Atlantic Standard Time",
"Venezuela Standard Time",
"Central Brazilian Standard Time",
"SA Western Standard Time",
"Pacific SA Standard Time",
"Newfoundland Standard Time",
"Tocantins Standard Time",
"E. South America Standard Time",
"SA Eastern Standard Time",
"Argentina Standard Time",
"Greenland Standard Time",
"Montevideo Standard Time",
"Magallanes Standard Time",
"Saint Pierre Standard Time",
"Bahia Standard Time",
"UTC-02",
"Mid-Atlantic Standard Time",
"Azores Standard Time",
"Cape Verde Standard Time",
"UTC",
"GMT Standard Time",
"Greenwich Standard Time",
"Sao Tome Standard Time",
"Morocco Standard Time",
"W. Europe Standard Time",
"Central Europe Standard Time",
"Romance Standard Time",
"Central European Standard Time",
"W. Central Africa Standard Time",
"Jordan Standard Time",
"GTB Standard Time",
"Middle East Standard Time",
"Egypt Standard Time",
"E. Europe Standard Time",
"Syria Standard Time",
"West Bank Standard Time",
"South Africa Standard Time",
"FLE Standard Time",
"Israel Standard Time",
"Kaliningrad Standard Time",
"Sudan Standard Time",
"Libya Standard Time",
"Namibia Standard Time",
"Arabic Standard Time",
"Turkey Standard Time",
"Arab Standard Time",
"Belarus Standard Time",
"Russian Standard Time",
"E. Africa Standard Time",
"Iran Standard Time",
"Arabian Standard Time",
"Astrakhan Standard Time",
"Azerbaijan Standard Time",
"Russia Time Zone 3",
"Mauritius Standard Time",
"Saratov Standard Time",
"Georgian Standard Time",
"Volgograd Standard Time",
"Caucasus Standard Time",
"Afghanistan Standard Time",
"West Asia Standard Time",
"Ekaterinburg Standard Time",
"Pakistan Standard Time",
"Qyzylorda Standard Time",
"India Standard Time",
"Sri Lanka Standard Time",
"Nepal Standard Time",
"Central Asia Standard Time",
"Bangladesh Standard Time",
"Omsk Standard Time",
"Myanmar Standard Time",
"SE Asia Standard Time",
"Altai Standard Time",
"W. Mongolia Standard Time",
"North Asia Standard Time",
"N. Central Asia Standard Time",
"Tomsk Standard Time",
"China Standard Time",
"North Asia East Standard Time",
"Singapore Standard Time",
"W. Australia Standard Time",
"Taipei Standard Time",
"Ulaanbaatar Standard Time",
"Aus Central W. Standard Time",
"Transbaikal Standard Time",
"Tokyo Standard Time",
"North Korea Standard Time",
"Korea Standard Time",
"Yakutsk Standard Time",
"Cen. Australia Standard Time",
"AUS Central Standard Time",
"E. Australia Standard Time",
"AUS Eastern Standard Time",
"West Pacific Standard Time",
"Tasmania Standard Time",
"Vladivostok Standard Time",
"Lord Howe Standard Time",
"Bougainville Standard Time",
"Russia Time Zone 10",
"Magadan Standard Time",
"Norfolk Standard Time",
"Sakhalin Standard Time",
"Central Pacific Standard Time",
"Russia Time Zone 11",
"New Zealand Standard Time",
"UTC+12",
"Fiji Standard Time",
"Kamchatka Standard Time",
"Chatham Islands Standard Time",
"UTC+13",
"Tonga Standard Time",
"Samoa Standard Time",
"Line Islands Standard Time"
],
"minLength": 2,
"metadata": {
"description": "Time zone of the virtual machines. Type \"[TimeZoneInfo]::GetSystemTimeZones().Id\" in PowerShell to get the list."
}
}
},
"functions": [],
"variables": {},
"resources": [
{
"type": "Microsoft.DevTestLab/schedules",
"apiVersion": "2018-09-15",
"location": "[parameters('location')]",
"name": "[concat('shutdown-computevm-', parameters('virtualMachineName'))]",
"properties": {
"status": "[parameters('autoShutdown')]",
"taskType": "ComputeVmShutdownTask",
"dailyRecurrence": {
"time": "[parameters('autoShutdownTime')]"
},
"timeZoneId": "[parameters('autoShutdownTimeZone')]",
"notificationSettings": {
"status": "Disabled",
"timeInMinutes": 30,
"notificationLocale": "en"
},
"targetResourceId": "[resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'))]"
}
}
],
"outputs": {}
}

Просмотреть файл

@ -0,0 +1,21 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location":{
"value": "germanywestcentral"
},
"virtualMachineName": {
"value": "dcVM"
},
"autoShutdown": {
"value": "Enabled"
},
"autoShutdownTime": {
"value": "0100"
},
"autoShutdownTimeZone": {
"value": "UTC"
}
}
}

Просмотреть файл

@ -0,0 +1,68 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"virtualNetworkName": {
"type": "string",
"metadata": {
"description": "The name of the Virtual Network to Create"
}
},
"virtualNetworkAddressRange": {
"type": "string",
"metadata": {
"description": "The address range of the new VNET in CIDR format"
}
},
"subnetName": {
"type": "string",
"metadata": {
"description": "The name of the subnet created in the new VNET"
}
},
"subnetRange": {
"type": "string",
"metadata": {
"description": "The address range of the subnet created in the new VNET"
}
},
"DNSServerAddress": {
"type": "array",
"metadata": {
"description": "The DNS address(es) of the DNS Server(s) used by the VNET"
}
},
"location": {
"type": "string",
"metadata": {
"description": "Location for all resources."
}
}
},
"resources": [
{
"type": "Microsoft.Network/virtualNetworks",
"name": "[parameters('virtualNetworkName')]",
"apiVersion": "2020-05-01",
"location": "[parameters('location')]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[parameters('virtualNetworkAddressRange')]"
]
},
"dhcpOptions": {
"dnsServers": "[parameters('DNSServerAddress')]"
},
"subnets": [
{
"name": "[parameters('subnetName')]",
"properties": {
"addressPrefix": "[parameters('subnetRange')]"
}
}
]
}
}
]
}

59
nestedtemplates/vnet.json Normal file
Просмотреть файл

@ -0,0 +1,59 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"virtualNetworkName": {
"type": "string",
"metadata": {
"description": "The name of the Virtual Network to Create"
}
},
"virtualNetworkAddressRange": {
"type": "string",
"metadata": {
"description": "The address range of the new VNET in CIDR format"
}
},
"subnetName": {
"type": "string",
"metadata": {
"description": "The name of the subnet created in the new VNET"
}
},
"subnetRange": {
"type": "string",
"metadata": {
"description": "The address range of the subnet created in the new VNET"
}
},
"location": {
"type": "string",
"metadata": {
"description": "Location for all resources."
}
}
},
"resources": [
{
"type": "Microsoft.Network/virtualNetworks",
"name": "[parameters('virtualNetworkName')]",
"apiVersion": "2020-05-01",
"location": "[parameters('location')]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[parameters('virtualNetworkAddressRange')]"
]
},
"subnets": [
{
"name": "[parameters('subnetName')]",
"properties": {
"addressPrefix": "[parameters('subnetRange')]"
}
}
]
}
}
]
}

77
readme.md Normal file
Просмотреть файл

@ -0,0 +1,77 @@
# Aks Hci on Azure VM project
This repository is designed to simplify Aks Hci demos in mind for people who are developers without domain knowledge or IT-Pros without Virtualization knowledge. There are two options to utilize the ARM template;
## Aks Hci on Azure VM
Only Windows Admin Center VM will be created once ARM template successfully deployed. Windows Admin center or PowerShell scripts (available to the desktop) may be utilized for completing Aks Hci deployment on top of Azure VM in couple of minutes.
### **Architecture of the deployment** (Aks Hci on Azure VM)
![AksHciOnAzureStackHci](./.images/AksHcionAzureVM.png)
## Aks Hci on Azure Stack HCI cluster
Azure Stack HCI host and Windows Admin Center VMs will be created once ARM template successfully deployed. Windows Admin center or PowerShell scripts (available to the desktop) may be utilized for completing Azure Stack HCI deployment in couple of minutes. Afterwards Aks Hci may be deployed on top of Azure Stack HCI clusters using provided scripts (available to the desktop).
**Note**: Due to nature of multiple layers of Nested virtualization, there are performance implications. However this is implemented to practice bits and pieces of the whole deployment to experience Aks Hci on top of Azure Stack HCI.
### **Architecture of the deployment** (Aks Hci on Azure Stack HCI cluster)
![AksHciOnAzureStackHci](./.images/AksHciOnAzureStackHci.png)
## Using ARM template to deploy Azure VM
Click the button below to deploy from the portal:
[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fyagmurs%2FAzureStackHCIonAzure%2Ftest%2Fazuredeploy.json)
[![Visualize](https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/1-CONTRIBUTION-GUIDE/images/visualizebutton.svg?sanitize=true)](http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2Fyagmurs%2FAzureStackHCIonAzure%2Ftest%2Fazuredeploy.json)
### High level deployment process and features
Deploy the ARM template (above buttons) by providing all the parameters required. Find details of **Aks Hci Scenario** options below. Most of the parameters have default values and sufficient for demostrate Aks Hci features and deployment procedures.
During the ARM template deployment Azure VM DSC will create Windows Admin Center VM than Chocolatey which means will be updated once released in Chocolatey repository. All installed extensions are getting updated daily in the background.
Note that all VMs deployed within the Azure VM use **same password** that has been specified in the ARM template.
* Azure VM will be configured as Domain Controller, DHCP, DNS and Hyper-v host.
* All Local accounts are named as **Administrator**.
* The **Domain Administrator** username is the **Username specified in the ARM template**.
### Deployment Scenarios
#### **Aks Hci on Azure VM**
This is one of scenario if you are willing to understand how to deploy Aks Hci and understand options.
![ARM-akshcionAzureVM](./.images/ARM-akshcionAzureVM.png)
**Note**: Once **'onAzureVMDirectly'** option selected for **'Aks Hci Scenario'** the following two option will be disregarded in the DSC configuration. As a result on WAC (Windows Admin Center) VM will be deployed.
#### **Aks Hci on Azure Stack HCI cluster**
This is one of scenario if you are willing to understand how to deploy Aks Hci on Azure Stack HCI and understand options. This is also useful scenarion to test Azure Stack HCI only without deploying Aks Hci on top of Azure Stack Hci Cluster.
![ARM-akshcionAzureStackHCICluster](./.images/ARM-akshcionAzureStackHCICluster.png)
**Note**: Once **'onNestedAzureStackHciClusteronAzureVM'** option selected for **'Aks Hci Scenario'** Make sure the correlation between the deployment VM size and Azure Stack HCI host counts and Memory sizes are compatible. As a result a number of Azure Stack HCI VMs (specified in 'AzS Hci Host Count' with 'AzS Hci Host Memory') and WAC (Windows Admin Center) VM will be deployed on Azure VM.
## How to run PoC once Azure VM deployed
There are couple of shortcuts available on the desktop; can be utilized to demostraion or learning purposes to understand process and options
* Proof of concepts guide (which is this guide)
* Step by step lab Script, the script includes;
* Deployment of Azure Stack HCI cluster through a wizard. (Depends on the scenario selected)
* Tools and prerequisites installations
* Management and Target Aks clusters deployment
* Azure Arc onboarding process
* Enable Azure Arc montioring
* Deploy demo application to Kubernetes cluster onboarded to Azure Arc
* Scale up kubernetes cluster
* Deployment of an older version of Kubernetes cluster than updating the cluster to newer version
* Uninstall onboarding from Azure Arc
* Destroy kubernetes cluster
* Remove Aks Hci deployment

Просмотреть файл

@ -0,0 +1,248 @@
#https://docs.microsoft.com/en-us/azure-stack/aks-hci/setup-powershell
#the following function downloads, extract and place required PowerShell Modules in PowerShell modules folder
Prepare-AzureVMforAksHciDeployment
# variables used in the script, update them accordingly based on your environment before proceed further
$targetDrive = "V:"
$AksHciTargetFolder = "AksHCIMain"
$AksHciTargetPath = "$targetDrive\$AksHciTargetFolder"
$sourcePath = "$targetDrive\source"
$targetClusterName = "target-cls1"
$tenant = "xxxxxxxxxxx.onmicrosoft.com"
$subscriptionID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
$rgName = "new-arc-rg"
$location = "westeurope"
break
#region pre-requisites
# Install Az modules to access Azure and Azure Arc Kubernetes resources
Install-Module az
Install-Module Az.ConnectedKubernetes
# Install Chocolatey if not installed already
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
# supress choco installation prompt
choco feature enable -n allowGlobalConfirmation --verbose
# Install Azure Cli using Chocolatey
choco install azure-cli --verbose
# Install latest Helm using Chocolatey
choco install kubernetes-helm --verbose
#update environment variable values after Azure Cli and Helm installation
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine")
# Add and update Az Cli k8sconfiguration and connectedk8s extensions
# https://docs.microsoft.com/en-us/azure/azure-arc/kubernetes/connect-cluster
az extension add --name connectedk8s
az extension add --name k8sconfiguration
# check if update available for extensions
az extension update --name connectedk8s
az extension update --name k8sconfiguration
#endregion pre-requisites
break
#region Enable AksHCI
#Deploy Management Cluster
# https://docs.microsoft.com/en-us/azure-stack/aks-hci/create-kubernetes-cluster-powershell
Import-Module AksHci
Initialize-AksHciNode
$managementClusterParams = @{
imageDir = "$AksHciTargetPath\Images"
cloudConfigLocation = "$AksHciTargetPath\Config"
workingDir = "$AksHciTargetPath\Working"
vnetName = 'Default Switch'
controlPlaneVmSize = 'default' # Get-AksHciVmSize
loadBalancerVmSize = 'default' # Get-AksHciVmSize
vnetType = 'ICS'
}
Set-AksHciConfig @managementClusterParams
Install-AksHci
#Deploy Target Cluster
$targetClusterParams = @{
clusterName = $targetClusterName
kubernetesVersion = 'v1.18.8'
controlPlaneNodeCount = 1
linuxNodeCount = 1
windowsNodeCount = 0
controlPlaneVmSize = 'default' # Get-AksHciVmSize
loadBalancerVmSize = 'default' # Get-AksHciVmSize
linuxNodeVmSize = 'Standard_D4s_v3' # Get-AksHciVmSize
windowsNodeVmSize = 'default' # Get-AksHciVmSize
}
New-AksHciCluster @targetClusterParams
#endregion Enable AksHCI
#region deploy and upgrade kubernetes cluster
# https://docs.microsoft.com/en-us/azure-stack/aks-hci/create-kubernetes-cluster-powershell#step-3-upgrade-kubernetes-version
$demoClusterParams = @{
clusterName = 'update-demo'
kubernetesVersion = 'v1.16.10' # v1.16.15, v1.17.11, v1.18.8
controlPlaneNodeCount = 1
linuxNodeCount = 1
windowsNodeCount = 0
controlPlaneVmSize = 'default' # Get-AksHciSize
loadBalancerVmSize = 'default' # Get-AksHciSize
linuxNodeVmSize = 'default' # Get-AksHciSize
windowsNodeVmSize = 'default' # Get-AksHciSize
}
New-AksHciCluster @demoClusterParams
#List k8s clusters
Get-AksHciCluster -clusterName update-demo
# scale up controller node count
Set-AksHciClusterNodeCount -clusterName update-demo -controlPlaneNodeCount 3
# run update patch (1.16.x --> 1.16.y)
Update-AksHciCluster -clusterName update-demo -patch
# run update without patching (1.16.x --> 1.17.y)
Update-AksHciCluster -clusterName update-demo
#endregion
break
#list Aks Hci cmdlets
Get-Command -Module AksHci
#List k8s clusters
Get-AksHciCluster
#Retreive AksHCI logs for Target Cluster deployment
Get-AksHciCredential -clusterName $targetClusterName
#region onboarding
# login Azure
Connect-AzAccount -Tenant $tenant
# Get current Azure context
Get-AzContext
# list subscriptions
Get-AzSubscription
# select subscription
Select-AzSubscription -Subscription $subscriptionID
# Verify using correct subscription
Get-AzContext
$context = Get-AzContext
# Create new resource group to onboard Aks Hci to Azure Arc
$rg = New-AzResourceGroup -Name $rgName -Location $location
#https://docs.microsoft.com/en-us/powershell/module/az.resources/new-azadserviceprincipal?view=azps-5.4.0
# Create new Spn on azure and assing them contributor access on the Resource Group
$sp = New-AzADServicePrincipal -Role Contributor -Scope "/subscriptions/$subscriptionID/resourceGroups/$($rg.ResourceGroupName)"
[pscredential]$credObject = New-Object System.Management.Automation.PSCredential ($sp.ApplicationId, $sp.Secret)
#https://docs.microsoft.com/en-us/azure-stack/aks-hci/connect-to-arc
# Onboard Aks Hci to Azure Arc using Powershell
Install-AksHciArcOnboarding -clusterName $targetClusterName -resourcegroup $rg.ResourceGroupName -location $rg.location -subscriptionId $context.Subscription.Id -clientid $sp.ApplicationId -clientsecret $credObject.GetNetworkCredential().Password -tenantid $context.Tenant.Id
# get state of the onboarding process
kubectl get pods -n azure-arc-onboarding
# list error information
kubectl describe pod -n azure-arc-onboarding azure-arc-onboarding-<Name of the pod>
kubectl logs -n azure-arc-onboarding azure-arc-onboarding-<Name of the pod>
#endregion onboarding
#region enable monitoring
# enable monitoring using Powershell
# https://docs.microsoft.com/en-us/azure/azure-monitor/insights/container-insights-enable-arc-enabled-clusters
Invoke-WebRequest https://aka.ms/enable-monitoring-powershell-script -OutFile enable-monitoring.ps1
$azureArcClusterResourceId = "/subscriptions/$subscriptionID/resourceGroups/$($rg.ResourceGroupName)/providers/Microsoft.Kubernetes/connectedClusters/$targetClusterName"
$kubeContext = kubectl.exe config current-context
$logAnalyticsWorkspaceResourceId = "/subscriptions/$subscriptionID/resourceGroups/$($rg.ResourceGroupName)/providers/microsoft.operationalinsights/workspaces/yagmurslog"
.\enable-monitoring.ps1 -clusterResourceId $azureArcClusterResourceId -kubeContext $kubeContext -workspaceResourceId $logAnalyticsWorkspaceResourceId
#endregion enable monitoring
#region deploy application
# the repository can be forked to run advanced scenarios. If you fork the repo please update the repo variable accordingly to be used in the following commands.
$gitRepo = "https://github.com/Azure/arc-k8s-demo"
# deploy demo application from Azure Arc Enabled Kubernetes from Azure portal (UI)
<#
Go to Azure Portal --> Azure arc target kubernetes cluster --> select gitops and add, provide following information
Configuration name: cluster-config
Operator instance name: cluster-config
Operator namespace: cluster-config
Repository URL: https://github.com/Azure/arc-k8s-demo.git
Operator scope: Cluster
add
#>
# deploy demo application on Azure Arc Enabled Kubernetes using Azure Cli
# https://docs.microsoft.com/en-us/azure/azure-arc/kubernetes/use-gitops-connected-cluster
az login --tenant $tenant
az k8sconfiguration create --name "cluster-config" --cluster-name $targetClusterName --resource-group $rg.ResourceGroupName --operator-instance-name "cluster-config" --operator-namespace 'cluster-config' --repository-url $gitRepo --scope "cluster" --cluster-type "connectedClusters" --operator-params "'--git-poll-interval 3s --git-readonly'"
# list all service config
kubectl.exe get services
# list specific service config for azure vote application
kubectl.exe get services azure-vote-front
#endregion deploy application
#region scale up
# Scale up/down node count
Set-AksHciClusterNodeCount -clusterName $targetClusterName -linuxNodeCount 1 -windowsNodeCount 0
# scale up azure vote application pod count
# scale up with devops from github vote application pod count
# verify scale up
#endregion
#region clean up
# uninstall / remove from Azure Arc
Uninstall-AksHciArcOnboarding -clusterName $targetClusterName
#Retreive AksHCI logs for Target Cluster deployment
Get-AksHciLogs
#List k8s clusters
Get-AksHciCluster
#Remove Target cluster
Remove-AksHciCluster -clusterName $targetClusterName
Uninstall-AksHci
#endregion

Просмотреть файл

@ -0,0 +1,275 @@
Import-Module AzureStackHCIInstallerHelper
# The following function calls the wizard to setup Azure Stack Hci cluster then prepares hosts for Aks Hci Deployment
Start-AksHciPoC -verbose
#register Azure Stack HCI cluster as Azure Arc resource (pre-requisites to deploy any vm on Azure Stack HCI)
# https://docs.microsoft.com/en-us/azure-stack/hci/deploy/register-with-azure
# variables used in the script, update them accordingly based on your environment before proceed further
$tenant = "xxxxxxxxxxx.onmicrosoft.com"
$subscriptionID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
$rgName = "new-arc-hci-rg"
$location = "westeurope"
$hciHostName = "hpv01"
$hciClusterName = "hci01"
Install-Module az
Install-Module AzureAD
Install-Module -Name Az.StackHCI
Connect-AzAccount -Tenant $tenant
Select-AzSubscription -Subscription $subscriptionID
$rg = New-AzResourceGroup -Name $rgName -Location $location
Register-AzStackHCI -SubscriptionId $subscriptionID -ComputerName $hciHostName -ResourceName $hciClusterName -ResourceGroupName $rg.ResourceGroupName -Region $rg.location
break
#############################################################
# #
# Run the following code on one of the Azure Stack HCI host #
# #
#############################################################
#Enable AksHCI on Azure Stack HCI cluster
# variables used in the script, update them accordingly based on your environment before proceed further
$targetDrive = "C:\ClusterStorage"
$AksHciTargetFolder = "AksHCIMain"
$AksHciTargetPath = "$targetDrive\$AksHciTargetFolder"
$sourcePath = "$AksHciTargetPath\source"
$targetClusterName = "target-cls1-on-hci" #must be lower case
$tenant = "xxxxxxxxxxx.onmicrosoft.com"
$subscriptionID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
$rgName = "new-arc-rg"
$location = "westeurope"
break
#region pre-requisites
# Install Az modules to access Azure and Azure Arc Kubernetes resources
Install-Module az
Install-Module Az.ConnectedKubernetes
# Install Chocolatey if not installed already
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
# supress choco installation prompt
choco feature enable -n allowGlobalConfirmation
# Install Azure Cli using Chocolatey
choco install azure-cli
# Install latest Helm using Chocolatey
choco install kubernetes-helm
#update environment variable values after Azure Cli and Helm installation
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine")
# Add and update Az Cli k8sconfiguration and connectedk8s extensions
# https://docs.microsoft.com/en-us/azure/azure-arc/kubernetes/connect-cluster
az extension add --name connectedk8s
az extension add --name k8sconfiguration
# check if update available for extensions
az extension update --name connectedk8s
az extension update --name k8sconfiguration
#endregion pre-requisites
break
#region Enable AksHCI
#Deploy Management Cluster
# https://docs.microsoft.com/en-us/azure-stack/aks-hci/create-kubernetes-cluster-powershell
Import-Module AksHci
Initialize-AksHciNode
$managementClusterParams = @{
imageDir = "$AksHciTargetPath\Images"
cloudConfigLocation = "$AksHciTargetPath\Config"
workingDir = "$AksHciTargetPath\Working"
vnetName = 'Default Switch'
controlPlaneVmSize = 'default' # Get-AksHciVmSize
loadBalancerVmSize = 'default' # Get-AksHciVmSize
}
Set-AksHciConfig @managementClusterParams
Install-AksHci
#Deploy Target Cluster
$targetClusterParams = @{
clusterName = $targetClusterName
kubernetesVersion = 'v1.18.8'
controlPlaneNodeCount = 1
linuxNodeCount = 1
windowsNodeCount = 0
controlPlaneVmSize = 'default' # Get-AksHciVmSize
loadBalancerVmSize = 'default' # Get-AksHciVmSize
linuxNodeVmSize = 'default' # Get-AksHciVmSize
windowsNodeVmSize = 'default' # Get-AksHciVmSize
}
New-AksHciCluster @targetClusterParams
#endregion Enable AksHCI
#region deploy and upgrade kubernetes cluster
# https://docs.microsoft.com/en-us/azure-stack/aks-hci/create-kubernetes-cluster-powershell#step-3-upgrade-kubernetes-version
$demoClusterParams = @{
clusterName = 'update-demo'
kubernetesVersion = 'v1.16.10' # v1.16.15, v1.17.11, v1.18.8
controlPlaneNodeCount = 1
linuxNodeCount = 1
windowsNodeCount = 0
controlPlaneVmSize = 'default' # Get-AksHciSize
loadBalancerVmSize = 'default' # Get-AksHciSize
linuxNodeVmSize = 'default' # Get-AksHciSize
windowsNodeVmSize = 'default' # Get-AksHciSize
}
New-AksHciCluster @demoClusterParams
#List k8s clusters
Get-AksHciCluster -clusterName update-demo
# scale up controller node count
Set-AksHciClusterNodeCount -clusterName update-demo -controlPlaneNodeCount 3
# run update patch (1.16.x --> 1.16.y)
Update-AksHciCluster -clusterName update-demo -patch
# run update without patching (1.16.x --> 1.17.y)
Update-AksHciCluster -clusterName update-demo
#endregion
break
#list Aks Hci cmdlets
Get-Command -Module AksHci
#List k8s clusters
Get-AksHciCluster
#Retreive AksHCI logs for Target Cluster deployment
Get-AksHciCredential -clusterName $targetClusterName
#region onboarding
# login Azure
Connect-AzAccount -Tenant $tenant
# Get current Azure context
Get-AzContext
# list subscriptions
Get-AzSubscription
# select subscription
Select-AzSubscription -Subscription $subscriptionID
# Verify using correct subscription
Get-AzContext
$context = Get-AzContext
# Create new resource group to onboard Aks Hci to Azure Arc
$rg = New-AzResourceGroup -Name $rgName -Location $location
#https://docs.microsoft.com/en-us/powershell/module/az.resources/new-azadserviceprincipal?view=azps-5.4.0
# Create new Spn on azure and assing them contributor access on the Resource Group
$sp = New-AzADServicePrincipal -Role Contributor -Scope "/subscriptions/$subscriptionID/resourceGroups/$($rg.ResourceGroupName)"
[pscredential]$credObject = New-Object System.Management.Automation.PSCredential ($sp.ApplicationId, $sp.Secret)
#https://docs.microsoft.com/en-us/azure-stack/aks-hci/connect-to-arc
# Onboard Aks Hci to Azure Arc using Powershell
Install-AksHciArcOnboarding -clusterName $targetClusterName -resourcegroup $rg.ResourceGroupName -location $rg.location -subscriptionId $context.Subscription.Id -clientid $sp.ApplicationId -clientsecret $credObject.GetNetworkCredential().Password -tenantid $context.Tenant.Id
# get state of the onboarding process
kubectl get pods -n azure-arc-onboarding
# list error information
kubectl describe pod -n azure-arc-onboarding azure-arc-onboarding-<Name of the pod>
kubectl logs -n azure-arc-onboarding azure-arc-onboarding-<Name of the pod>
#endregion onboarding
#region enable monitoring
# enable monitoring using Powershell
# https://docs.microsoft.com/en-us/azure/azure-monitor/insights/container-insights-enable-arc-enabled-clusters
Invoke-WebRequest https://aka.ms/enable-monitoring-powershell-script -OutFile enable-monitoring.ps1
$azureArcClusterResourceId = "/subscriptions/$subscriptionID/resourceGroups/$($rg.ResourceGroupName)/providers/Microsoft.Kubernetes/connectedClusters/$targetClusterName"
$kubeContext = kubectl.exe config current-context
$logAnalyticsWorkspaceResourceId = "/subscriptions/$subscriptionID/resourceGroups/$($rg.ResourceGroupName)/providers/microsoft.operationalinsights/workspaces/yagmurslog"
.\enable-monitoring.ps1 -clusterResourceId $azureArcClusterResourceId -kubeContext $kubeContext -workspaceResourceId $logAnalyticsWorkspaceResourceId
#endregion enable monitoring
#region deploy application
# the repository can be forked to run advanced scenarios. If you fork the repo please update the repo variable accordingly to be used in the following commands.
$gitRepo = "https://github.com/Azure/arc-k8s-demo"
# deploy demo application from Azure Arc Enabled Kubernetes from Azure portal (UI)
<#
Go to Azure Portal --> Azure arc target kubernetes cluster --> select gitops and add, provide following information
Configuration name: cluster-config
Operator instance name: cluster-config
Operator namespace: cluster-config
Repository URL: https://github.com/Azure/arc-k8s-demo.git
Operator scope: Cluster
add
#>
# deploy demo application on Azure Arc Enabled Kubernetes using Azure Cli
# https://docs.microsoft.com/en-us/azure/azure-arc/kubernetes/use-gitops-connected-cluster
az login --tenant $tenant
az k8sconfiguration create --name "cluster-config" --cluster-name $targetClusterName --resource-group $rg.ResourceGroupName --operator-instance-name "cluster-config" --operator-namespace 'cluster-config' --repository-url $gitRepo --scope "cluster" --cluster-type "connectedClusters" --operator-params "'--git-poll-interval 3s --git-readonly'"
# list all service config
kubectl.exe get services
# list specific service config for azure vote application
kubectl.exe get services azure-vote-front
#endregion deploy application
#region scale up
# Scale up/down node count
Set-AksHciClusterNodeCount -clusterName $targetClusterName -linuxNodeCount 1 -windowsNodeCount 0
# scale up azure vote application pod count
# scale up with devops from github vote application pod count
# verify scale up
#endregion
#region clean up
# uninstall / remove from Azure Arc
Uninstall-AksHciArcOnboarding -clusterName $targetClusterName
#Retreive AksHCI logs for Target Cluster deployment
Get-AksHciLogs
#List k8s clusters
Get-AksHciCluster
#Remove Target cluster
Remove-AksHciCluster -clusterName $targetClusterName
Uninstall-AksHci
#endregion

Просмотреть файл

@ -0,0 +1,85 @@
$rgPrefix = 'yagmurs-azurestack'
$location = 'germanywestcentral'
$branch = 'test'
$subs = Get-Content .\scripts\ignore\subscription.txt
if (-not (Get-AzAccessToken))
{
Connect-AzAccount -UseDeviceAuthentication
}
if (-not ($sub))
{
$subs | Out-GridView -PassThru | ForEach-Object {$sub = $_}
}
Write-Verbose -Message "Subscription: $sub will be used" -Verbose
if ((Get-AzContext | Select-Object -ExpandProperty name) -notlike "$sub*")
{
Get-AzSubscription | Out-GridView -PassThru | Select-AzSubscription
}
$paramUri = "https://raw.githubusercontent.com/yagmurs/AzureStackHCIonAzure/test/azuredeploy.parameters.json"
$paramFileAsHash = ((Invoke-WebRequest -UseBasicParsing -Uri $paramUri).content | ConvertFrom-Json -AsHashtable)
if (-not ($clearTextPassword))
{
$clearTextPassword = Read-Host -Prompt "Enter password for the VM" -MaskInput
}
$encryptedPass = $clearTextPassword | ConvertTo-SecureString -AsPlainText -Force
$templateParameterObject = @{}
$paramFileAsHash.parameters.keys | ForEach-Object {$templateParameterObject[$_] = $paramFileAsHash.parameters.$_.value}
$templateParameterObject.add("AdminPassword", $encryptedPass)
$templateParameterObject.location = $location
$templateParameterObject.branch = $branch
#$templateParameterObject.aksHciScenario = 'onNestedAzureStackHciClusteronAzureVM'
#$templateParameterObject
do {
Write-Host "'N'ew or 'D'SC only deployment?" -Nonewline -ForegroundColor DarkYellow -BackgroundColor Blue
$dtype = read-host
} until ($dtype -eq "N" -or $dtype -eq "D")
if ($dtype -eq "n")
{
if ([string]::IsNullOrEmpty($rgPrefix))
{
Write-Error "`$rgPrefix is empty" -ErrorAction Stop
}
do
{
$r = get-random -Minimum 1 -Maximum 3
} while (Get-AzResourceGroup -Name "$rgPrefix$r" -ErrorAction SilentlyContinue)
$rgName = "$rgPrefix$r"
$rgObject = @($("$rgPrefix" + 0), $("$rgPrefix" + 1), $("$rgPrefix" + 2), $("$rgPrefix" + 3)) | ForEach-Object {Get-AzResourceGroup -Name $_ -ErrorAction SilentlyContinue}
if ($rgObject)
{
Write-Verbose -Message "Resource Group: $($rgObject.ResourceGroupName) will be deleted" -Verbose
$rgObject | Remove-AzResourceGroup -confirm:$true
#$rgObject | Remove-AzResourceGroup -Force -AsJob
}
$templateParameterObject.dnsPrefix = $templateParameterObject.dnsPrefix.Insert($templateParameterObject.dnsPrefix.Length, $r)
New-AzResourceGroup -Name $rgName -Location $templateParameterObject.location
New-AzResourceGroupDeployment -ResourceGroupName $rgName `
-Name "azshcihost" -TemplateUri "https://raw.githubusercontent.com/yagmurs/AzureStackHCIonAzure/$branch/azuredeploy.json" `
-TemplateParameterObject $templateParameterObject
}
elseif ($dtype -eq "d")
{
$rg = (Get-AzResourceGroup -ResourceGroupName $rgPrefix*).ResourceGroupName
$r = $rg[-1]
Write-Verbose "Removing DSC Extension for VM on $rg Resource Group" -Verbose
Get-AzVMExtension -ResourceGroupName $rg -VMName dc01 | Where-Object ExtensionType -eq DSC | Remove-AzVMExtension -Force -Verbose
$templateParameterObject.dnsPrefix = $templateParameterObject.dnsPrefix.Insert($templateParameterObject.dnsPrefix.Length, $r)
Write-Verbose "Redeploying ARM template for VM on $rg Resource Group" -Verbose
New-AzResourceGroupDeployment -ResourceGroupName $rg `
-Name "azshcihost" -TemplateUri "https://raw.githubusercontent.com/yagmurs/AzureStackHCIonAzure/$branch/azuredeploy.json" `
-TemplateParameterObject $templateParameterObject -Force -Verbose
}