Add Custom Script Extension on multiple Azure VMs

custom script extension

Hi Scripters! Today want to share with you my script to add custom script extension on multiple Azure VMs.

Recently I was working on a project where one of the requirement was installation of FTP service on 20+ virtual machines already created in Azure. I’ve created a script for FTP service installation on single server, but how to apply it automatically to multiple of them. Decided to add custom script extension for all of them and simply do installation this way.

Probably now you will ask ok, you used custom script extension but how to configure them automatically on all of them. My script is an answer here 🙂

How it works?

First of all you must have a script which you want to run on all of yours Azure virtual machines. In my case it was script for FTP installation on IIS – but for you it can be for example on creation of local user of group on machine. Once you have a script you should copy it as a blob to storage account. Once it is done you should provide proper input parameters to script, limit the scope of virtual machines to which it should apply (line 12 of a script) and this is the way to add custom script extension to multiple machines on Azure.

IMPORTANT:

You should keep in mind that script will remove custom script extension if it’s already exist on machine. It will not destroy changes applied by this script, but only extension itself. The reason of that is the Azure VMs do not support more than one same type of extension installed.

Requirements:

  • Az module installed
  • Proper access to subscription where you have storage account and virtual machines – best Contributor

Script:

param(
    $TenantId,
    $defaultSubscriptionId,
    $customScriptExtensionName,
    $scriptName,
    $storageAccountName,
    $storageAccountContainer,
    $storageAccountResourceGroup,
    $storageSubscriptionId
)

$VMs = Get-AzVM ## Here you should apply filter if you want to limit installation to specific VMs

Select-AzSubscription -SubscriptionId $storageSubscriptionId

$fileUri = @("https://$storageAccountName.blob.core.windows.net/$storageAccountContainer/$scriptName")
$settings = @{"fileUris" = $fileUri};
$storageKey = (Get-AzStorageAccountKey -Name $storageAccountName -ResourceGroupName $storageAccountResourceGroup)[0].Value
$protectedSettings = @{"storageAccountName" = $storageAccounttName; "storageAccountKey" = $storageKey; "commandToExecute" = "powershell -ExecutionPolicy Unrestricted -File $scriptName"};

Select-AzSubscription -SubscriptionId $defaultSubscriptionId

foreach($vm in $VMs){
    Write-Output "Starting VM $($vm.Name)"
    Start-AzVm -ResourceGroupName "$($vm.ResourceGroupName)" -Name "$($vm.Name)"
    Write-OUtput "Working on vm $($vm.Name)"
    $extensions = (Get-AzVm -ResourceGroupName "$($vm.ResourceGroupName)" -Name "$($vm.Name)").Extensions
    foreach($ext in $extensions)
    {
        if($ext.VirtualMachineExtensionType -eq "CustomScriptExtension"){
            Write-Output "Removing CustomScriptExtension with name $($ext.Name) from vm $($vm.Name)"
            Remove-AzVMExtension -ResourceGroupName "$($vm.ResourceGroupName)" -VMName "$($vm.Name)" -Name $ext.Name -Force
            Write-Output "Removed CustomScriptExtension with name $($ext.Name) from vm $($vm.Name)"
        }
    }
    Write-Output "$customScriptExtenstionName installation on VM $($vm.Name)"

    Set-AzVMExtension -ResourceGroupName "$($vm.ResourceGroupName)" `
        -Location "$($vm.Location)" `
        -VMName "$($vm.Name)" `
        -Name "$customScriptExtenstionName" `
        -Publisher "Microsoft.Compute" `
        -ExtensionType "CustomScriptExtension" `
        -TypeHandlerVersion "1.10" `    `
        -Settings $settings    `
        -ProtectedSettings $protectedSettings

    Write-Output "---------------------------"
}

Hope that it will be usefull for some of you 😉

Enjoy!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.