diff --git a/HandsOnLabs/01-CreatingFirstLab/media/explorer01.png b/HandsOnLabs/01-CreatingFirstLab/media/explorer01.png new file mode 100644 index 00000000..13d39a9f Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/explorer01.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/explorer02.png b/HandsOnLabs/01-CreatingFirstLab/media/explorer02.png new file mode 100644 index 00000000..88beccba Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/explorer02.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/explorer03.png b/HandsOnLabs/01-CreatingFirstLab/media/explorer03.png new file mode 100644 index 00000000..49677d45 Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/explorer03.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/explorer04.png b/HandsOnLabs/01-CreatingFirstLab/media/explorer04.png new file mode 100644 index 00000000..a754598a Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/explorer04.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/explorer05.png b/HandsOnLabs/01-CreatingFirstLab/media/explorer05.png new file mode 100644 index 00000000..e2f3149f Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/explorer05.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/explorer06.png b/HandsOnLabs/01-CreatingFirstLab/media/explorer06.png new file mode 100644 index 00000000..eb15c5e9 Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/explorer06.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/explorer07.png b/HandsOnLabs/01-CreatingFirstLab/media/explorer07.png new file mode 100644 index 00000000..f894a09a Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/explorer07.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/hvmanager01.png b/HandsOnLabs/01-CreatingFirstLab/media/hvmanager01.png new file mode 100644 index 00000000..4a7d6138 Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/hvmanager01.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/notepad01.png b/HandsOnLabs/01-CreatingFirstLab/media/notepad01.png new file mode 100644 index 00000000..57f7ece6 Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/notepad01.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/powershell01.png b/HandsOnLabs/01-CreatingFirstLab/media/powershell01.png new file mode 100644 index 00000000..f23acc6c Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/powershell01.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/powershell02.png b/HandsOnLabs/01-CreatingFirstLab/media/powershell02.png new file mode 100644 index 00000000..a7dfcc9e Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/powershell02.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/powershell03.png b/HandsOnLabs/01-CreatingFirstLab/media/powershell03.png new file mode 100644 index 00000000..0d7b4cc8 Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/powershell03.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/powershell04.png b/HandsOnLabs/01-CreatingFirstLab/media/powershell04.png new file mode 100644 index 00000000..745f746d Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/powershell04.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/powershell05.png b/HandsOnLabs/01-CreatingFirstLab/media/powershell05.png new file mode 100644 index 00000000..a448b90c Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/powershell05.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/powershell06.png b/HandsOnLabs/01-CreatingFirstLab/media/powershell06.png new file mode 100644 index 00000000..d93bf3c7 Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/powershell06.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/powershell07.png b/HandsOnLabs/01-CreatingFirstLab/media/powershell07.png new file mode 100644 index 00000000..8d05515d Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/powershell07.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/media/powershell08.png b/HandsOnLabs/01-CreatingFirstLab/media/powershell08.png new file mode 100644 index 00000000..150d975d Binary files /dev/null and b/HandsOnLabs/01-CreatingFirstLab/media/powershell08.png differ diff --git a/HandsOnLabs/01-CreatingFirstLab/readme.md b/HandsOnLabs/01-CreatingFirstLab/readme.md new file mode 100644 index 00000000..c55f23c8 --- /dev/null +++ b/HandsOnLabs/01-CreatingFirstLab/readme.md @@ -0,0 +1,197 @@ +# Creating first Lab + + + +- [Creating first Lab](#creating-first-lab) + - [Task 01: Prepare files](#task-01-prepare-files) + - [Step 01: Download MSLab files](#step-01-download-mslab-files) + - [Step 02: Unblock files and set execution policy](#step-02-unblock-files-and-set-execution-policy) + - [Task 02: Download Required files](#task-02-download-required-files) + - [Task 03: Build the lab Prerequisites](#task-03-build-the-lab-prerequisites) + - [Step 01: Run first MSLab script](#step-01-run-first-mslab-script) + - [Step 02: Create Parent Disks - second MSLab script](#step-02-create-parent-disks---second-mslab-script) + - [Step 03: Create Azure Local Parent Disk](#step-03-create-azure-local-parent-disk) + - [Task 03 - Deploy Azure Local Lab](#task-03---deploy-azure-local-lab) + - [Step 01: Modify LabConfig.ps1](#step-01-modify-labconfigps1) + - [Step 02: Deploy](#step-02-deploy) + - [Step 03: Cleanup Optional](#step-03-cleanup-optional) + - [Tips & Tricks](#tips--tricks) + - [Add "Default" virtual switch in Windows Server 2025](#add-default-virtual-switch-in-windows-server-2025) + + + + +## Task 01: Prepare files + +### Step 01: Download MSLab files + +Note: MSLab files are available at https://aka.ms/mslab/download + +Note: Since we want you to learn PowerShell a bit, steps - if possible - will be in PowerShell. + +```PowerShell +#download mslab to Downloads +Invoke-WebRequest -Uri https://aka.ms/mslab/download -OutFile $env:UserProfile\Downloads\mslab.zip + +#extract to c:\MSLab +Expand-Archive -Path $env:UserProfile\Downloads\mslab.zip -DestinationPath c:\MSLab\ + +``` + +### Step 02: Unblock files and set execution policy + +Note: Since PowerShell scripts are no longer signed (you can push @vladimir machv@microsoft.com to request that internally again, and yes, it's a lot of "paperwork"), files needs to be ublocked and execution policy configured + +```PowerShell +$MSLabPath="C:\MSLab\" + +#grab extracted files and unblock +Get-ChildItem -Path $MSLabPath | Unblock-File + +#set execution policy to remote signed +Set-ExecutionPolicy -ExecutionPolicy RemoteSigned + +``` + +## Task 02: Download Required files + +Note: Personally I prefer MSDN images (or VL images if you have it available), but [eval images](https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2025) are also fine. Why downloading ISO and not VHD? Because ISO contains all 4 versions (core/GUI,Standard and Datacenter) and VHD is only one. Plus VHD is sized 30GB (last time I checked). So it's more convenient to create image using MSLab scripts + +Note: Start-BitsTransfer is used because invoke-webrequest is slow for big files (unless you configure different progresspreference) + +```PowerShell +#ISO +$WindowsServerEvalURL="https://software-static.download.prss.microsoft.com/dbazure/888969d5-f34g-4e03-ac9d-1f9786c66749/26100.1742.240906-0331.ge_release_svc_refresh_SERVER_EVAL_x64FRE_en-us.iso" +$AzureLocal2505URL="http://aka.ms/hcireleaseimage/2505" + +#download +Start-BitsTransfer -Source $WindowsServerEvalURL -Destination $env:userprofile\Downloads\ +Start-BitsTransfer -Source $AzureLocal2505URL -Destination $env:userprofile\Downloads\AzureLocal2505.iso + +``` + +## Task 03: Build the lab Prerequisites + +In your MSLab folder you should be able to see following files + +![](./media/explorer01.png) + +and ISO files should be downloaded in downloads folder + +![](./media/explorer02.png) + + +### Step 01: Run first MSLab script + +In your MSLab folder right-click at 1_Prereq.ps1 and run with PowerShell. + +![](./media/explorer03.png) + +Note: this script will create folders, scripts. Will download all additional files from internet. + +Tip: this is the only step that is needed to download files. After this step, you can distribute MSLab folder to offline environment and run 1_prereqs again. + +Expected output: + +![](./media/powershell01.png) + +![](./media/explorer04.png) + + +### Step 02: Create Parent Disks - second MSLab script + +In your MSLab folder right-click at 2_CreateParentDisks.ps1 and run with PowerShell. + +![](./media/explorer05.png) + +The script will ask you about telemetry level and will ask you for Windows Server 2025 ISO. Once asked for MSU, hit cancel. + +![](./media/powershell02.png) + +![](./media/powershell03.png) + +Note: this script will create Windows Server 2025 VHDs (GUI and Core) and will create domain controller. Once all is created, VMs are removed and files cleaned + +Result: + +![](./media/powershell04.png) + +![](./media/explorer06.png) + +### Step 03: Create Azure Local Parent Disk + +In your MSLab folder navigate to ParentDisks folder. In ParentDisks folder right-click at CreateParentDisk.ps1 and select run with PowerShell + +![](./media/explorer07.png) + +Script will ask you for ISO, so point it to downloaded Azure Local ISO. Once asked for MSU, click cancel. + +![](./media/powershell05.png) + +Note: this way you can create any VHD (Windows Server 2016-2025, Windows 11...) + +You'll be asked for name and size, simply hit enter to accept default values. + +Result: + +![](./media/powershell06.png) + +## Task 03 - Deploy Azure Local Lab + +### Step 01: Modify LabConfig.ps1 + +In your MSLab folder open LabConfig.ps1 and replace it with following text + +Note: following config will use folder name as prefix (MSLab in this case). It will create 2 Azure Local VMs with maximum CPUs available and each with 24GB RAM. + +```PowerShell +$LabConfig=@{AllowedVLANs="1-10,711-719" ; DomainAdminName='LabAdmin'; AdminPassword='LS1setup!' ; DCEdition='4'; Internet=$true; AdditionalNetworksConfig=@(); VMs=@()} + +#Azure Local 24H2 +#labconfig will not domain join VMs +1..2 | ForEach-Object {$LABConfig.VMs += @{ VMName = "ALNode$_" ; Configuration = 'S2D' ; ParentVHD = 'AzSHCI24H2_G2.vhdx' ; HDDNumber = 4 ; HDDSize= 1TB ; MemoryStartupBytes= 24GB; VMProcessorCount="MAX" ; vTPM=$true ; Unattend="NoDjoin" ; NestedVirt=$true }} + +#VM for Windows Admin Center (optional) +#$LabConfig.VMs += @{ VMName = 'WACGW' ; ParentVHD = 'Win2025Core_G2.vhdx'; MGMTNICs=1} + +#Management machine (Windows Server 2025 GUI) +$LabConfig.VMs += @{ VMName = 'Management' ; ParentVHD = 'Win2025_G2.vhdx'; MGMTNICs=1 ; AddToolsVHD=$True } + +``` + +Result: + +![](./media/notepad01.png) + +### Step 02: Deploy + +In your MSLab folder right-click at Deploy.ps1 and run with PowerShell. In ~5 minutes you should have your lab + +Result: + +![](./media/hvmanager01.png) + +### Step 03: Cleanup (Optional) + +In your MSLab folder right-click at Cleanup.ps1 and run with PowerShell. In ~10 seconds your lab is gone and ready to deploy again. + +## Tips & Tricks + +### Add "Default" virtual switch in Windows Server 2025 + +In Windows 11 there's already "Default virtual switch" that provides internet connectivity to your lab. This script will add it to Windows Server. It's useful if your network does not have DHCP, so you dont have to assign DC IP manually. + +```PowerShell +#install Containers feature to be able manage HNS networks (needs reboot) +Install-WindowsFeature -Name Containers + +#install HNS powershell module +Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force +Install-Module -Name HNS -Force -AllowClobber + +#add default switch +New-HnsDefaultSwitchNetwork +``` +![](./media/hvmanager07.png) + +![](./media/powershell08.png) \ No newline at end of file diff --git a/HandsOnLabs/02-DeployingAzureLocal/media/edge01.png b/HandsOnLabs/02-DeployingAzureLocal/media/edge01.png new file mode 100644 index 00000000..be884c1b Binary files /dev/null and b/HandsOnLabs/02-DeployingAzureLocal/media/edge01.png differ diff --git a/HandsOnLabs/02-DeployingAzureLocal/media/edge02.png b/HandsOnLabs/02-DeployingAzureLocal/media/edge02.png new file mode 100644 index 00000000..31dd86e7 Binary files /dev/null and b/HandsOnLabs/02-DeployingAzureLocal/media/edge02.png differ diff --git a/HandsOnLabs/02-DeployingAzureLocal/media/edge03.png b/HandsOnLabs/02-DeployingAzureLocal/media/edge03.png new file mode 100644 index 00000000..0048b00c Binary files /dev/null and b/HandsOnLabs/02-DeployingAzureLocal/media/edge03.png differ diff --git a/HandsOnLabs/02-DeployingAzureLocal/media/hypervmanager01.png b/HandsOnLabs/02-DeployingAzureLocal/media/hypervmanager01.png new file mode 100644 index 00000000..73294e75 Binary files /dev/null and b/HandsOnLabs/02-DeployingAzureLocal/media/hypervmanager01.png differ diff --git a/HandsOnLabs/02-DeployingAzureLocal/media/powershell01.png b/HandsOnLabs/02-DeployingAzureLocal/media/powershell01.png new file mode 100644 index 00000000..4c54ab1e Binary files /dev/null and b/HandsOnLabs/02-DeployingAzureLocal/media/powershell01.png differ diff --git a/HandsOnLabs/02-DeployingAzureLocal/media/powershell02.png b/HandsOnLabs/02-DeployingAzureLocal/media/powershell02.png new file mode 100644 index 00000000..b48bd209 Binary files /dev/null and b/HandsOnLabs/02-DeployingAzureLocal/media/powershell02.png differ diff --git a/HandsOnLabs/02-DeployingAzureLocal/media/powershell03.png b/HandsOnLabs/02-DeployingAzureLocal/media/powershell03.png new file mode 100644 index 00000000..e85541cc Binary files /dev/null and b/HandsOnLabs/02-DeployingAzureLocal/media/powershell03.png differ diff --git a/HandsOnLabs/02-DeployingAzureLocal/media/powershell04.png b/HandsOnLabs/02-DeployingAzureLocal/media/powershell04.png new file mode 100644 index 00000000..51851a66 Binary files /dev/null and b/HandsOnLabs/02-DeployingAzureLocal/media/powershell04.png differ diff --git a/HandsOnLabs/02-DeployingAzureLocal/media/powershell05.png b/HandsOnLabs/02-DeployingAzureLocal/media/powershell05.png new file mode 100644 index 00000000..b0807106 Binary files /dev/null and b/HandsOnLabs/02-DeployingAzureLocal/media/powershell05.png differ diff --git a/HandsOnLabs/02-DeployingAzureLocal/readme.md b/HandsOnLabs/02-DeployingAzureLocal/readme.md new file mode 100644 index 00000000..1c7f3f2f --- /dev/null +++ b/HandsOnLabs/02-DeployingAzureLocal/readme.md @@ -0,0 +1,399 @@ +# Deploying Azure Local + + + +- [Deploying Azure Local](#deploying-azure-local) + - [About the lab](#about-the-lab) + - [LabConfig](#labconfig) + - [NTP Prerequisite](#ntp-prerequisite) + - [The Lab](#the-lab) + - [Task 01 - Connect to servers](#task-01---connect-to-servers) + - [Step 01 Login to Management VM](#step-01-login-to-management-vm) + - [Step 02 Connect to Servers using PowerShell Remoting](#step-02-connect-to-servers-using-powershell-remoting) + - [Task 02 - Validate environment using Environment Checker tool](#task-02---validate-environment-using-environment-checker-tool) + - [Task 03 - Create AD Prerequisites](#task-03---create-ad-prerequisites) + - [Task 04 - Create Azure Resources](#task-04---create-azure-resources) + - [Task 05 - Register with Arc](#task-05---register-with-arc) + - [Task 07 - Validation prerequisites](#task-07---validation-prerequisites) + - [Task 06 - Deploy via Azure Portal](#task-06---deploy-via-azure-portal) + + + +## About the lab + +In this lab you will deploy 2 node Azure Local into virtual environment using [cloud deployment](https://learn.microsoft.com/en-us/azure-stack/hci/whats-new#cloud-based-deployment). + +To setup lab, follow [01-Creating First Lab](../../HandsOnLabs/01-CreatingFirstLab/readme.md) + +Lab consumes ~60GB RAM. You can modify number of VMs and get down to ~30GB + +## LabConfig + +```PowerShell +$LabConfig=@{AllowedVLANs="1-10,711-719" ; DomainAdminName='LabAdmin'; AdminPassword='LS1setup!' ; DCEdition='4'; Internet=$true; AdditionalNetworksConfig=@(); VMs=@()} + +#Azure Local 24H2 +#labconfig will not domain join VMs +1..2 | ForEach-Object {$LABConfig.VMs += @{ VMName = "ALNode$_" ; Configuration = 'S2D' ; ParentVHD = 'AzSHCI24H2_G2.vhdx' ; HDDNumber = 4 ; HDDSize= 1TB ; MemoryStartupBytes= 24GB; VMProcessorCount="MAX" ; vTPM=$true ; Unattend="NoDjoin" ; NestedVirt=$true }} + +#VM for Windows Admin Center (optional) +#$LabConfig.VMs += @{ VMName = 'WACGW' ; ParentVHD = 'Win2025Core_G2.vhdx'; MGMTNICs=1} + +#Management machine (Windows Server 2025 GUI) +$LabConfig.VMs += @{ VMName = 'Management' ; ParentVHD = 'Win2025_G2.vhdx'; MGMTNICs=1 ; AddToolsVHD=$True } + +``` + +## NTP Prerequisite + +To successfully configure NTP server it's necessary to disable time synchronization from Hyper-V host. + +Run following code **from hyper-v host** to disable time sync + +```PowerShell +Get-VM *ALNode* | Disable-VMIntegrationService -Name "Time Synchronization" + +``` + +## The Lab + +### Task 01 - Connect to servers + +#### Step 01 Login to Management VM + +Provide following credentials: + +* Username: LabAdmin +* Password: LS1setup! + +![](./media/hypervmanager01.png) + + +#### Step 02 Connect to Servers using PowerShell Remoting + +In Management machine run following PowerShell command to configure Trusted Hosts and invoke command remotely + +```PowerShell +$Servers="ALNode1","ALNode2" +$UserName="Administrator" +$Password="LS1setup!" +$SecuredPassword = ConvertTo-SecureString $password -AsPlainText -Force +$Credentials= New-Object System.Management.Automation.PSCredential ($UserName,$SecuredPassword) + +#configure trusted hosts to be able to communicate with servers +$TrustedHosts=@() +$TrustedHosts+=$Servers +Set-Item WSMan:\localhost\Client\TrustedHosts -Value $($TrustedHosts -join ',') -Force + +#Send some command to servers +Invoke-Command -ComputerName $Servers -ScriptBlock { + Get-NetAdapter +} -Credential $Credentials + +``` + +![](./media/powershell01.png) + +### Task 02 - Validate environment using Environment Checker tool + +* https://learn.microsoft.com/en-in/azure/azure-local/manage/use-environment-checker?tabs=connectivity + + +```PowerShell +<# this breaks registration - recipe validation failed + +#Install modules +Invoke-Command -ComputerName $Servers -Scriptblock { + Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force + Install-Module PowerShellGet -AllowClobber -Force + Install-Module -Name AzStackHci.EnvironmentChecker -Force +} -Credential $Credentials + +#validate environment +$result=Invoke-Command -ComputerName $Servers -Scriptblock { + Invoke-AzStackHciConnectivityValidation -PassThru +} -Credential $Credentials +$result | Out-GridView + +#> +``` + +![](./media/powershell02.png) + +### Task 03 - Create AD Prerequisites + +* https://learn.microsoft.com/en-us/azure/azure-local/deploy/deployment-prep-active-directory + +```PowerShell +$AsHCIOUName="OU=ALClus01,DC=Corp,DC=contoso,DC=com" +$LCMUserName="ALClus01-LCMUser" +$LCMPassword="LS1setup!LS1setup!" +#Create LCM credentials +$SecuredPassword = ConvertTo-SecureString $LCMPassword -AsPlainText -Force +$LCMCredentials= New-Object System.Management.Automation.PSCredential ($LCMUserName,$SecuredPassword) + +#create objects in Active Directory + #install posh module for prestaging Active Directory + Install-PackageProvider -Name NuGet -Force + Install-Module AsHciADArtifactsPreCreationTool -Repository PSGallery -Force + + #make sure active directory module and GPMC is installed + Install-WindowsFeature -Name RSAT-AD-PowerShell,GPMC + + #populate objects + New-HciAdObjectsPreCreation -AzureStackLCMUserCredential $LCMCredentials -AsHciOUName $AsHCIOUName + + #to check OU (and future cluster) in GUI install management tools + Install-WindowsFeature -Name "RSAT-ADDS","RSAT-Clustering" + +``` + +![](./media/powershell03.png) + +### Task 04 - Create Azure Resources + +As you can see, there's an optional code block that can create Arc Gateway. Simply uncomment if you want to deploy Azure Local with Arc Gw. + +```PowerShell +$GatewayName="ALClus01-ArcGW" +$ResourceGroupName="ALClus01-RG" +$Location="eastus" + +#login to azure + #download Azure module + Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force + if (!(Get-InstalledModule -Name az.accounts -ErrorAction Ignore)){ + Install-Module -Name Az.Accounts -Force + } + #login using device authentication + Connect-AzAccount -UseDeviceAuthentication + + #assuming new az.accounts module was used and it asked you what subscription to use - then correct subscription is selected for context + $Subscription=(Get-AzContext).Subscription + + #install az resources module + if (!(Get-InstalledModule -Name az.resources -ErrorAction Ignore)){ + Install-Module -Name az.resources -Force + } + + #create resource group + if (-not(Get-AzResourceGroup -Name $ResourceGroupName -ErrorAction Ignore)){ + New-AzResourceGroup -Name $ResourceGroupName -Location $location + } +#region (Optional) configure Arc Gateway +<# + #install az.arcgateway module + if (!(Get-InstalledModule -Name az.arcgateway -ErrorAction Ignore)){ + Install-Module -Name az.arcgateway -Force + } + #make sure "Microsoft.HybridCompute" is registered (and possibly other RPs) + Register-AzResourceProvider -ProviderNamespace "Microsoft.HybridCompute" + Register-AzResourceProvider -ProviderNamespace "Microsoft.GuestConfiguration" + Register-AzResourceProvider -ProviderNamespace "Microsoft.HybridConnectivity" + Register-AzResourceProvider -ProviderNamespace "Microsoft.AzureStackHCI" + + #create GW + if (Get-AzArcGateway -Name $gatewayname -ResourceGroupName $ResourceGroupName -ErrorAction Ignore){ + $ArcGWInfo=Get-AzArcGateway -Name $gatewayname -ResourceGroupName $ResourceGroupName + }else{ + $ArcGWInfo=New-AzArcGateway -Name $GatewayName -ResourceGroupName $ResourceGroupName -Location $Location -SubscriptionID $Subscription.ID + } +#> +#endregion + +#generate variables for use in this window +$SubscriptionID=$Subscription.ID +$Region=$Location +$TenantID=$Subscription.TenantID +$ArcGatewayID=$ArcGWInfo.ID + +#output variables (so you can just copy it and have powershell code to create variables in another session or you can copy it to WebUI deployment) +Write-Host -ForegroundColor Cyan @" + #Variables to copy + `$SubscriptionID=`"$($Subscription.ID)`" + `$ResourceGroupName=`"$ResourceGroupName`" + `$Region=`"$Location`" + `$TenantID=`"$($subscription.tenantID)`" + `$ArcGatewayID=`"$(($ArcGWInfo).ID)`" +"@ + +``` + +Script outputs code that you can copy and hand over to another window if needed to provide variables. + +![](./media/powershell04.png) + +![](./media/edge01.png) + +### Task 05 - Register with Arc + +* https://learn.microsoft.com/en-us/azure/azure-local/deploy/deployment-arc-register-server-permissions?view=azloc-24112&tabs=powershell + +As you can see, code contains few fixes that will be addressed in future releases (converting token to plaintext, starting scheduled task that fails in virtual environments...) + +```PowerShell +#Make sure resource providers are registered +Register-AzResourceProvider -ProviderNamespace "Microsoft.HybridCompute" +Register-AzResourceProvider -ProviderNamespace "Microsoft.GuestConfiguration" +Register-AzResourceProvider -ProviderNamespace "Microsoft.HybridConnectivity" +Register-AzResourceProvider -ProviderNamespace "Microsoft.AzureStackHCI" +Register-AzResourceProvider -ProviderNamespace "Microsoft.Kubernetes" +Register-AzResourceProvider -ProviderNamespace "Microsoft.KubernetesConfiguration" +Register-AzResourceProvider -ProviderNamespace "Microsoft.ExtendedLocation" +Register-AzResourceProvider -ProviderNamespace "Microsoft.ResourceConnector" +Register-AzResourceProvider -ProviderNamespace "Microsoft.HybridContainerService" +Register-AzResourceProvider -ProviderNamespace "Microsoft.Attestation" +Register-AzResourceProvider -ProviderNamespace "Microsoft.Storage" + +#deploy ARC Agent (with Arc Gateway, without proxy. For more examples visit https://learn.microsoft.com/en-us/azure/azure-local/deploy/deployment-arc-register-server-permissions?tabs=powershell) + $armtoken = (Get-AzAccessToken).Token + $id = (Get-AzContext).Account.Id + $Cloud="AzureCloud" + + #check if token is plaintext (older module version outputs plaintext, version 5 outputs secure string) - will be fixed in 2506 + # Check if the token is a SecureString + if ($armtoken -is [System.Security.SecureString]) { + # Convert SecureString to plaintext + $armtoken = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($armtoken)) + }else { + Write-Output "Token is already plaintext." + } + + #check if ImageCustomizationScheduledTask is not in disabled state (if it's "ready", run it) - will be fixed in 2506 + Invoke-Command -ComputerName $Servers -ScriptBlock { + $task=Get-ScheduledTask -TaskName ImageCustomizationScheduledTask + if ($task.State -ne "Disabled" -and $task.State -ne "Running"){ + Write-Output "Starting Scheduled task ImageCustomizationScheduledTask on $env:ComputerName" + $task | Start-ScheduledTask + } + } -Credential $Credentials + #wait until it's disabled + Invoke-Command -ComputerName $Servers -ScriptBlock { + $task=Get-ScheduledTask -TaskName ImageCustomizationScheduledTask + if ($task.state -eq "running"){ + do { + Write-Output "Waiting for ImageCustomizationScheduledTask on $env:computerName to finish" + Start-Sleep 1 + $task=Get-ScheduledTask -TaskName ImageCustomizationScheduledTask + } while ($task.state -ne "Disabled") + } + } -Credential $Credentials + + #register servers + Invoke-Command -ComputerName $Servers -ScriptBlock { + Invoke-AzStackHciArcInitialization -SubscriptionID $using:SubscriptionID -ResourceGroup $using:ResourceGroupName -TenantID $using:TenantID -Cloud $using:Cloud -Region $Using:Location -ArmAccessToken $using:ARMtoken -AccountID $using:id #-ArcGatewayID $using:ArcGatewayID + } -Credential $Credentials + +``` + +Result: + +![](./media/powershell05.png) + +![](./media/edge02.png) + +### Task 07 - Validation prerequisites + +```PowerShell +#region to successfully validate you need make sure there's just one GW + #make sure there is only one management NIC with IP address (setup is complaining about multiple gateways) + Invoke-Command -ComputerName $servers -ScriptBlock { + Get-NetIPConfiguration | Where-Object IPV4defaultGateway | Get-NetAdapter | Sort-Object Name | Select-Object -Skip 1 | Set-NetIPInterface -Dhcp Disabled + } -Credential $Credentials +#endregion + +#region Convert DHCP address to Static (since 2411 there's a check for static IP) + Invoke-Command -ComputerName $Servers -ScriptBlock { + $InterfaceAlias=(Get-NetIPAddress -AddressFamily IPv4 | Where-Object {$_.IPAddress -NotLike "169*" -and $_.PrefixOrigin -eq "DHCP"}).InterfaceAlias + $IPConf=Get-NetIPConfiguration -InterfaceAlias $InterfaceAlias + $IPAddress=Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias $InterfaceAlias + $IP=$IPAddress.IPAddress + $Index=$IPAddress.InterfaceIndex + $GW=$IPConf.IPv4DefaultGateway.NextHop + $Prefix=$IPAddress.PrefixLength + $DNSServers=@() + $ipconf.dnsserver | ForEach-Object {if ($_.addressfamily -eq 2){$DNSServers+=$_.ServerAddresses}} + Set-NetIPInterface -InterfaceIndex $Index -Dhcp Disabled + New-NetIPAddress -InterfaceIndex $Index -AddressFamily IPv4 -IPAddress $IP -PrefixLength $Prefix -DefaultGateway $GW -ErrorAction SilentlyContinue + Set-DnsClientServerAddress -InterfaceIndex $index -ServerAddresses $DNSServers + } -Credential $Credentials +#endregion + +#region and make sure password is complex and long enough (12chars at least) + $NewPassword="LS1setup!LS1setup!" + Invoke-Command -ComputerName $servers -ScriptBlock { + Set-LocalUser -Name Administrator -AccountNeverExpires -Password (ConvertTo-SecureString $Using:NewPassword -AsPlainText -Force) + } -Credential $Credentials + #create new credentials + $UserName="Administrator" + $SecuredPassword = ConvertTo-SecureString $NewPassword -AsPlainText -Force + $Credentials= New-Object System.Management.Automation.PSCredential ($UserName,$SecuredPassword) +#endregion + +``` + +### Task 06 - Deploy via Azure Portal + +* https://learn.microsoft.com/en-us/azure/azure-local/deploy/deploy-via-portal + +In Azure Portal navigate to Azure Arc and into Azure Local under Host environments. In Get started with Azure Local, click on **Create instance** under **Deploy Azure Local**. + +![](./media/edge03.png) + +Use values below for virtual cluster + +``` +Basics: + Resource Group: ALClus01-RG + ClusterName: ALClus01 + Keyvaultname: + +Configuration: + New Configuration + +Networking + Network Switch for storage + Group All traffic + + Network adapter 1: Ethernet + Network adapter 1 VLAN ID: 711 (default) + Network adapter 2: Ethernet 2 + Network adapter 2 VLAN ID: 712 (default) + + RDMA Protocol: Disabled (in case you are running lab in VMs) + Jumbo Frames: 1514 (in case you are running lab in VMs as hyper-v does not by default support Jumbo Frames) + + Starting IP: 10.0.0.111 + ENding IP: 10.0.0.116 + Subnet mask: 255.255.255.0 + Default Gateway: 10.0.0.1 + DNS Server: 10.0.0.1 + +Management + Custom location name: ALClus01CustomLocation (default) + + Azure storage account name: + + Domain: corp.contoso.com + Computer name prefix: ALClus01 + OU: OU=ALClus01,DC=Corp,DC=contoso,DC=com + + Deployment account: + Username: ALClus01-LCMUser + Password: LS1setup!LS1setup! + + Local Administrator + Username: Administrator + Password: LS1setup!LS1setup! + +Security: + Customized security settings + Unselect Bitlocker for data volumes (would consume too much space) + +Advanced: + Create workload volumes (Default) + +Tags: + +``` + diff --git a/README.md b/README.md index 8208b8f5..cb354f57 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,7 @@ ## tl;dr -To start using MSLab just download the latest version of the scripts from the [Releases](https://github.com/microsoft/MSLab/releases) section of this repository or follow [Dell GEOS hands-on-labs](https://github.com/DellGEOS/AzureLocalHOLs). - +To start using MSLab just download the latest version of the scripts from the [Releases](https://github.com/microsoft/MSLab/releases) or start with [Hands-on-Labs](HandsOnLabs/). 💡 Shortcut to the latest version is https://aka.ms/mslab/download @@ -11,31 +10,36 @@ To start using MSLab just download the latest version of the scripts from the [R Download MSLab

+ +## NEW - Hands-on-Labs + +Originally I developed Hands-on Labs when I was working for Dell at https://github.com/DellGEOS/AzureStackHOLs. To continue with just virtual labs, MSLab HOLs are now being added. + +* [01 Creating First Lab](HandsOnLabs/01-CreatingFirstLab/) +* [02 Deploying Azure Local](HandsOnLabs/02-DeployingAzureLocal/) + + ## Introduction - [MSLab](#mslab) - [tl;dr](#tldr) + - [NEW - Hands-on-Labs](#new---hands-on-labs) - [Introduction](#introduction) - [Requirements](#requirements) - [Scripts](#scripts) - [Data Collection](#data-collection) - [How to get the Scripts](#how-to-get-the-scripts) - - [Scenarios](#scenarios) + - [Scenarios Archived](#scenarios-archived) - [Use cases](#use-cases) - [Prototyping](#prototyping) - [Hands on Labs](#hands-on-labs) - [Issue reproduction](#issue-reproduction) - [Sessions](#sessions) - [Run in PowerShell 7](#run-in-powershell-7) -- [Set context menu option](#set-context-menu-option) -- [Set context menu option](#set-context-menu-option) - [Execution Policy](#execution-policy) -- [Get a Code signing certificate from store](#get-a-code-signing-certificate-from-store) -- [Get a Code signing certificate from store](#get-a-code-signing-certificate-from-store) -- [Add signature to a LabConfig file](#add-signature-to-a-labconfig-file) - - [Linux (preview)](#linux-preview) + - [Linux preview](#linux-preview) @@ -69,9 +73,11 @@ In the past, this ZIP file was stored in the git repository, and recently we swi This built ZIP file is more optimized, e. g. the file 0_Shared.ps1 is in-lined to the rest of the scripts to keep the number of MSLab files as low as possible. Compared to the git repository where I tend to split those scripts to multiple independent files for a better supportability on our side. -## Scenarios +## Scenarios (Archived) + +Over the time, we have developed multiple [scenarios](Scenarios/) simulating Azure Stack HCI and even deep dives into other technologies such as [Windows Admin Center](Scenarios/Windows%20Admin%20Center%20and%20Enterprise%20CA), [Certification Authority](Scenarios/Certification%20Authority) or [Just Enough Administration](Scenarios/BitLocker%20with%20JEA). Scenarios can be reused for real environments. For example [S2D Hyperconverged](Scenarios/S2D%20Hyperconverged) can be used to deploy real Azure Stack HCI clusters. It has not been updated lately as all effort went to [Dell Azure Local HOLs](https://github.com/DellGEOS/AzureLocalHOLs). -Over the time, we have developed multiple [scenarios](Scenarios/) simulating Azure Stack HCI and even deep dives into other technologies such as [Windows Admin Center](Scenarios/Windows%20Admin%20Center%20and%20Enterprise%20CA), [Certification Authority](Scenarios/Certification%20Authority) or [Just Enough Administration](Scenarios/BitLocker%20with%20JEA). Scenarios can be reused for real environments. For example [S2D Hyperconverged](Scenarios/S2D%20Hyperconverged) can be used to deploy real Azure Stack HCI clusters. It has not been updated lately as all effort went to [Dell Azure Local HOLs](https://github.com/DellGEOS/AzureLocalHOLs) +It has not been updated for quite some time, so consider it just a inspiration. ## Use cases