Расширение Custom Script в ОС Windows

Расширение пользовательских сценариев скачивает и выполняет сценарии на виртуальных машинах Azure. Это расширение можно использовать для настройки после развертывания, установки программного обеспечения и других задач настройки или управления. Сценарии можно скачать из службы хранилища Azure или GitHub или передать на портал Azure во время выполнения расширения.

Расширение пользовательских сценариев интегрируется с шаблонами Azure Resource Manager. Его также можно запустить с помощью Azure CLI, PowerShell, портала Azure или виртуальных машин Azure REST API.

В этой статье показано, как применять пользовательское расширение сценариев с помощью модуля Azure PowerShell и шаблонов Azure Resource Manager. В ней статье также показаны шаги по устранению неполадок в системах Windows.

Предварительные требования

Примечание

Не используйте расширение пользовательских сценариев для выполнения команды Update-AzVM на той же виртуальной машине, которая использовалась для параметра, так как команда выполнится через определенный период времени.

Операционная система

Расширение пользовательских скриптов для Windows запустится в следующих поддерживаемых операционных системах:

  • Windows Server 2008 R2
  • Windows Server 2012
  • Windows Server 2012 R2
  • Windows 10
  • Windows Server 2016
  • Windows Server 2016 Core
  • Windows Server 2019
  • Windows Server 2019 Core
  • Windows 11

Расположение скрипта

Вы можете настроить расширение, чтобы получить доступ к Хранилищу BLOB-объектов Azure с помощью учетных данных службы Хранилища BLOB-объектов Azure. Скрипт может находиться в любом расположении при условии, что виртуальная машина может осуществлять маршрутизацию в конечную точку (например, GitHub или внутренний файловый сервер).

Подключение к Интернету

Чтобы загрузить скрипт из внешнего источника, например из GitHub или службы хранилища Azure, нужно открыть дополнительный брандмауэр или порты группы безопасности сети (NSG). К примеру, если скрипт находится в службе хранилища Azure, можете предоставить к нему доступ с помощью тегов службы для хранилища группы безопасности сети Azure.

Расширение пользовательских скриптов не может обходить проверку сертификатов, поэтому при загрузке из защищенного расположения, например, с самозаверяющим сертификатом, могут возникать такие ошибки, как "Удаленный сертификат недействителен согласно результатам проверки подлинности". Убедитесь, что сертификат правильно установлен в хранилище доверенных корневых центров сертификации на виртуальной машине.

Если ваш скрипт находится на локальном сервере, вам может потребоваться открыть дополнительный брандмауэр или порты группы безопасности сети.

Советы и рекомендации

  • Наибольшая частота сбоев для этого расширения обусловлена синтаксическими ошибками в скрипте. Убедитесь, что скрипт запускается без ошибок. Добавьте дополнительные возможности ведения журнала в скрипт, чтобы упростить поиск ошибок.
  • Пишите идемпотентные скрипты, чтобы их повторные запуски не приводили к изменениям системы.
  • Выполняемые скрипты не должны запрашивать ввод данных пользователем.
  • Выполнение скриптов разрешено в течение 90 минут. Выполняющиеся дольше скрипты приведут к сбою подготовки расширения.
  • Не помещайте перезагрузки в скрипт. Это действие вызовет проблемы с другими устанавливаемыми расширениями, и расширение не будет работать после перезагрузки.
  • Если у вас есть скрипт, приводящий к перезагрузке перед установкой приложений и запуском скриптов, назначьте время перезагрузки с помощью запланированного задания Windows или таких инструментов, как расширения DSC, Chef или Puppet.
  • Не запускайте скрипт, который приводит к остановке или обновлению агента виртуальных машин. Это может привести к тому, что расширение останется в состоянии перехода, из-за чего истечет время ожидания.
  • Расширение будет выполнять скрипт только один раз. Если вы хотите выполнять скрипт при каждой загрузке, используйте расширение, чтобы создать запланированную задачу Windows.
  • Чтобы запланировать время выполнения скрипта, создайте запланированную задачу Windows с помощью расширения.
  • Во время выполнения скрипта на портале Azure или в CLI вы увидите только "переходное" состояние расширения. Если требуются более частые обновления состояния выполняющегося скрипта, следует создать собственное решение.
  • Расширение пользовательских скриптов не предусматривает собственную поддержку прокси-серверов. Но вы можете использовать средство передачи файлов, которое поддерживает прокси-серверы в скрипте, например Invoke-WebRequest.
  • Следует учитывать настраиваемые расположения каталогов, которые могут использоваться вашими скриптами или командами. Для решения этой ситуации необходимо иметь в распоряжении логику.
  • Расширение пользовательских скриптов будет выполняться под учетной записью LocalSystem.
  • Если вы планируете использовать свойства storageAccountName и storageAccountKey, эти свойства должны быть выровнены в protectedSettings.

Схема расширения

В конфигурации расширения пользовательских сценариев указываются такие параметры, как расположение сценария и команда для его выполнения. Эту конфигурацию можно хранить в файлах конфигурации, указать в командной строке или в шаблоне Azure Resource Manager.

Конфиденциальные данные можно хранить в зашифрованном виде в защищенной конфигурации, которая расшифровывается только внутри виртуальной машины. Защищенная конфигурация удобна, если команда выполнения содержит секреты, такие как пароль или ссылка на подписанный URL-адрес (SAS) файла. Ниже приведен пример:

{
    "apiVersion": "2018-06-01",
    "type": "Microsoft.Compute/virtualMachines/extensions",
    "name": "virtualMachineName/config-app",
    "location": "[resourceGroup().location]",
    "dependsOn": [
        "[concat('Microsoft.Compute/virtualMachines/', variables('vmName'),copyindex())]",
        "[variables('musicstoresqlName')]"
    ],
    "tags": {
        "displayName": "config-app"
    },
    "properties": {
        "publisher": "Microsoft.Compute",
        "type": "CustomScriptExtension",
        "typeHandlerVersion": "1.10",
        "autoUpgradeMinorVersion": true,
        "settings": {
            "timestamp":123456789
        },
        "protectedSettings": {
            "commandToExecute": "myExecutionCommand",
            "storageAccountName": "myStorageAccountName",
            "storageAccountKey": "myStorageAccountKey",
            "managedIdentity" : {},
            "fileUris": [
                "script location"
            ]
        }
    }
}

Примечание

Свойство managedIdentity не должно применяться вместе со свойствами storageAccountName или storageAccountKey.

На виртуальной машине может быть установлена только одна версия расширения. Если дважды указать пользовательский скрипт в одном и том же шаблоне Azure Resource Manager для одной и той же виртуальной машины, произойдет сбой.

Эту схему можно использовать в ресурсе виртуальной машины или в качестве автономного ресурса. Имя ресурса должно быть в формате virtualMachineName/extensionName, если это расширение используется в качестве автономного ресурса в шаблоне Azure Resource Manager.

Значения свойств

Имя Значение или пример Тип данных
apiVersion 2015-06-15 Дата
publisher Microsoft.Compute строка
type CustomScriptExtension строка
typeHandlerVersion 1.10 INT
fileUris https://raw.githubusercontent.com/Microsoft/dotnet-core-sample-templates/master/dotnet-core-music-windows/scripts/configure-music-app.ps1 array
timestamp 123456789 32-разрядное целое число
commandToExecute powershell -ExecutionPolicy Unrestricted -File configure-music-app.ps1 строка
storageAccountName examplestorageacct строка
storageAccountKey TmJK/1N3AbAZ3q/+hOXoi/l73zOqsaxXDhqa9Y83/v5UpXQp2DQIBuv2Tifp60cE/OaHsJZmQZ7teQfczQj8hg== строка
managedIdentity { }, { "clientId": "31b403aa-c364-4240-a7ff-d85fb6cd7232" } или { "objectId": "12dd289c-0583-46e5-b9b4-115d5c19ef4b" } Объект JSON

Примечание

В именах свойств учитывается регистр. Чтобы избежать проблем с развертыванием, используйте имена, как показано ниже.

Сведения о значениях свойств

Свойство Необязательное или обязательное Сведения
fileUris Необязательно URL-адреса для загрузки файлов. Если URL-адреса являются конфиденциальными (например, содержат ключи), это поле должно быть указано в protectedSettings.
commandToExecute Обязательно Точка входа для выполнения скрипта. Если команда содержит секретные данные, например пароли, или если универсальные коды ресурса (URI) для файлов являются конфиденциальным, используйте это свойство.
timestamp Необязательно Меняйте это значение, только чтобы вызвать перезапуск скрипта. Допускается любое целое значение, если оно отличается от предыдущего значения.
storageAccountName Необязательно Название учетной записи хранения. Если указаны учетные данные хранилища, все значения fileUris должны иметь формат URL-адресов для BLOB-объектов Azure.
storageAccountKey Необязательно Ключ доступа учетной записи хранения.
managedIdentity Необязательно Управляемое удостоверение для скачивания файлов:

clientId (необязательный параметр, строка): идентификатор клиента для управляемого удостоверения.

objectId (необязательный параметр, строка): идентификатор объекта управляемого удостоверения.

Приведенные ниже значения можно задать в открытых или защищенных параметрах. Расширение отклонит любую конфигурацию, в которой эти значения заданы в открытых или защищенных параметрах.

  • commandToExecute
  • fileUris

Открытые параметры могут быть полезны для отладки, но мы рекомендуем использовать защищенные параметры.

Открытые параметры отправляются в виде открытого текста на виртуальную машину, где будет выполняться скрипт. Защищенные параметры шифруются с помощью ключа, который известен только Azure и виртуальной машине. Параметры сохраняются на виртуальной машине по мере их отправки. Это значит, что если параметры были зашифрованы, они сохранятся в таком виде и на виртуальной машине. Сертификат, используемый для расшифровки зашифрованных значений, хранится на виртуальной машине. Сертификат также используется для расшифровки параметров (при необходимости) в среде выполнения.

Свойство: managedIdentity

Примечание

Это свойство должно быть задано только в защищенных параметрах.

Расширение пользовательских скриптов (версии 1.10 и более поздних) поддерживает управляемые удостоверения для скачивания файлов с URL-адресов, указанных в параметре fileUris. Это предоставляет расширению пользовательских скриптов доступ к частным BLOB-объектам службы хранилища Azure или контейнерам без необходимости вводить пароли, такие как маркеры SAS или ключи учетной записи хранения.

Для использования этой функции пользователь должен добавить назначенное системой или пользователем удостоверение в виртуальную машину или набор ее настроек, где должно выполняться расширение пользовательских скриптов. Затем пользователь должен предоставить управляемому удостоверению доступ к контейнеру службы хранилища Azure или его BLOB-объекту.

Чтобы использовать назначенное системой удостоверение на целевой виртуальной машине или ее масштабируемом наборе, задайте для managedidentity пустой объект JSON.

Пример.

{
  "fileUris": ["https://mystorage.blob.core.windows.net/privatecontainer/script1.ps1"],
  "commandToExecute": "powershell.exe script1.ps1",
  "managedIdentity" : {}
}

Чтобы использовать назначенное пользователем удостоверение на целевой виртуальной машине или ее масштабируемом наборе, настройте managedidentity с помощью идентификатора клиента или идентификатора объекта управляемого удостоверения.

Примеры:

{
  "fileUris": ["https://mystorage.blob.core.windows.net/privatecontainer/script1.ps1"],
  "commandToExecute": "powershell.exe script1.ps1",
  "managedIdentity" : { "clientId": "31b403aa-c364-4240-a7ff-d85fb6cd7232" }
}
{
  "fileUris": ["https://mystorage.blob.core.windows.net/privatecontainer/script1.ps1"],
  "commandToExecute": "powershell.exe script1.ps1",
  "managedIdentity" : { "objectId": "12dd289c-0583-46e5-b9b4-115d5c19ef4b" }
}

Примечание

Свойство managedIdentity не должно применяться вместе со свойствами storageAccountName или storageAccountKey.

Развертывание шаблона

Вы можете развернуть расширения виртуальной машины Azure с помощью шаблонов Azure Resource Manager. Схема JSON, подробно описанная в предыдущем разделе, может использоваться в шаблоне Azure Resource Manager для запуска расширения пользовательского скрипта во время развертывания шаблона. Приведенные ниже примеры демонстрируют использование расширения пользовательских сценариев:

Развертывание с помощью PowerShell

Вы можете использовать команду Set-AzVMCustomScriptExtension, чтобы добавить расширение пользовательских сценариев в существующую виртуальную машину. Дополнительные сведения см. в статье о Set-AzVMCustomScriptExtension.

Set-AzVMCustomScriptExtension -ResourceGroupName <resourceGroupName> `
    -VMName <vmName> `
    -Location myLocation `
    -FileUri <fileUrl> `
    -Run 'myScript.ps1' `
    -Name DemoScriptExtension

Дополнительные примеры

Использование нескольких скриптов

В этом примере три скрипта используются для построения сервера. Свойство commandToExecute вызывает первый скрипт. Также есть параметры, с помощью которых вызываются другие. Например, можно создать главный сценарий, который управляет выполнением с правильной обработкой ошибок, ведением журнала и управлением состоянием. Скрипты загружаются на локальный компьютер для выполнения.

Например, в 1_Add_Tools.ps1можно вызвать 2_Add_Features.ps1, добавив .\2_Add_Features.ps1 в скрипт. Этот процесс можно повторить для других скриптов, определенных в $settings.

$fileUri = @("https://xxxxxxx.blob.core.windows.net/buildServer1/1_Add_Tools.ps1",
"https://xxxxxxx.blob.core.windows.net/buildServer1/2_Add_Features.ps1",
"https://xxxxxxx.blob.core.windows.net/buildServer1/3_CompleteInstall.ps1")

$settings = @{"fileUris" = $fileUri};

$storageAcctName = "xxxxxxx"
$storageKey = "1234ABCD"
$protectedSettings = @{"storageAccountName" = $storageAcctName; "storageAccountKey" = $storageKey; "commandToExecute" = "powershell -ExecutionPolicy Unrestricted -File 1_Add_Tools.ps1"};

#run command
Set-AzVMExtension -ResourceGroupName <resourceGroupName> `
    -Location <locationName> `
    -VMName <vmName> `
    -Name "buildserver1" `
    -Publisher "Microsoft.Compute" `
    -ExtensionType "CustomScriptExtension" `
    -TypeHandlerVersion "1.10" `
    -Settings $settings `
    -ProtectedSettings $protectedSettings;

Запуск скриптов из локальной общей папки

В этом примере может потребоваться использовать локальный сервер SMB в качестве расположения скрипта. Тогда вам не нужно указывать другие параметры, кроме commandToExecute.

$protectedSettings = @{"commandToExecute" = "powershell -ExecutionPolicy Unrestricted -File \\filesvr\build\serverUpdate1.ps1"};

Set-AzVMExtension -ResourceGroupName <resourceGroupName> `
    -Location <locationName> `
    -VMName <vmName> `
    -Name "serverUpdate"
    -Publisher "Microsoft.Compute" `
    -ExtensionType "CustomScriptExtension" `
    -TypeHandlerVersion "1.10" `
    -ProtectedSettings $protectedSettings

Запуск пользовательского скрипта более одного раза с помощью интерфейса командной строки

Обработчик расширения пользовательского скрипта не позволит выполнить сценарий, если были переданы одни и те же параметры. Такое поведение предотвращает случайный перезапуск, который может привести к непредвиденному поведению, если скрипт не является идемпотентным. Чтобы узнать, не заблокировал ли обработчик перезапуск, откройте файл C:\WindowsAzure\Logs\Plugins\Microsoft.Compute.CustomScriptExtension<HandlerVersion>\CustomScriptHandler.log и выполните поиск предупреждения, похожего на следующее:

Current sequence number, <SequenceNumber>, is not greater than the sequence number of the most recently executed configuration. Exiting...

Чтобы выполнить расширение пользовательского скрипта более одного раза, должны соблюдаться следующие условия:

  • Параметр Name расширения совпадает с указанным при предыдущем развертывании расширения.
  • Конфигурация обновлена. Вы можете добавить в команду динамическое свойство, например метку времени. Если обработчик обнаруживает изменение в параметрах конфигурации, оно будет рассматриваться как явное желание перезапустить скрипт.

Кроме того, можно задать для свойства ForceUpdateTag значение true.

Использование Invoke-WebRequest

Если вы используете Invoke-WebRequest в скрипте, необходимо указать параметр -UseBasicParsing. Если параметр не указан, при проверке подробного состояния будет выводится следующее сообщение об ошибке:

The response content cannot be parsed because the Internet Explorer engine is not available, or Internet Explorer's first-launch configuration is not complete. Specify the UseBasicParsing parameter and try again.

Масштабируемые наборы виртуальных машин

Если вы развертываете расширение пользовательских скриптов с портала Azure, вы не можете повлиять на срок действия маркера SAS для доступа к скрипту в вашей учетной записи хранения. В результате начальное развертывание будет работать, но после истечения срока действия маркера SAS учетной записи хранения все последующие операции масштабирования будут неудачными, так как расширение пользовательских скриптов больше не сможет получить доступ к учетной записи хранения.

Мы рекомендуем использовать PowerShell, Azure CLI или шаблон Azure Resource Manager при развертывании расширения пользовательских скриптов в масштабируемом наборе виртуальных машин. Таким образом, вы можете использовать управляемое удостоверение или иметь возможность непосредственного управления сроком действия маркера SAS для доступа к скрипту в вашей учетной записи хранения столько, сколько потребуется.

Устранение неполадок и поддержка

Данные о состоянии развертывания расширения можно получить на портале Azure, а также с помощью модуля Azure PowerShell. Чтобы просмотреть состояние развертывания расширений для виртуальной машины, выполните следующую команду:

Get-AzVMExtension -ResourceGroupName <resourceGroupName> -VMName <vmName> -Name myExtensionName

Выходные данные расширения регистрируются в файле, расположенном в следующей папке на целевой виртуальной машине:

C:\WindowsAzure\Logs\Plugins\Microsoft.Compute.CustomScriptExtension

Указанные файлы скачиваются в указанную ниже папку на целевой виртуальной машине:

C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.*\Downloads\<n>

В предыдущем пути <n> — это десятичное целое число, которое может меняться между выполнениями расширения. Значение 1.* соответствует фактическому текущему значению typeHandlerVersion расширения. Например, фактическим каталогом может быть C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.8\Downloads\2.

При выполнении команды commandToExecute расширение устанавливает этот каталог (например, ...\Downloads\2) в качестве текущего рабочего каталога. Этот процесс позволяет использовать относительные пути для поиска файлов, скачанных с помощью свойства fileURIs. Ниже приведены примеры скачанных файлов:

URI в fileUris Относительное расположение скачанных файлов Абсолютное расположение скачанных файлов 1
https://someAcct.blob.core.windows.net/aContainer/scripts/myscript.ps1 ./scripts/myscript.ps1 C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.8\Downloads\2\scripts\myscript.ps1
https://someAcct.blob.core.windows.net/aContainer/topLevel.ps1 ./topLevel.ps1 C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.8\Downloads\2\topLevel.ps1

1Абсолютные пути каталогов изменяются в течение времени существования виртуальной машины, но не в рамках одного выполнения расширения пользовательских скриптов.

Так как со временем абсолютный путь для скачивания может измениться, в строке commandToExecute лучше указывать относительные пути к сценариям или файлам, когда это возможно. Пример:

"commandToExecute": "powershell.exe . . . -File \"./scripts/myscript.ps1\""

Для файлов, скачанных с помощью списка свойств fileUris, сохраняются данные пути после первого сегмента универсального кода ресурса (URI). Как показано в таблице выше, скачанные файлы распределяются по подкаталогам в соответствии со структурой значений fileUris.

Поддержка

Если вам нужна помощь по любой части этой статьи, обратитесь к поддержке сообщества Azure.

Можно также зарегистрировать обращение в службу поддержки Azure. Перейдите на сайт поддержки Azure и щелкните Получить поддержку. Дополнительные сведения об использовании службы поддержки Azure см. в статье Часто задаваемые вопросы о поддержке Microsoft Azure.