Automate Linux VM Customization Tasks Using CustomScript Extension

virtual machine

You might already be familiar with the CustomScript extension for Windows VM in the Windows Extension Blog, the good news is that, the extension is also available for Linux VM now.

Cloud-init was introduced in a previous blog as well, which enables you to inject a script or metadata into an Azure Linux VM during provision time. CustomScript extension provides even more power for customizing your VM, it can run your scripts during or after provision; it can also run on any Azure supported Linux VM.

 

What CustomScript can do for you?

After creating the Linux VM on Azure, you may need to deploy your workload (web server, database, etc.) on the VM, ideally this can be done via a serial of scripts.

  • CustomScript extension can automatically download and execute these scripts for you, from the location you’ve specified, with parameters you’ve entered.
  • CustomScript extension supports scripts written in any scripting language for Linux (Python, Linux shell scripts etc.), as long as the correspondent script interpreter is installed on your VM.
  • You can install and configure CustomScript Extension during the VM provision or any time after the provision.
  • You can deploy the CustomScript Extension using Azure PowerShell Cmdlets. Deployment through xPlat scripts and Azure Portal will be also supported in next few weeks, stay tuned for more details. 

 

Pre-requisites

  • Microsoft Azure Linux Agent version 2.0.5 or later. Note most Azure VM Linux gallery images included version 2.0.5. You can run waagent -version to confirm the version installed in the VM. If the VM is running a version earlier than 2.0.5 you can follow these instructions to update it.
  • Azure PowerShell. Note Cross-Platform CLI support for extensions is expected to be available in a few weeks.
  • The scripts you want to run, make sure it is uploaded to Azure Storage blob or Github location.

 

Deploy the CustomScript Extension

You can deploy the extension through Azure PowerShell,  xPlat scripts or Azure portal. For this article, we will focus on deploy the extension through Azure PowerShell.  For reference of APIs in the scripts, check here.

First, make sure you have already installed Azure PowerShell. Depending on where your scripts are located, there are two options to deploy the extension and run your scripts.  

Running the script stored in Azure storage blob

  1. User writes and uploads the script to an Azure blob location.
  2. He adds the extension to his VM either during the provision or post the provision.
  3. He enters the Azure blob location of the script and the optional parameters.
  4. Inside the VM the extension downloads the script.
  5. The extension launches the script with user specified parameters.
#Identify the VM, enter the Azure storage account name and key
$vm = Get-AzureVM -ServiceName ‘MyServiceName’ -Name ‘MyVMName’
$PrivateConfiguration = '{"storageAccountName": "MyAccount","storageAccountKey":"Mykey"}' 
#Specify the Location of the script from Azure blob, and command to execute
$PublicConfiguration = '{"fileUris":["http://MyAccount.blob.core.windows.net/vhds/MyShellScript.sh"], "commandToExecute": "sh MyShellScript.sh" }' 

#Deploy the extension to the VM, pick up the latest version of the extension
$ExtensionName = 'CustomScriptForLinux'  
$Publisher = 'Microsoft.OSTCExtensions'  
$Version = '1.1' 
Set-AzureVMExtension -ExtensionName $ExtensionName -VM  $vm -Publisher $Publisher -Version $Version -PrivateConfiguration $PrivateConfiguration -PublicConfiguration $PublicConfiguration  | Update-AzureVM

 

Running scripts stored in GitHub

  1. The user writes the scripts and uploads them to GitHub.
  2. He adds the extension to his VM either during provision or post provision.
  3. He enters the GitHub location of the script and optional parameters.
  4. Inside the VM the extension downloads the scripts.
  5. The extension launches the script with user specified parameters.
#Identify the VM
$vm = Get-AzureVM -ServiceName ‘MyServiceName’ -Name ‘MyVMName’
#Specify the Location of the script and the command to execute
$PublicConfiguration = '{"fileUris":["https://github.com/MyProject/Archive/MyPythonScript.py"], "commandToExecute": "python MyPythonScript.py" }' 

#Deploy the extension to the VM, pick up the latest version of the extension
$ExtensionName = 'CustomScriptForLinux'  
$Publisher = 'Microsoft.OSTCExtensions'  
$Version = '1.1' 
Set-AzureVMExtension -ExtensionName $ExtensionName -VM  $vm -Publisher $Publisher -Version $Version -PublicConfiguration $PublicConfiguration  | Update-AzureVM

 

Query the Result

  • The CustomScript extension will kick off user’s scripts right after the deployment of the extension.
  • The execution result can be retrieved via Azure PowerShell Cmdlet Get-AzureVM or Get-Deployment. You can also check the status through xPlat scripts and Azure portal (coming soon).
  • You can find the CustomScript extension’s log file at /var/log/azure/Microsoft.OSTCExtensions. CustomScriptForLinux/1.0/extension.log.  Note the standard output of the user’s script will also be captured in this log file.

 

Additional notes

  • If you have multiple scripts, you can author an entry point script that calls the dependent scripts, then upload the entry point script, dependent scripts and any other dependent binaries to the script location(Azure storage blob or GitHub).
  • The extension is designed for one off tasks after VM creation. If the extension is called the second time with the same configuration, it will not execute the script you specified. However if you do need to run the CustomScript extension multiple times, you can run it with different configurations. For example:
  1. Change the name of your script.
  2. Use following code to add a timestamp as the [PublicConfiguration] parameter:
    #Generate the current timestamp, add to the configuration, this ensures the configuration is different every time the CustomScript extension runs
    $TimeStamp = (Get-Date).Ticks
    $PublicConfiguration = '{"fileUris":[“MyAccount.blob.core.windows.net/vhds/MyShellScript.sh”], "commandToExecute": "sh MyShellScript.sh", “timestamp”: “' + $TimeStamp + '“}

 

Known issue

When you run the PowerShell command “Set-AzureVMExtension” on Linux VM, you may hit following error: “Provision Guest Agent must be enabled on the VM object before setting IaaS VM Access Extension”.

Root Cause: when you create the image via portal, the value of guest agent on the VM is not always  set to “True”. If your VM is created using PowerShell, you will not see this issue.

Resolution: Add the following PowerShell command to set the ProvisionGuestAgent to “True”;

$vm = Get-AzureVM -ServiceName ‘MyServiceName’ -Name ‘MyVMName’

$vm.GetInstance().ProvisionGuestAgent = $true