Pokud chcete restartovat Azure App Service dle časového plánu, nabízí se použít jednoduše PowerShell:
Stop-AzureRmWebApp -Name '_App Service Name_' -ResourceGroupName '_Resource Group Name_' Start-AzureRmWebApp -Name '_App Service Name_' -ResourceGroupName '_Resource Group Name_'
Jenom je potřeba vyřešit dva problémy:
- Čím budeme takový skript spouštět? …můžeme prostě použít WebJob.
- Jak se bude skript autentizovat? …je potřeba použít Service Principal.
Vezměme to od konce.
Credits: Tento návod vznikl na základě postupu původně publikovaného Karanem Singhem, zaměstnancem Microsoftu, na jeho MSDN blog. Postup jsem opravil a ověřil.
Vytvoření Service Principal Id pro autentizaci
Určitě není dobrý nápad, spouštět podobné joby pod uživatelským účtem reálného uživatele. V mém případě je to navíc v podstatě nemožné, protože mám Organizational Account s 2-FA.
Je potřeba použít servisní účet a Service Principal Id je přesně to, co v kontextu Azure potřebujeme.
Abychom ho vytvořili, můžeme použít jednoduchý Powershell script (jednorázový úkon z vlastního PC):
param ( [Parameter(Mandatory=$true, HelpMessage="Enter Azure Subscription name. You need to be Subscription Admin to execute the script")] [string] $subscriptionName, [Parameter(Mandatory=$true, HelpMessage="Provide a password for SPN application that you would create")] [string] $password, [Parameter(Mandatory=$false, HelpMessage="Provide a SPN role assignment")] [string] $spnRole = "owner" ) #Initialize $ErrorActionPreference = "Stop" $VerbosePreference = "SilentlyContinue" $userName = $env:USERNAME $newguid = [guid]::NewGuid() $displayName = [String]::Format("VSO.{0}.{1}", $userName, $newguid) $homePage = "http://" + $displayName $identifierUri = $homePage #Initialize subscription $isAzureModulePresent = Get-Module -Name AzureRM* -ListAvailable if ([String]::IsNullOrEmpty($isAzureModulePresent) -eq $true) { Write-Output "Script requires AzureRM modules to be present. Obtain AzureRM from https://github.com/Azure/azure-powershell/releases. Please refer https://github.com/Microsoft/vsts-tasks/blob/master/Tasks/DeployAzureResourceGroup/README.md for recommended AzureRM versions." -Verbose return } Import-Module -Name AzureRM.Profile Write-Output "Provide your credentials to access Azure subscription $subscriptionName" -Verbose Login-AzureRmAccount -SubscriptionName $subscriptionName $azureSubscription = Get-AzureRmSubscription -SubscriptionName $subscriptionName $connectionName = $azureSubscription.SubscriptionName $tenantId = $azureSubscription.TenantId $id = $azureSubscription.SubscriptionId #Create a new AD Application Write-Output "Creating a new Application in AAD (App URI - $identifierUri)" -Verbose $secpasswd = ConvertTo-SecureString $password -AsPlainText -Force $azureAdApplication = New-AzureRmADApplication -DisplayName $displayName -HomePage $homePage -IdentifierUris $identifierUri -Password $secpasswd -Verbose $appId = $azureAdApplication.ApplicationId Write-Output "Azure AAD Application creation completed successfully (Application Id: $appId)" -Verbose #Create new SPN Write-Output "Creating a new SPN" -Verbose $spn = New-AzureRmADServicePrincipal -ApplicationId $appId $spnName = $spn.ServicePrincipalName Write-Output "SPN creation completed successfully (SPN Name: $spnName)" -Verbose #Assign role to SPN Write-Output "Waiting for SPN creation to reflect in Directory before Role assignment" Start-Sleep 20 Write-Output "Assigning role ($spnRole) to SPN App ($appId)" -Verbose New-AzureRmRoleAssignment -RoleDefinitionName $spnRole -ServicePrincipalName $appId Write-Output "SPN role assignment completed successfully" -Verbose #Print the values Write-Output "`nCopy and Paste below values for Service Connection" -Verbose Write-Output "***************************************************************************" Write-Output "Connection Name: $connectionName(SPN)" Write-Output "Subscription Id: $id" Write-Output "Subscription Name: $connectionName" Write-Output "Service Principal Id: $appId" Write-Output "Service Principal key: <Password that you typed in>" Write-Output "Tenant Id: $tenantId" Write-Output "***************************************************************************"
Budete dotázáni na název subscription a heslo pro Service Principal Id. Pro úspěšné vykonání musíte být administrátoři své Azure Active Directory.
Založený Service Principal Id si pečlivě uložte a chraňte, dostává totiž roli Owner (popř. můžete nastavit jinou, např. Contributor). Účet lze využít i na spoustu dalších administračních úkonů, byť je dobrý nápad mít oddělené účty pro každý takový job (ideálně s minimálními právy jen pro daný úkon, ale to ponechávám pro tuto chvíli pro vlastní doladění).
Vytvoření naplánovaného WebJobu
V zásadě použijte libovolný vlastní postup pro nasazení naplánovaného WebJobu, který bude spouště příslušný skript:
$ProgressPreference= "SilentlyContinue" $password = '_Service Principal Key/Password_' $secpasswd = ConvertTo-SecureString $password -AsPlainText -Force $mycreds = New-Object System.Management.Automation.PSCredential ("_Service Principal Id_", $secpasswd) Add-AzureRmAccount -ServicePrincipal -Tenant '_Tenant Id_' -Credential $mycreds Select-AzureRmSubscription -SubscriptionId '_Subscription Id_' Stop-AzureRmWebApp -Name '_App Service Name_' -ResourceGroupName '_Resource Group Name_' Start-AzureRmWebApp -Name '_App Service Name_' -ResourceGroupName '_Resource Group Name_'
Můžete to udělat například ručně přímo z portálu:
- Uložte skript do souboru run.ps1 a ten zazipujte (na názvu ZIPu nezáleží).
- Přes App Service / Web Jobs a Add můžete WebJob přidat:
Hotov. Jen pamatujte, že naplánované WebJoby běží lépe (vůbec), jen pokud běží vaše aplikace, tedy potřebujete mít nastaven režim Always On.
Vytvořený WebJob můžete snadno ověřit i ručním spuštěním z portálu (tlačítko Start), popř. si můžete výsledek prohlédnout přes KUDU Dashboard (tlačítko Logs) – což mimochodem vřele doporučuji, protože není jisté, že se vám vše povedlo bezchybně a čekat na plánované spuštění je zbytečné.