创建映像并使用用户分配的托管标识来访问 Azure 存储帐户中的文件

适用于:✔️ Linux VM ✔️ 灵活规模集

本文介绍如何使用 Azure VM 映像生成器创建自定义映像。 该服务使用用户分配的托管标识访问 Azure 存储帐户中的文件,并可阻止对存储帐户的未经身份验证的访问。

Azure VM 映像生成器支持使用脚本并从 GitHub、Azure 存储帐户和其他位置复制文件。 如果要使用这些位置,那么 VM 映像生成器必须可以从外部访问它们。

在以下示例中,你将创建两个资源组,一个用于自定义映像,另一个用于托管包含脚本文件的 Azure 存储帐户。 此示例模拟了一个真实场景,即,你可能在各种存储帐户中具有生成工件或映像文件。 你将创建用户分配的标识,然后授予该标识对脚本文件的读取权限,但不允许对文件进行公共访问。 然后将使用 shell 定制器从存储帐户下载并运行脚本。

创建资源组

  1. 因为你将重复使用某些信息,所以要创建一些变量来存储这些信息。

    # Image resource group name 
    imageResourceGroup=aibmdimsi
    # Storage resource group
    strResourceGroup=aibmdimsistor
    # Location 
    location=ChinaNorth3
    # Name of the image to be created
    imageName=aibCustLinuxImgMsi01
    # Image distribution metadata reference name
    runOutputName=u1804ManImgMsiro
    
  2. 为你的订阅 ID 创建变量:

    subscriptionID=$(az account show --query id --output tsv)
    
  3. 同时为映像和脚本存储创建资源组:

    # Create a resource group for the image template
    az group create -n $imageResourceGroup -l $location
    # Create a resource group for the script storage
    az group create -n $strResourceGroup -l $location
    
  4. 创建用户分配的标识,并在资源组上设置权限:

    VM 映像生成器使用提供的用户标识将映像注入到资源组中。 在此示例中将创建一个 Azure 角色定义,该定义具有分发映像的特定操作。 然后将角色定义分配给用户标识。

    # Create a user-assigned identity for VM Image Builder to access the storage account where the script is located
    identityName=aibBuiUserId$(date +'%s')
    az identity create -g $imageResourceGroup -n $identityName
    
    # Get an identity ID
    imgBuilderCliId=$(az identity show -g $imageResourceGroup -n $identityName --query clientId -o tsv)
    
    # Get the user-identity URI, which is needed for the template
    imgBuilderId=/subscriptions/$subscriptionID/resourcegroups/$imageResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$identityName
    
    # Download the preconfigured role definition example
    curl https://raw.githubusercontent.com/azure/azvmimagebuilder/master/solutions/12_Creating_AIB_Security_Roles/aibRoleImageCreation.json -o aibRoleImageCreation.json
    
    # Update the definition
    sed -i -e "s/<subscriptionID>/$subscriptionID/g" aibRoleImageCreation.json
    sed -i -e "s/<rgName>/$imageResourceGroup/g" aibRoleImageCreation.json
    
    # Create role definitions
    az role definition create --role-definition ./aibRoleImageCreation.json
    
    # Grant the role definition to the user-assigned identity
    az role assignment create \
        --assignee $imgBuilderCliId \
        --role "Azure Image Builder Service Image Creation Role" \
        --scope /subscriptions/$subscriptionID/resourceGroups/$imageResourceGroup
    
  5. 创建存储帐户,将示例脚本从 GitHub 复制到该存储帐户中:

    # Script storage account
    scriptStorageAcc=aibstorscript$(date +'%s')
    
    # Script container
    scriptStorageAccContainer=scriptscont$(date +'%s')
    
    # Script URL
    scriptUrl=https://$scriptStorageAcc.blob.core.chinacloudapi.cn/$scriptStorageAccContainer/customizeScript.sh
    
    # Create the storage account and blob in the resource group
    az storage account create -n $scriptStorageAcc -g $strResourceGroup -l $location --sku Standard_LRS
    
    az storage container create -n $scriptStorageAccContainer --fail-on-exist --account-name $scriptStorageAcc
    
    # Copy in an example script from the GitHub repo 
    az storage blob copy start \
        --destination-blob customizeScript.sh \
        --destination-container $scriptStorageAccContainer \
        --account-name $scriptStorageAcc \
        --source-uri https://raw.githubusercontent.com/azure/azvmimagebuilder/master/quickquickstarts/customizeScript.sh
    
  6. 授予 VM 映像生成器在映像资源组中创建资源的权限。 --assignee 值是用户标识 ID。

    az role assignment create \
        --assignee $imgBuilderCliId \
        --role "Storage Blob Data Reader" \
        --scope /subscriptions/$subscriptionID/resourceGroups/$strResourceGroup/providers/Microsoft.Storage/storageAccounts/$scriptStorageAcc/blobServices/default/containers/$scriptStorageAccContainer 
    

修改示例

下载示例 JSON 文件,并使用先前创建的变量对其进行配置。

curl https://raw.githubusercontent.com/azure/azvmimagebuilder/master/quickquickstarts/7_Creating_Custom_Image_using_MSI_to_Access_Storage/helloImageTemplateMsi.json -o helloImageTemplateMsi.json
sed -i -e "s/<subscriptionID>/$subscriptionID/g" helloImageTemplateMsi.json
sed -i -e "s/<rgName>/$imageResourceGroup/g" helloImageTemplateMsi.json
sed -i -e "s/<region>/$location/g" helloImageTemplateMsi.json
sed -i -e "s/<imageName>/$imageName/g" helloImageTemplateMsi.json
sed -i -e "s%<scriptUrl>%$scriptUrl%g" helloImageTemplateMsi.json
sed -i -e "s%<imgBuilderId>%$imgBuilderId%g" helloImageTemplateMsi.json
sed -i -e "s%<runOutputName>%$runOutputName%g" helloImageTemplateMsi.json

创建映像

  1. 将映像配置提交到 VM 映像生成器服务:

    az resource create \
        --resource-group $imageResourceGroup \
        --properties @helloImageTemplateMsi.json \
        --is-full-object \
        --resource-type Microsoft.VirtualMachineImages/imageTemplates \
        -n helloImageTemplateMsi01
    
  2. 启动映像生成:

    az resource invoke-action \
        --resource-group $imageResourceGroup \
        --resource-type  Microsoft.VirtualMachineImages/imageTemplates \
        -n helloImageTemplateMsi01 \
        --action Run 
    

生成可能需要大约 15 分钟才能完成。

创建 VM

  1. 从映像创建 VM:

    az vm create \
    --resource-group $imageResourceGroup \
    --name aibImgVm00 \
    --admin-username aibuser \
    --image $imageName \
    --location $location \
    --generate-ssh-keys
    
  2. 创建 VM 后,启动与 VM 的安全外壳 (SSH) 会话。

    ssh aibuser@<publicIp>
    

建立 SSH 连接后,应会收到一条“每日消息”,说明映像已进行自定义:


*******************************************************
**            This VM was built from the:            **
**      !! AZURE VM IMAGE BUILDER Custom Image !!    **
**         You have just been Customized :-)         **
*******************************************************

清理资源

如果不再需要在此过程中创建的资源,可以通过运行以下代码将其删除:


az role definition delete --name "$imageRoleDefName"
```azurecli
az role assignment delete \
    --assignee $imgBuilderCliId \
    --role "$imageRoleDefName" \
    --scope /subscriptions/$subscriptionID/resourceGroups/$imageResourceGroup
az identity delete --ids $imgBuilderId
az resource delete \
    --resource-group $imageResourceGroup \
    --resource-type Microsoft.VirtualMachineImages/imageTemplates \
    -n helloImageTemplateMsi01
az group delete -n $imageResourceGroup
az group delete -n $strResourceGroup

后续步骤

如果使用 VM 映像生成器时遇到任何问题,请参阅 Azure VM 映像生成器疑难解答