Набор масштабов виртуальной машины Azure: возможно ли передать сценарий / настройки начальной загрузки, не загружая их с URL? - PullRequest
0 голосов
/ 09 февраля 2019

Я вижу, что с помощью Custom Script Extension можно загружать новые виртуальные машины (в Scale Set).Для доступа к сценарию необходимы URI хранилища Azure и учетные данные.Этот подход не работает для меня, потому что (внутренняя политика) не позволяет передавать учетные данные хранилища.

Мой VMSS назначил идентификатор службы, последний зарегистрирован в KeyVault.Таким образом, довольно просто получить учетные данные непосредственно на коробке.Но для этого мне нужен хотя бы небольшой скрипт начальной загрузки =)

Я нашел один хакерский способ добиться этого с помощью расширения пользовательских скриптов:

$bootstrapScriptPath = Join-Path -Path $PSScriptRoot -ChildPath "bootstrap.ps1"
$bootstrapScriptBlock = get-command $bootstrapScriptPath | Select -ExpandProperty ScriptBlock
$installScriptBase64 = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($bootstrapScriptBlock.ToString()))

"commandToExecute": "[concat('powershell -ExecutionPolicy Unrestricted -EncodedCommand ', parameters('installScriptBase64'))]"

Но мне интересно, есть ли лучшие решения.

По сути, мне нужно что-то, что обеспечивает Cloud Service - возможность загружать полезную нагрузку и настройки конфигурации.

РЕШЕНИЕ

(обратите внимание, это для Windows VM. Для Linux VM есть более простой способ - благодаря @sendmarsh)

Пожалуйста, смотритениже для фактической реализации (обратите внимание, я пометил в качестве ответа сообщение от @ 4c74356b41, который предложил эту идею).

Ответы [ 3 ]

0 голосов
/ 11 февраля 2019

Вы можете избежать использования расширения сценария с пользовательскими данными и облачным инициализацией - если это виртуальная машина Linux.Если вы не используете расширение скрипта, вы сэкономите и пару минут от времени развертывания.

Здесь есть пример для виртуальной машины: https://msftstack.wordpress.com/2018/11/26/speeding-up-azure-resource-manager-templates-using-cloud-init/ - вы можете использовать тот же метод для набора масштабов.

0 голосов
/ 22 февраля 2019

Вот где я остановился:

  1. Передача Bootstrap.ps1 в качестве пользовательских данных
  2. Выполнение сложной команды через расширение Custom Script - оно декодирует CustomData.bin, копирует как Bootstrap.ps1 и вызывает его с параметрами
  3. внешние файлы не загружаются
  4. Bootstrap.ps1 регистрирует планировщик задач для повторного запуска, получает токен из службы метаданных для назначенного пользователем управляемого идентификатора, переходит в хранилище ключейчтобы получить учетные данные для загрузки основной полезной нагрузки, загрузки, распаковки и т. д.

Ниже приведены фрагменты о том, как заставить работать № 1 и № 2.

Пример Bootstrap.ps1:

param(
 [Parameter(Mandatory=$True)]
 [string]
 $param1,

 [Parameter(Mandatory=$True)]
 [string]
 $param2
)

$ErrorActionPreference = "Stop"

Write-Output("Running Bootstrap.ps1 with the following parameters:");
Write-Output("`$param1 = `"$param1`";");
Write-Output("`$param2 = `"$param2`";");

Передать его как CustomData:

# Encoding bootstrap script
$bootstrapScriptPath = (Join-Path -Path "." -ChildPath "Node/Bootstrap.ps1");
$bootstrapScriptBlock = get-command $bootstrapScriptPath | Select -ExpandProperty ScriptBlock;
$encodedScript = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($bootstrapScriptBlock.ToString()));
...
| Set-AzVMOperatingSystem -CustomData $encodedScript

Командная строка:

$commandLine = "powershell -ExecutionPolicy Unrestricted -Command `"" ` + # Running powershell in cmd
                    "`$ErrorActionPreference = 'Stop';" ` + # Upon any error fail the provisioning of the extension
                    "`$content = [IO.File]::ReadAllText('C:\AzureData\CustomData.bin');" + ` # Read Base64-encoded file
                    "`$bytes = [System.Convert]::FromBase64String(`$content);" + ` # Convert to bytes
                    "`$script = [System.Text.Encoding]::Unicode.GetString(`$bytes);" + ` # Decode to string
                    "[IO.File]::WriteAllText('C:\AzureData\Bootstrap.ps1', `$script);" + ` # Save as Bootstrap.ps1
                    "C:\AzureData\Bootstrap.ps1 " + ` # Run a script
                    "-param1 'test' -param2 'test' " + ` # Pass needed parameters
                    " | Out-File -PSPath 'C:\AzureData\output.log';" ` +
                "`"";

Расширение пользовательского сценария:

$extensionSettings = @{ "fileUris" = ""; "commandToExecute" = ""};
$extensionProtectedSettings = @{ "commandToExecute" = "$commandLine" };
$result = Set-AzVMExtension -VMName "$($vm.Name)" -Location $resourceGroupLocation -Publisher "Microsoft.Compute" -Type "CustomScriptExtension" `
                            -TypeHandlerVersion "1.9" -Settings $extensionSettings -ProtectedSettings $extensionProtectedSettings `
                            -Name "Bootstrap" -ResourceGroupName $resourceGroup.ResourceGroupName;
0 голосов
/ 09 февраля 2019

Прежде всего, я не вижу ничего хакерского, это правильный подход.

Другой способ передачи данных - использование свойства custom data .Он будет доступен в виде файла внутри vm, я не помню, закодирован ли он в base64, но вы можете быстро выяснить это после предоставления.

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

В любом случае вам нужно передать свой сценарий в vm и вызвать его с помощью расширения сценария.Вы можете использовать пользовательское изображение со скриптом внутри него.или вы можете иметь скрипт в общедоступном URL-адресе, чтобы vm всегда мог его извлечь и выполнить (в этом случае вам необходим MSI для обработки аутентификации).

Еще одна вещь, которую вы можете сделать, - pullсертификаты от KV непосредственно внутри ВМ во время.снабжение.

...