Skip to content

Commit d37e72c

Browse files
authored
Merge pull request #219345 from xnkevinnguyen/devbox-custom-images
Add how-to guide for devbox users to provision custom images with Azu…
2 parents 62c9f5a + 9ae0717 commit d37e72c

File tree

4 files changed

+279
-0
lines changed

4 files changed

+279
-0
lines changed
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
---
2+
title: Configure a Dev Box with Azure Image Builder
3+
titleSuffix: Microsoft Dev Box Preview
4+
description: 'Learn how to create a custom image with Azure Image Builder, then create a Dev box with the image.'
5+
services: dev-box
6+
ms.service: dev-box
7+
author: RoseHJM
8+
ms.author: rosemalcolm
9+
ms.date: 11/17/2022
10+
ms.topic: how-to
11+
---
12+
13+
# Configure a Dev Box with Azure Image Builder
14+
15+
By using standardized virtual machine (VM) images, your organization can more easily migrate to the cloud and help ensure consistency in your deployments. Images ordinarily include predefined security, configuration settings, and any necessary software. Setting up your own imaging pipeline requires time, infrastructure, and many other details. With Azure VM Image Builder, you can create a configuration that describes your image and submit it to the service, where the image is built and then distributed to a dev box project. In this article, you will create a customized dev box using a template which includes a customization step to install Visual Studio Code.
16+
17+
Although it's possible to create custom VM images by hand or by using other tools, the process can be cumbersome and unreliable. VM Image Builder, which is built on HashiCorp Packer, gives you the benefits of a managed service.
18+
19+
To reduce the complexity of creating VM images, VM Image Builder:
20+
21+
- Removes the need to use complex tooling, processes, and manual steps to create a VM image. VM Image Builder abstracts out all these details and hides Azure-specific requirements, such as the need to generalize the image (Sysprep). And it gives more advanced users the ability to override such requirements.
22+
23+
- Can be integrated with existing image build pipelines for a click-and-go experience. To do so, you can either call VM Image Builder from your pipeline or use an Azure VM Image Builder service DevOps task (preview).
24+
25+
- Can fetch customization data from various sources, which removes the need to collect them all from one place.
26+
27+
- Can be integrated with Compute Gallery, which creates an image management system with which to distribute, replicate, version, and scale images globally. Additionally, you can distribute the same resulting image as a VHD or as one or more managed images, without having to rebuild them from scratch.
28+
29+
## Prerequisites
30+
To provision a custom image you've creating by using VM Image Builder, you need:
31+
- Owner or Contributor permissions on an Azure Subscription or a specific resource group.
32+
- A resource group
33+
- A dev center with an attached network connection.
34+
If you don't have a dev center with an attached network connection, follow these steps to attach the network connection: [Create a network connection](./quickstart-configure-dev-box-service.md#create-a-network-connection).
35+
36+
## Create a Windows image and distribute it to an Azure Compute Gallery
37+
The next step is to use Azure VM Image Builder and Azure PowerShell to create an image version in an Azure Compute Gallery (formerly Shared Image Gallery) and then distribute the image globally. You can also do this by using the Azure CLI.
38+
39+
1. To use VM Image Builder, you need to register the features.
40+
41+
Check your provider registrations. Make sure that each one returns Registered.
42+
43+
```powershell
44+
Get-AzResourceProvider -ProviderNamespace Microsoft.VirtualMachineImages | Format-table -Property ResourceTypes,RegistrationState
45+
Get-AzResourceProvider -ProviderNamespace Microsoft.Storage | Format-table -Property ResourceTypes,RegistrationState
46+
Get-AzResourceProvider -ProviderNamespace Microsoft.Compute | Format-table -Property ResourceTypes,RegistrationState
47+
Get-AzResourceProvider -ProviderNamespace Microsoft.KeyVault | Format-table -Property ResourceTypes,RegistrationState
48+
Get-AzResourceProvider -ProviderNamespace Microsoft.Network | Format-table -Property ResourceTypes,RegistrationState
49+
```
50+
51+
52+
If they don't return Registered, register the providers by running the following commands:
53+
```powershell
54+
Register-AzResourceProvider -ProviderNamespace Microsoft.VirtualMachineImages
55+
Register-AzResourceProvider -ProviderNamespace Microsoft.Storage
56+
Register-AzResourceProvider -ProviderNamespace Microsoft.Compute
57+
Register-AzResourceProvider -ProviderNamespace Microsoft.KeyVault
58+
Register-AzResourceProvider -ProviderNamespace Microsoft.Network
59+
```
60+
61+
2. Install PowerShell modules:
62+
63+
```powershell
64+
'Az.ImageBuilder', 'Az.ManagedServiceIdentity' | ForEach-Object {Install-Module -Name $_ -AllowPrerelease}
65+
```
66+
67+
3. Create variables to store information that you'll use more than once.
68+
69+
Copy the sample code and replace the Resource group with the resource group you have used to create the dev center.
70+
71+
```powershell
72+
# Get existing context
73+
$currentAzContext = Get-AzContext
74+
# Get your current subscription ID.
75+
$subscriptionID=$currentAzContext.Subscription.Id
76+
# Destination image resource group
77+
$imageResourceGroup="<Resource group>"
78+
# Location
79+
$location="eastus2"
80+
# Image distribution metadata reference name
81+
$runOutputName="aibCustWinManImg01"
82+
# Image template name
83+
$imageTemplateName="vscodeWinTemplate"
84+
```
85+
86+
4. Create a user-assigned identity and set permissions on the resource group
87+
88+
VM Image Builder uses the provided user-identity to inject the image into Azure Compute Gallery. In this example, you create an Azure role definition with specific actions for distributing the image. The role definition is then assigned to the user identity.
89+
90+
```powershell
91+
# setup role def names, these need to be unique
92+
$timeInt=$(get-date -UFormat "%s")
93+
$imageRoleDefName="Azure Image Builder Image Def"+$timeInt
94+
$identityName="aibIdentity"+$timeInt
95+
96+
## Add an Azure PowerShell module to support AzUserAssignedIdentity
97+
Install-Module -Name Az.ManagedServiceIdentity
98+
99+
# Create an identity
100+
New-AzUserAssignedIdentity -ResourceGroupName $imageResourceGroup -Name $identityName
101+
102+
$identityNameResourceId=$(Get-AzUserAssignedIdentity -ResourceGroupName $imageResourceGroup -Name $identityName).Id
103+
$identityNamePrincipalId=$(Get-AzUserAssignedIdentity -ResourceGroupName $imageResourceGroup -Name $identityName).PrincipalId
104+
```
105+
106+
5. Assign permissions for the identity to distribute the images
107+
108+
Use this command to download an Azure role definition template, and then update it with the previously specified parameters.
109+
110+
```powershell
111+
$aibRoleImageCreationUrl="https://raw.githubusercontent.com/azure/azvmimagebuilder/master/solutions/12_Creating_AIB_Security_Roles/aibRoleImageCreation.json"
112+
$aibRoleImageCreationPath = "aibRoleImageCreation.json"
113+
114+
# Download the configuration
115+
Invoke-WebRequest -Uri $aibRoleImageCreationUrl -OutFile $aibRoleImageCreationPath -UseBasicParsing
116+
((Get-Content -path $aibRoleImageCreationPath -Raw) -replace '<subscriptionID>',$subscriptionID) | Set-Content -Path $aibRoleImageCreationPath
117+
((Get-Content -path $aibRoleImageCreationPath -Raw) -replace '<rgName>', $imageResourceGroup) | Set-Content -Path $aibRoleImageCreationPath
118+
((Get-Content -path $aibRoleImageCreationPath -Raw) -replace 'Azure Image Builder Service Image Creation Role', $imageRoleDefName) | Set-Content -Path $aibRoleImageCreationPath
119+
120+
# Create a role definition
121+
New-AzRoleDefinition -InputFile ./aibRoleImageCreation.json
122+
# Grant the role definition to the VM Image Builder service principal
123+
New-AzRoleAssignment -ObjectId $identityNamePrincipalId -RoleDefinitionName $imageRoleDefName -Scope "/subscriptions/$subscriptionID/resourceGroups/$imageResourceGroup"
124+
```
125+
126+
## Create an Azure Compute Gallery
127+
128+
To use VM Image Builder with an Azure Compute Gallery, you need to have an existing gallery and image definition. VM Image Builder doesn't create the gallery and image definition for you. The definition created below will have Trusted Launch as security type and meets the windows 365 image requirements.
129+
130+
```powershell
131+
# Gallery name
132+
$galleryName= "devboxGallery"
133+
134+
# Image definition name
135+
$imageDefName ="vscodeImageDef"
136+
137+
# Additional replication region
138+
$replRegion2="eastus"
139+
140+
# Create the gallery
141+
New-AzGallery -GalleryName $galleryName -ResourceGroupName $imageResourceGroup -Location $location
142+
143+
$SecurityType = @{Name='SecurityType';Value='TrustedLaunch'}
144+
$features = @($SecurityType)
145+
146+
# Create the image definition
147+
New-AzGalleryImageDefinition -GalleryName $galleryName -ResourceGroupName $imageResourceGroup -Location $location -Name $imageDefName -OsState generalized -OsType Windows -Publisher 'myCompany' -Offer 'vscodebox' -Sku '1-0-0' -Feature $features -HyperVGeneration "V2"
148+
```
149+
150+
1. Copy the ARM Template for Azure Image Builder. This template indicates the source image and also the customizations applied. With this template, we are installing choco and vscode. It also indicates where the image will be distributed.
151+
152+
```json
153+
{
154+
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
155+
"contentVersion": "1.0.0.0",
156+
"parameters": {
157+
"imageTemplateName": {
158+
"type": "string"
159+
},
160+
"api-version": {
161+
"type": "string"
162+
},
163+
"svclocation": {
164+
"type": "string"
165+
}
166+
},
167+
"variables": {},
168+
"resources": [
169+
{
170+
"name": "[parameters('imageTemplateName')]",
171+
"type": "Microsoft.VirtualMachineImages/imageTemplates",
172+
"apiVersion": "[parameters('api-version')]",
173+
"location": "[parameters('svclocation')]",
174+
"dependsOn": [],
175+
"tags": {
176+
"imagebuilderTemplate": "win11multi",
177+
"userIdentity": "enabled"
178+
},
179+
"identity": {
180+
"type": "UserAssigned",
181+
"userAssignedIdentities": {
182+
"<imgBuilderId>": {}
183+
}
184+
},
185+
"properties": {
186+
"buildTimeoutInMinutes": 100,
187+
"vmProfile": {
188+
"vmSize": "Standard_DS2_v2",
189+
"osDiskSizeGB": 127
190+
},
191+
"source": {
192+
"type": "PlatformImage",
193+
"publisher": "MicrosoftWindowsDesktop",
194+
"offer": "Windows-11",
195+
"sku": "win11-21h2-avd",
196+
"version": "latest"
197+
},
198+
"customize": [
199+
{
200+
"type": "PowerShell",
201+
"name": "Install Choco and Vscode",
202+
"inline": [
203+
"Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))",
204+
"choco install -y vscode"
205+
]
206+
}
207+
],
208+
"distribute":
209+
[
210+
{
211+
"type": "SharedImage",
212+
"galleryImageId": "/subscriptions/<subscriptionID>/resourceGroups/<rgName>/providers/Microsoft.Compute/galleries/<sharedImageGalName>/images/<imageDefName>",
213+
"runOutputName": "<runOutputName>",
214+
"artifactTags": {
215+
"source": "azureVmImageBuilder",
216+
"baseosimg": "win11multi"
217+
},
218+
"replicationRegions": [
219+
"<region1>",
220+
"<region2>"
221+
]
222+
}
223+
]
224+
}
225+
}
226+
]
227+
}
228+
```
229+
2. Configure the template with your variables.
230+
```powershell
231+
$templateFilePath = <Template Path>
232+
233+
(Get-Content -path $templateFilePath -Raw ) -replace '<subscriptionID>',$subscriptionID | Set-Content -Path $templateFilePath
234+
(Get-Content -path $templateFilePath -Raw ) -replace '<rgName>',$imageResourceGroup | Set-Content -Path $templateFilePath
235+
(Get-Content -path $templateFilePath -Raw ) -replace '<runOutputName>',$runOutputName | Set-Content -Path $templateFilePath
236+
(Get-Content -path $templateFilePath -Raw ) -replace '<imageDefName>',$imageDefName | Set-Content -Path $templateFilePath
237+
(Get-Content -path $templateFilePath -Raw ) -replace '<sharedImageGalName>',$galleryName| Set-Content -Path $templateFilePath
238+
(Get-Content -path $templateFilePath -Raw ) -replace '<region1>',$location | Set-Content -Path $templateFilePath
239+
(Get-Content -path $templateFilePath -Raw ) -replace '<region2>',$replRegion2 | Set-Content -Path $templateFilePath
240+
((Get-Content -path $templateFilePath -Raw) -replace '<imgBuilderId>',$identityNameResourceId) | Set-Content -Path $templateFilePath
241+
```
242+
3. Create the image version
243+
244+
Your template must be submitted to the service. The following commands will download any dependent artifacts, such as scripts, and store them in the staging resource group, which is prefixed with IT_.
245+
246+
```powershell
247+
New-AzResourceGroupDeployment -ResourceGroupName $imageResourceGroup -TemplateFile $templateFilePath -Api-Version "2020-02-14" -imageTemplateName $imageTemplateName -svclocation $location
248+
```
249+
To build the image, invoke 'Run' on the template.
250+
```powershell
251+
Invoke-AzResourceAction -ResourceName $imageTemplateName -ResourceGroupName $imageResourceGroup -ResourceType Microsoft.VirtualMachineImages/imageTemplates -ApiVersion "2020-02-14" -Action Run
252+
```
253+
Creating the image and replicating it to both regions can take a few moments. Before you begin creating a dev box definition, wait until this part is finished.
254+
```powershell
255+
Get-AzImageBuilderTemplate -ImageTemplateName $imageTemplateName -ResourceGroupName $imageResourceGroup | Select-Object -Property Name, LastRunStatusRunState, LastRunStatusMessage, ProvisioningState
256+
```
257+
Alternatively, you can navigate to the Azure portal to your compute gallery > image definition to view the provisioning state of your image.
258+
259+
![Provisioning state of the customized image version](./media/how-to-customize-devbox-azure-image-builder/image-version-provisioning-state.png)
260+
261+
## Configure the Azure Compute Gallery
262+
263+
Once your custom image has been provisioned within the compute gallery, you can configure the gallery to use the images within the dev center. More details here:
264+
265+
[Configure an Azure Compute Gallery](./how-to-configure-azure-compute-gallery.md)
266+
267+
## Setting up Dev Box Service with Custom Image
268+
269+
Once the compute gallery images are available in the dev center. You can use the custom image with the dev box service. More details here:
270+
271+
[Configure the Microsoft Dev Box Service](./quickstart-configure-dev-box-service.md)
272+
273+
## Next steps
274+
- [Create dev box definitions](./quickstart-configure-dev-box-service.md#create-a-dev-box-definition)
275+
- [Configure an Azure Compute Gallery](./how-to-configure-azure-compute-gallery.md)

articles/dev-box/index.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ landingContent:
5757
links:
5858
- text: Configure an Azure Compute Gallery
5959
url: how-to-configure-azure-compute-gallery.md
60+
- text: Provision a custom image with Azure Image Builder
61+
url: how-to-customize-devbox-azure-image-builder.md
6062

6163
# Card
6264
- title: Reference docs
37.2 KB
Loading

articles/dev-box/toc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
href: how-to-manage-network-connection.md
4444
- name: Microsoft Dev Box CLI
4545
href: how-to-install-dev-box-cli.md
46+
- name: Provision a Custom Image with Azure Image Builder
47+
href: how-to-customize-devbox-azure-image-builder.md
4648
- name: Reference
4749
items:
4850
- name: Azure CLI

0 commit comments

Comments
 (0)