Windows용 사용자 지정 스크립트 확장

사용자 지정 스크립트 확장은 Azure VM(가상 머신)에서 스크립트를 다운로드하고 실행합니다. 이 확장은 배포 후 구성, 소프트웨어 설치 또는 기타 구성 또는 관리 작업에 사용합니다. Azure Storage 또는 GitHub에서 스크립트를 다운로드하거나 확장 런타임 시 Azure Portal에 제공할 수 있습니다.

사용자 지정 스크립트 확장은 Azure Resource Manager 템플릿과 통합됩니다. Azure CLI, Azure PowerShell, Azure Portal 또는 Azure Virtual Machines REST API를 사용하여 실행할 수도 있습니다.

이 문서에서는 Azure PowerShell 모듈 및 Azure Resource Manager 템플릿을 사용하여 사용자 지정 스크립트 확장을 사용하는 방법을 자세히 설명합니다. 또한 Windows 시스템에 대한 문제 해결 단계를 제공합니다.

필수 조건

참고 항목

사용자 지정 스크립트 확장을 사용하여 매개 변수와 동일한 VM으로 Update-AzVM을 실행하지 마세요. 대기 시간이 길어집니다.

지원되는 Windows 운영 체제

Windows OS x64
Windows 10 지원됨
Windows 11 지원됨
Windows Server 2008 SP2 지원됨
Windows Server 2008 R2 지원됨
Windows Server 2012 지원됨
Windows Server 2012 R2 지원됨
Windows Server 2016 지원됨
Windows Server 2016 Core 지원됨
Windows Server 2019 지원됨
Windows Server 2019 Core 지원됨
Windows Server 2022 지원됨
Windows Server 2022 Core 지원됨

스크립트 위치

Azure Blob Storage 자격 증명을 사용하도록 확장을 설정하여 Azure Blob Storage에 액세스할 수 있습니다. VM에서 해당 엔드포인트(예: GitHub 또는 내부 파일 서버)로 라우팅할 수 있는 경우 스크립트 위치는 어디에나 있을 수 있습니다.

인터넷 연결

GitHub 또는 Azure Storage와 같이 외부에서 스크립트를 다운로드하려면 다른 방화벽 또는 NSG(네트워크 보안 그룹) 포트를 열어야 합니다. 예를 들어 스크립트가 Azure Storage에 있는 경우 Storage에 대한 Azure NSG 서비스 태그를 사용하여 액세스를 허용할 수 있습니다.

사용자 지정 스크립트 확장에는 인증서 유효성 검사를 우회할 수 있는 방법이 없습니다. 예를 들어 자체 서명된 인증서를 사용해 안전한 위치에서 다운로드하는 경우 유효성 검사 절차에 따르면 원격 인증서가 잘못되었습니다.와 같은 오류가 발생할 수 있습니다. 인증서가 VM의 신뢰할 수 있는 루트 인증 기관 저장소에 올바르게 설치되어 있는지 확인하세요.

스크립트가 로컬 서버에 있는 경우 다른 방화벽 또는 NSG 포트를 열어야 할 수도 있습니다.

  • 출력은 마지막 4096바이트로 제한됩니다.
  • 문자를 올바르게 이스케이프하면 문자열을 올바르게 구문 분석할 수 있습니다. 예를 들어 파일 경로를 처리할 때 단일 리터럴 백슬래시를 이스케이프하려면 항상 두 개의 백슬래시가 필요합니다. 샘플: {"commandToExecute": "C:\\Windows\\System32\\systeminfo.exe >> D:\\test.txt"}
  • 이 확장 실패율이 매우 높은 이유는 스크립트의 구문 오류 때문입니다. 스크립트가 오류 없이 실행되는지 확인합니다. 오류를 더 쉽게 찾을 수 있도록 더 많은 로깅을 스크립트에 입력합니다.
  • 실수로 두 번 이상 실행해도 시스템이 변경되지 않도록 idempotent가 있는 스크립트를 작성합니다.
  • 스크립트를 실행하는 경우 사용자 입력이 필요하지 않은지 확인합니다.
  • 스크립트는 90분 동안 실행할 수 있습니다. 더 길면 확장 프로비전에 실패합니다.
  • 스크립트 내에 다시 시작을 추가하지 마세요. 이 작업을 수행하면 설치하는 다른 확장에서 문제가 발생하고 다시 시작 후에 확장이 계속되지 않습니다.
  • 애플리케이션을 설치하고 스크립트를 실행하기 전에 다시 시작하게 하는 스크립트가 있는 경우 Windows 예약된 작업을 사용하거나 DSC, Chef 또는 Puppet 확장과 같은 도구를 사용하여 다시 시작을 예약합니다.
  • VM 에이전트를 중지하거나 업데이트하는 스크립트를 실행하지 않습니다. 이러한 스크립트를 실행하는 경우 확장이 전환 중 상태로 남아 있어 시간이 초과될 수 있습니다.
  • 확장은 스크립트를 한 번만 실행합니다. 시작할 때마다 스크립트를 실행하려면 확장을 사용하여 Windows 예약된 작업을 만듭니다.
  • 스크립트가 실행될 시간을 예약하려면 확장을 사용하여 Windows 예약된 작업을 만듭니다.
  • 스크립트가 실행 중인 경우 Azure Portal 또는 CLI에서 전환 중 확장 상태만 표시됩니다. 실행 중인 스크립트의 상태를 더 자주 업데이트하려면 사용자 고유의 솔루션을 만듭니다.
  • 사용자 지정 스크립트 확장은 기본적으로 프록시 서버를 지원하지 않습니다. 그러나 Invoke-WebRequest와 같이 스크립트 내에서 프록시 서버를 지원하는 파일 전송 도구를 사용할 수 있습니다.
  • 스크립트 또는 명령에서 사용할 수 있는 기본 디렉터리가 아닌 위치에 주의합니다. 이 상황을 처리할 논리가 있습니다.
  • 사용자 지정 스크립트 확장은 LocalSystem 계정에서 실행됩니다.
  • storageAccountNamestorageAccountKey 속성을 사용하려는 경우 이러한 속성을 protectedSettings에 배치해야 합니다.
  • VM에는 하나의 확장 버전만 적용할 수 있습니다. 두 번째 사용자 지정 스크립트를 실행하기 위해 기존 확장을 새 구성으로 업데이트할 수 있습니다. 또는 사용자 지정 스크립트 확장을 제거하고 업데이트된 스크립트로 다시 적용할 수 있습니다.

확장 스키마

사용자 지정 스크립트 확장 구성은 스크립트 위치 및 실행할 명령과 같은 항목을 지정합니다. 이 구성을 구성 파일에 저장하거나 명령줄에 지정하거나 Azure Resource Manager 템플릿에서 지정할 수 있습니다.

중요한 데이터는 보호된 구성에 저장하면 암호화된 후 VM 내에서만 암호 해독됩니다. 보호된 구성은 실행 명령에 비밀 또는 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 속성과 함께 사용하면 안 됩니다.

한 번에 하나의 확장 버전만 VM에 설치할 수 있습니다. 동일한 VM에 대해 동일한 Azure Resource Manager 템플릿에서 사용자 지정 스크립트를 두 번 지정하면 실패합니다.

VM 리소스 내에서 또는 독립 실행형 리소스로 이 스키마를 사용할 수 있습니다. 이 확장이 Azure Resource Manager 템플릿에서 독립 실행형 리소스로 사용되는 경우 리소스 이름은 virtualMachineName/extensionName 형식이어야 합니다.

속성 값

이름 값 또는 예 데이터 형식
apiVersion 2015-06-15 날짜
publisher Microsoft.Compute string
type CustomScriptExtension string
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 string
storageAccountName examplestorageacct string
storageAccountKey TmJK/1N3AbAZ3q/+hOXoi/l73zOqsaxXDhqa9Y83/v5UpXQp2DQIBuv2Tifp60cE/OaHsJZmQZ7teQfczQj8hg== string
managedIdentity { } 또는 { "clientId": "31b403aa-c364-4240-a7ff-d85fb6cd7232" } 또는 { "objectId": "12dd289c-0583-46e5-b9b4-115d5c19ef4b" } JSON 개체

참고 항목

이러한 속성 이름은 대/소문자를 구분합니다. 배포 문제를 방지하려면 다음과 같이 이름을 사용합니다.

속성 값 세부 정보

속성 선택 또는 필수 세부 정보
fileUris 선택 사항 다운로드할 파일의 URL입니다. URL이 중요한 경우(예: 키가 포함된 경우) 이 필드는 protectedSettings에 지정해야 합니다.
commandToExecute Required 실행할 진입점 스크립트입니다. 명령에 암호와 같은 비밀이 포함되어 있거나 파일 URI가 중요한 경우 이 속성을 사용합니다.
timestamp 선택 사항 스크립트의 다시 실행을 트리거하는 경우에만 이 값을 변경합니다. 이전 값과 다른 모든 정수 값을 사용할 수 있습니다.
storageAccountName 선택 사항 스토리지 계정의 이름입니다. 스토리지 자격 증명을 지정하는 경우 모든 fileUris 값은 Azure Blob에 대한 URL이어야 합니다.
storageAccountKey 선택 사항 스토리지 계정의 액세스 키입니다.
managedIdentity 선택 사항 파일을 다운로드하기 위한 관리 ID입니다. 유효한 값은 관리 ID의 클라이언트 ID인 clientId(선택 사항, 문자열) 및 관리 ID의 개체 ID인 objectId(선택 사항, 문자열)입니다.

퍼블릭 설정은 스크립트가 실행되는 VM에 일반 텍스트로 보내집니다. 보호된 설정은 Azure 및 VM에만 알려진 키를 통해 암호화됩니다. 설정은 보내진 그대로 VM에 저장됩니다. 즉, 설정이 암호화된 경우 VM에도 암호화되어 저장됩니다. 암호화된 값을 해독하는 데 사용되는 인증서는 VM에 저장됩니다. 인증서는 런타임 시 설정의 암호를 해독하는 데도 사용됩니다(필요한 경우).

공용 설정을 사용하면 디버깅에 유용할 수 있지만 보호된 설정을 사용하는 것이 좋습니다.

공용 또는 보호된 설정에서 설정할 수 있는 값은 다음과 같습니다. 확장은 이러한 값이 퍼블릭 설정과 보호된 설정 모두에 설정된 구성을 거부합니다.

  • commandToExecute
  • fileUris

속성: managedIdentity

참고 항목

이 속성 은 보호된 설정에서만 지정해야 합니다 .

사용자 지정 스크립트 확장 버전 1.10 이상은 fileUris 설정에 제공된 URL에서 파일을 다운로드하기 위한 관리 ID를 지원합니다. 속성을 통해 사용자 지정 스크립트 확장은 사용자가 SAS 토큰 또는 스토리지 계정 키와 같은 비밀을 전달할 필요 없이 Azure Storage 프라이빗 Blob 또는 컨테이너에 액세스할 수 있습니다.

이 기능을 사용하려면 시스템 할당 또는 사용자 할당 ID를 사용자 지정 스크립트 확장이 실행되는 VM 또는 가상 머신 확장 집합에 추가합니다. 그런 다음 Azure Storage 컨테이너 또는 Blob에 대한 관리 ID 액세스 권한을 부여합니다.

대상 VM 또는 가상 머신 확장 집합에서 시스템 할당 ID를 사용하려면 managedidentity를 빈 JSON 개체로 설정합니다.

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

대상 VM 또는 가상 머신 확장 집합에서 사용자 할당 ID를 사용하려면 managedidentity를 관리 ID의 클라이언트 ID 또는 개체 ID로 구성합니다.

{
  "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 VM 확장은 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

CLI를 사용하여 사용자 지정 스크립트를 두 번 이상 실행

사용자 지정 스크립트 확장 처리기는 정확히 동일한 설정이 전달된 경우 스크립트를 다시 실행하지 못하게 합니다. 이 동작은 스크립트가 멱등성이 아닌 경우 예기치 않은 동작을 일으킬 수 있는 우발적인 재실행을 방지합니다. 처리기가 다시 실행을 차단했는지 확인하려면 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.

Virtual Machine Scale Sets

Azure Portal에서 사용자 지정 스크립트 확장을 배포하는 경우 스토리지 계정의 스크립트에 액세스하기 위한 SAS 토큰의 만료를 제어할 수 없습니다. 이에 따라 초기 배포가 작동하지만 스토리지 계정의 SAS 토큰이 만료되면 사용자 지정 스크립트 확장에서 더 이상 스토리지 계정에 액세스할 수 없으므로 이후의 모든 크기 조정 작업이 실패합니다.

가상 머신 확장 집합에 사용자 지정 스크립트 확장을 배포하는 경우 PowerShell, Azure CLI 또는 Azure Resource Manager 템플릿을 사용하는 것이 좋습니다. 이렇게 하면 관리 ID를 사용하도록 선택하거나 필요한 기간 동안 스토리지 계정의 스크립트에 액세스하기 위해 SAS 토큰 만료를 직접 제어할 수 있습니다.

문제 해결 및 지원

Azure Portal 및 Azure PowerShell 모듈을 사용하여 확장 배포 상태에 대한 데이터를 검색할 수 있습니다. VM에 대한 확장의 배포 상태를 보려면 다음 명령을 실행합니다.

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>은 확장 실행 간에 변경될 수 있는 10진수 정수입니다. 이 값은 1.* 확장의 실제 현재 typeHandlerVersion 값과 일치합니다. 예를 들어 실제 디렉터리가 될 수 있습니다 C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.8\Downloads\2.

commandToExecute 명령을 실행하면 확장이 이 디렉터리(예: ...\Downloads\2)를 현재 작업 디렉터리로 설정합니다. 이 프로세스에서는 fileURIs 속성을 사용하여 다운로드된 파일을 찾을 때 상대 경로를 사용할 수 있습니다. 다운로드한 파일의 예는 다음과 같습니다.

fileUris의 URI 상대적 다운로드 위치 절대 다운로드 위치
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

절대 디렉터리 경로는 VM의 수명 동안 변경되지만, 사용자 지정 스크립트 확장의 단일 실행 내에서는 변경되지 않습니다.

절대 다운로드 경로는 시간이 지남에 따라 달라질 수 있으므로 가능하면 commandToExecute 문자열에서 상대 스크립트/파일 경로를 선택하는 것이 좋습니다. 예시:

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

첫 번째 URI 세그먼트 뒤의 경로 정보는 fileUris 속성 목록을 사용하여 다운로드된 파일에 유지됩니다. 앞의 표와 같이 다운로드된 파일은 다운로드 하위 디렉터리에 매핑되어 fileUris 값의 구조를 반영합니다.

지원