Automatyczna aktualizacja usługa mobilności w replikacji z platformy Azure do platformy Azure
Usługa Azure Site Recovery używa miesięcznego tempa wydania, aby rozwiązać wszelkie problemy i ulepszyć istniejące funkcje lub dodać nowe. Aby zachować aktualność usługi, należy zaplanować wdrożenie poprawek każdego miesiąca. Aby uniknąć obciążeń związanych z każdym uaktualnieniem, możesz zezwolić usłudze Site Recovery na zarządzanie aktualizacjami składników.
Jak wspomniano w architekturze odzyskiwania po awarii między platformami Azure, usługa mobilności jest instalowana na wszystkich maszynach wirtualnych platformy Azure, które mają włączoną replikację z jednego regionu platformy Azure do innego. W przypadku korzystania z aktualizacji automatycznych każda nowa wersja aktualizuje rozszerzenie usługa mobilności.
Uwaga
Do interakcji z platformą Azure zalecamy używanie modułu Azure Az w programie PowerShell. Zobacz Instalowanie programu Azure PowerShell, aby rozpocząć. Aby dowiedzieć się, jak przeprowadzić migrację do modułu Az PowerShell, zobacz Migracja programu Azure PowerShell z modułu AzureRM do modułu Az.
Jak działają aktualizacje automatyczne
Gdy używasz usługi Site Recovery do zarządzania aktualizacjami, wdraża globalny element Runbook (używany przez usługi platformy Azure) za pośrednictwem konta usługi Automation utworzonego w tej samej subskrypcji co magazyn. Każdy magazyn używa jednego konta automatyzacji. Dla każdej maszyny wirtualnej w magazynie element Runbook sprawdza aktywne aktualizacje automatyczne. Jeśli dostępna jest nowsza wersja rozszerzenia usługa mobilności, zostanie zainstalowana aktualizacja.
Domyślny harmonogram elementu Runbook odbywa się codziennie o godzinie 12:00 w strefie czasowej lokalizacji geograficznej replikowanej maszyny wirtualnej. Harmonogram elementu Runbook można również zmienić za pośrednictwem konta usługi Automation.
Uwaga
Począwszy od pakietu zbiorczego aktualizacji 35, możesz wybrać istniejące konto automatyzacji do użycia na potrzeby aktualizacji. Przed pakietem zbiorczym aktualizacji 35 usługa Site Recovery domyślnie utworzyła konto automatyzacji. Tę opcję można wybrać tylko po włączeniu replikacji dla maszyny wirtualnej. Nie jest ona dostępna dla maszyny wirtualnej, która ma już włączoną replikację. Wybrane ustawienie dotyczy wszystkich maszyn wirtualnych platformy Azure chronionych w tym samym magazynie.
Włączenie aktualizacji automatycznych nie wymaga ponownego uruchomienia maszyn wirtualnych platformy Azure ani nie ma wpływu na ciągłą replikację.
Rozliczenia zadań na koncie usługi Automation są oparte na liczbie minut czasu wykonywania zadania w miesiącu. Wykonywanie zadania zajmuje około minuty każdego dnia i jest objęte bezpłatną jednostką. Domyślnie 500 minut jest uwzględniane jako bezpłatne jednostki dla konta usługi Automation, jak pokazano w poniższej tabeli:
Uwzględnione bezpłatne jednostki (co miesiąc) | Cena |
---|---|
Czas wykonywania zadania 500 minut | {0,14/minuta |
Włącz aktualizacje automatyczne
Istnieje kilka sposobów zarządzania aktualizacjami rozszerzeń przez usługę Site Recovery:
- Zarządzanie w ramach kroku włączania replikacji
- Przełącz ustawienia aktualizacji rozszerzenia w magazynie
- Ręczne zarządzanie aktualizacjami
Zarządzanie w ramach kroku włączania replikacji
Po włączeniu replikacji dla maszyny wirtualnej, począwszy od widoku maszyny wirtualnej lub z magazynu usługi Recovery Services, możesz zezwolić usłudze Site Recovery na zarządzanie aktualizacjami rozszerzenia usługi Site Recovery lub zarządzanie nim ręcznie.
Przełącz ustawienia aktualizacji rozszerzenia w magazynie
W magazynie usługi Recovery Services przejdź do sekcji Zarządzanie infrastrukturą> usługi Site Recovery.
W obszarze Ustawienia aktualizacji>rozszerzenia usługi Azure Virtual Machines>zezwalaj usłudze Site Recovery na zarządzanie wybierz pozycję Włączone.
Aby ręcznie zarządzać rozszerzeniem, wybierz pozycję Wył.
Ważne
Po wybraniu opcji Zezwalaj usłudze Site Recovery na zarządzanie ustawienie jest stosowane do wszystkich maszyn wirtualnych w magazynie.
Wybierz pozycję Zapisz.
Uwaga
Każda opcja powiadamia o koncie usługi Automation używanym do zarządzania aktualizacjami. Jeśli używasz tej funkcji w magazynie po raz pierwszy, nowe konto usługi Automation zostanie utworzone domyślnie. Alternatywnie możesz dostosować ustawienie i wybrać istniejące konto usługi Automation. Po zdefiniowaniu wszystkie kolejne akcje umożliwiające włączenie replikacji w tym samym magazynie będą używać wybranego konta usługi Automation. Obecnie menu rozwijane będzie zawierać tylko listę kont automatyzacji, które znajdują się w tej samej grupie zasobów co magazyn.
W przypadku niestandardowego konta usługi Automation użyj następującego skryptu:
Ważne
Uruchom następujący skrypt w kontekście konta usługi Automation. Ten skrypt używa tożsamości zarządzanych przypisanych przez system jako typu uwierzytelniania.
param(
[Parameter(Mandatory=$true)]
[String] $VaultResourceId,
[Parameter(Mandatory=$true)]
[ValidateSet("Enabled",'Disabled')]
[Alias("Enabled or Disabled")]
[String] $AutoUpdateAction,
[Parameter(Mandatory=$false)]
[String] $AutomationAccountArmId
)
$SiteRecoveryRunbookName = "Modify-AutoUpdateForVaultForPatner"
$TaskId = [guid]::NewGuid().ToString()
$SubscriptionId = "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e"
$AsrApiVersion = "2021-12-01"
$ArmEndPoint = "https://management.azure.com"
$AadAuthority = "https://login.windows.net/"
$AadAudience = "https://management.core.windows.net/"
$AzureEnvironment = "AzureCloud"
$Timeout = "160"
$AuthenticationType = "SystemAssignedIdentity"
function Throw-TerminatingErrorMessage
{
Param
(
[Parameter(Mandatory=$true)]
[String]
$Message
)
throw ("Message: {0}, TaskId: {1}.") -f $Message, $TaskId
}
function Write-Tracing
{
Param
(
[Parameter(Mandatory=$true)]
[ValidateSet("Informational", "Warning", "ErrorLevel", "Succeeded", IgnoreCase = $true)]
[String]
$Level,
[Parameter(Mandatory=$true)]
[String]
$Message,
[Switch]
$DisplayMessageToUser
)
Write-Output $Message
}
function Write-InformationTracing
{
Param
(
[Parameter(Mandatory=$true)]
[String]
$Message
)
Write-Tracing -Message $Message -Level Informational -DisplayMessageToUser
}
function ValidateInput()
{
try
{
if(!$VaultResourceId.StartsWith("/subscriptions", [System.StringComparison]::OrdinalIgnoreCase))
{
$ErrorMessage = "The vault resource id should start with /subscriptions."
throw $ErrorMessage
}
$Tokens = $VaultResourceId.SubString(1).Split("/")
if(!($Tokens.Count % 2 -eq 0))
{
$ErrorMessage = ("Odd Number of tokens: {0}." -f $Tokens.Count)
throw $ErrorMessage
}
if(!($Tokens.Count/2 -eq 4))
{
$ErrorMessage = ("Invalid number of resource in vault ARM id expected:4, actual:{0}." -f ($Tokens.Count/2))
throw $ErrorMessage
}
if($AutoUpdateAction -ieq "Enabled" -and [string]::IsNullOrEmpty($AutomationAccountArmId))
{
$ErrorMessage = ("The automation account ARM id should not be null or empty when AutoUpdateAction is enabled.")
throw $ErrorMessage
}
}
catch
{
$ErrorMessage = ("ValidateInput failed with [Exception: {0}]." -f $_.Exception)
Write-Tracing -Level ErrorLevel -Message $ErrorMessage -DisplayMessageToUser
Throw-TerminatingErrorMessage -Message $ErrorMessage
}
}
function Initialize-SubscriptionId()
{
try
{
$Tokens = $VaultResourceId.SubString(1).Split("/")
$Count = 0
$ArmResources = @{}
while($Count -lt $Tokens.Count)
{
$ArmResources[$Tokens[$Count]] = $Tokens[$Count+1]
$Count = $Count + 2
}
return $ArmResources["subscriptions"]
}
catch
{
Write-Tracing -Level ErrorLevel -Message ("Initialize-SubscriptionId: failed with [Exception: {0}]." -f $_.Exception) -DisplayMessageToUser
throw
}
}
function Invoke-InternalRestMethod($Uri, $Headers, [ref]$Result)
{
$RetryCount = 0
$MaxRetry = 3
do
{
try
{
$ResultObject = Invoke-RestMethod -Uri $Uri -Headers $Headers
($Result.Value) += ($ResultObject)
break
}
catch
{
Write-InformationTracing ("Retry Count: {0}, Exception: {1}." -f $RetryCount, $_.Exception)
$RetryCount++
if(!($RetryCount -le $MaxRetry))
{
throw
}
Start-Sleep -Milliseconds 2000
}
}while($true)
}
function Invoke-InternalWebRequest($Uri, $Headers, $Method, $Body, $ContentType, [ref]$Result)
{
$RetryCount = 0
$MaxRetry = 3
do
{
try
{
$ResultObject = Invoke-WebRequest -Uri $UpdateUrl -Headers $Header -Method 'PATCH' `
-Body $InputJson -ContentType "application/json" -UseBasicParsing
($Result.Value) += ($ResultObject)
break
}
catch
{
Write-InformationTracing ("Retry Count: {0}, Exception: {1}." -f $RetryCount, $_.Exception)
$RetryCount++
if(!($RetryCount -le $MaxRetry))
{
throw
}
Start-Sleep -Milliseconds 2000
}
}while($true)
}
function Get-Header([ref]$Header, $AadAudience){
try
{
$Header.Value['Content-Type'] = 'application\json'
Write-InformationTracing ("The Authentication Type is system Assigned Identity based.")
$endpoint = $env:IDENTITY_ENDPOINT
$endpoint
$Headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Headers.Add("X-IDENTITY-HEADER", $env:IDENTITY_HEADER)
$Headers.Add("Metadata", "True")
$authenticationResult = Invoke-RestMethod -Method Get -Headers $Headers -Uri ($endpoint +'?resource=' +$AadAudience)
$accessToken = $authenticationResult.access_token
$Header.Value['Authorization'] = "Bearer " + $accessToken
$Header.Value["x-ms-client-request-id"] = $TaskId + "/" + (New-Guid).ToString() + "-" + (Get-Date).ToString("u")
}
catch
{
$ErrorMessage = ("Get-BearerToken: failed with [Exception: {0}]." -f $_.Exception)
Write-Tracing -Level ErrorLevel -Message $ErrorMessage -DisplayMessageToUser
Throw-TerminatingErrorMessage -Message $ErrorMessage
}
}
function Get-ProtectionContainerToBeModified([ref] $ContainerMappingList)
{
try
{
Write-InformationTracing ("Get protection container mappings : {0}." -f $VaultResourceId)
$ContainerMappingListUrl = $ArmEndPoint + $VaultResourceId + "/replicationProtectionContainerMappings" + "?api-version=" + $AsrApiVersion
Write-InformationTracing ("Getting the bearer token and the header.")
Get-Header ([ref]$Header) $AadAudience
$Result = @()
Invoke-InternalRestMethod -Uri $ContainerMappingListUrl -Headers $header -Result ([ref]$Result)
$ContainerMappings = $Result[0]
Write-InformationTracing ("Total retrieved container mappings: {0}." -f $ContainerMappings.Value.Count)
foreach($Mapping in $ContainerMappings.Value)
{
if(($Mapping.properties.providerSpecificDetails -eq $null) -or ($Mapping.properties.providerSpecificDetails.instanceType -ine "A2A"))
{
Write-InformationTracing ("Mapping properties: {0}." -f ($Mapping.properties))
Write-InformationTracing ("Ignoring container mapping: {0} as the provider does not match." -f ($Mapping.Id))
continue;
}
if($Mapping.Properties.State -ine "Paired")
{
Write-InformationTracing ("Ignoring container mapping: {0} as the state is not paired." -f ($Mapping.Id))
continue;
}
Write-InformationTracing ("Provider specific details {0}." -f ($Mapping.properties.providerSpecificDetails))
$MappingAutoUpdateStatus = $Mapping.properties.providerSpecificDetails.agentAutoUpdateStatus
$MappingAutomationAccountArmId = $Mapping.properties.providerSpecificDetails.automationAccountArmId
$MappingHealthErrorCount = $Mapping.properties.HealthErrorDetails.Count
if($AutoUpdateAction -ieq "Enabled" -and
($MappingAutoUpdateStatus -ieq "Enabled") -and
($MappingAutomationAccountArmId -ieq $AutomationAccountArmId) -and
($MappingHealthErrorCount -eq 0))
{
Write-InformationTracing ("Provider specific details {0}." -f ($Mapping.properties))
Write-InformationTracing ("Ignoring container mapping: {0} as the auto update is already enabled and is healthy." -f ($Mapping.Id))
continue;
}
($ContainerMappingList.Value).Add($Mapping.id)
}
}
catch
{
$ErrorMessage = ("Get-ProtectionContainerToBeModified: failed with [Exception: {0}]." -f $_.Exception)
Write-Tracing -Level ErrorLevel -Message $ErrorMessage -DisplayMessageToUser
Throw-TerminatingErrorMessage -Message $ErrorMessage
}
}
$OperationStartTime = Get-Date
$ContainerMappingList = New-Object System.Collections.Generic.List[System.String]
$JobsInProgressList = @()
$JobsCompletedSuccessList = @()
$JobsCompletedFailedList = @()
$JobsFailedToStart = 0
$JobsTimedOut = 0
$Header = @{}
$AzureRMProfile = Get-Module -ListAvailable -Name AzureRM.Profile | Select Name, Version, Path
$AzureRmProfileModulePath = Split-Path -Parent $AzureRMProfile.Path
Add-Type -Path (Join-Path $AzureRmProfileModulePath "Microsoft.IdentityModel.Clients.ActiveDirectory.dll")
$Inputs = ("Tracing inputs VaultResourceId: {0}, Timeout: {1}, AutoUpdateAction: {2}, AutomationAccountArmId: {3}." -f $VaultResourceId, $Timeout, $AutoUpdateAction, $AutomationAccountArmId)
Write-Tracing -Message $Inputs -Level Informational -DisplayMessageToUser
$CloudConfig = ("Tracing cloud configuration ArmEndPoint: {0}, AadAuthority: {1}, AadAudience: {2}." -f $ArmEndPoint, $AadAuthority, $AadAudience)
Write-Tracing -Message $CloudConfig -Level Informational -DisplayMessageToUser
ValidateInput
$SubscriptionId = Initialize-SubscriptionId
Get-ProtectionContainerToBeModified ([ref]$ContainerMappingList)
$Input = @{
"properties"= @{
"providerSpecificInput"= @{
"instanceType" = "A2A"
"agentAutoUpdateStatus" = $AutoUpdateAction
"automationAccountArmId" = $AutomationAccountArmId
"automationAccountAuthenticationType" = $AuthenticationType
}
}
}
$InputJson = $Input | ConvertTo-Json
if ($ContainerMappingList.Count -eq 0)
{
Write-Tracing -Level Succeeded -Message ("Exiting as there are no container mappings to be modified.") -DisplayMessageToUser
exit
}
Write-InformationTracing ("Container mappings to be updated has been retrieved with count: {0}." -f $ContainerMappingList.Count)
try
{
Write-InformationTracing ("Start the modify container mapping jobs.")
ForEach($Mapping in $ContainerMappingList)
{
try {
$UpdateUrl = $ArmEndPoint + $Mapping + "?api-version=" + $AsrApiVersion
Get-Header ([ref]$Header) $AadAudience
$Result = @()
Invoke-InternalWebRequest -Uri $UpdateUrl -Headers $Header -Method 'PATCH' `
-Body $InputJson -ContentType "application/json" -Result ([ref]$Result)
$Result = $Result[0]
$JobAsyncUrl = $Result.Headers['Azure-AsyncOperation']
Write-InformationTracing ("The modify container mapping job invoked with async url: {0}." -f $JobAsyncUrl)
$JobsInProgressList += $JobAsyncUrl;
# Rate controlling the set calls to maximum 60 calls per minute.
# ASR throttling for set calls is 200 in 1 minute.
Start-Sleep -Milliseconds 1000
}
catch{
Write-InformationTracing ("The modify container mappings job creation failed for: {0}." -f $Ru)
Write-InformationTracing $_
$JobsFailedToStart++
}
}
Write-InformationTracing ("Total modify container mappings has been initiated: {0}." -f $JobsInProgressList.Count)
}
catch
{
$ErrorMessage = ("Modify container mapping jobs failed with [Exception: {0}]." -f $_.Exception)
Write-Tracing -Level ErrorLevel -Message $ErrorMessage -DisplayMessageToUser
Throw-TerminatingErrorMessage -Message $ErrorMessage
}
try
{
while($JobsInProgressList.Count -ne 0)
{
Sleep -Seconds 30
$JobsInProgressListInternal = @()
ForEach($JobAsyncUrl in $JobsInProgressList)
{
try
{
Get-Header ([ref]$Header) $AadAudience
$Result = Invoke-RestMethod -Uri $JobAsyncUrl -Headers $header
$JobState = $Result.Status
if($JobState -ieq "InProgress")
{
$JobsInProgressListInternal += $JobAsyncUrl
}
elseif($JobState -ieq "Succeeded" -or `
$JobState -ieq "PartiallySucceeded" -or `
$JobState -ieq "CompletedWithInformation")
{
Write-InformationTracing ("Jobs succeeded with state: {0}." -f $JobState)
$JobsCompletedSuccessList += $JobAsyncUrl
}
else
{
Write-InformationTracing ("Jobs failed with state: {0}." -f $JobState)
$JobsCompletedFailedList += $JobAsyncUrl
}
}
catch
{
Write-InformationTracing ("The get job failed with: {0}. Ignoring the exception and retrying the next job." -f $_.Exception)
# The job on which the tracking failed, will be considered in progress and tried again later.
$JobsInProgressListInternal += $JobAsyncUrl
}
# Rate controlling the get calls to maximum 120 calls each minute.
# ASR throttling for get calls is 10000 in 60 minutes.
Start-Sleep -Milliseconds 500
}
Write-InformationTracing ("Jobs remaining {0}." -f $JobsInProgressListInternal.Count)
$CurrentTime = Get-Date
if($CurrentTime -gt $OperationStartTime.AddMinutes($Timeout))
{
Write-InformationTracing ("Tracing modify cloud pairing jobs has timed out.")
$JobsTimedOut = $JobsInProgressListInternal.Count
$JobsInProgressListInternal = @()
}
$JobsInProgressList = $JobsInProgressListInternal
}
}
catch
{
$ErrorMessage = ("Tracking modify cloud pairing jobs failed with [Exception: {0}]." -f $_.Exception)
Write-Tracing -Level ErrorLevel -Message $ErrorMessage -DisplayMessageToUser
Throw-TerminatingErrorMessage -Message $ErrorMessage
}
Write-InformationTracing ("Tracking modify cloud pairing jobs completed.")
Write-InformationTracing ("Modify cloud pairing jobs success: {0}." -f $JobsCompletedSuccessList.Count)
Write-InformationTracing ("Modify cloud pairing jobs failed: {0}." -f $JobsCompletedFailedList.Count)
Write-InformationTracing ("Modify cloud pairing jobs failed to start: {0}." -f $JobsFailedToStart)
Write-InformationTracing ("Modify cloud pairing jobs timedout: {0}." -f $JobsTimedOut)
if($JobsTimedOut -gt 0)
{
$ErrorMessage = "One or more modify cloud pairing jobs has timedout."
Write-Tracing -Level ErrorLevel -Message ($ErrorMessage)
Throw-TerminatingErrorMessage -Message $ErrorMessage
}
elseif($JobsCompletedSuccessList.Count -ne $ContainerMappingList.Count)
{
$ErrorMessage = "One or more modify cloud pairing jobs failed."
Write-Tracing -Level ErrorLevel -Message ($ErrorMessage)
Throw-TerminatingErrorMessage -Message $ErrorMessage
}
Write-Tracing -Level Succeeded -Message ("Modify cloud pairing completed.") -DisplayMessageToUser
Ręczne zarządzanie aktualizacjami
Jeśli na maszynach wirtualnych są zainstalowane nowe aktualizacje usługa mobilności, zobaczysz następujące powiadomienie: Dostępna jest nowa aktualizacja agenta replikacji usługi Site Recovery. Kliknij, aby zainstalować.
Wybierz powiadomienie, aby otworzyć stronę wyboru maszyny wirtualnej.
Wybierz maszyny wirtualne, które chcesz uaktualnić, a następnie wybierz przycisk OK. Usługa mobilności aktualizacji zostanie uruchomiona dla każdej wybranej maszyny wirtualnej.
Znane problemy i rozwiązywanie problemów
Jeśli wystąpi problem z aktualizacjami automatycznymi, w obszarze Problemy z konfiguracją na pulpicie nawigacyjnym magazynu zostanie wyświetlone powiadomienie o błędzie.
Jeśli nie możesz włączyć aktualizacji automatycznych, zobacz następujące typowe błędy i zalecane akcje:
Błąd: nie masz uprawnień do tworzenia konta Uruchom jako platformy Azure (jednostki usługi) i udzielenia roli Współautor jednostce usługi.
Zalecana akcja: upewnij się, że zalogowane konto jest przypisane jako Współautor i spróbuj ponownie. Aby uzyskać więcej informacji na temat przypisywania uprawnień, zobacz sekcję Wymaganych uprawnień w temacie Instrukcje: tworzenie aplikacji i jednostki usługi Microsoft Entra przy użyciu portalu, które mogą uzyskiwać dostęp do zasobów.
Aby rozwiązać większość problemów po włączeniu aktualizacji automatycznych, wybierz pozycję Napraw. Jeśli przycisk naprawy jest niedostępny, zobacz komunikat o błędzie wyświetlany w okienku ustawień aktualizacji rozszerzenia.
Błąd: Konto Uruchom jako nie ma uprawnień dostępu do zasobu usługi Recovery Services.
Zalecana akcja: Usuń, a następnie ponownie utwórz konto Uruchom jako. Możesz też upewnić się, że aplikacja Microsoft Entra konta Uruchom jako usługi Automation może uzyskać dostęp do zasobu usługi Recovery Services.
Błąd: Nie można odnaleźć konta Uruchom jako. Jeden z tych elementów został usunięty lub nie został utworzony — aplikacja Entra firmy Microsoft, jednostka usługi, rola, zasób certyfikatu automatyzacji, zasób połączenia automatyzacji — lub odcisk palca nie jest identyczny między certyfikatem a połączeniem.
Zalecana akcja: Usuń, a następnie ponownie utwórz konto Uruchom jako.
Błąd: Certyfikat Uruchom jako platformy Azure używany przez konto usługi Automation wkrótce wygaśnie.
Certyfikat z podpisem własnym utworzony dla konta Uruchom jako wygasa rok od daty utworzenia. Można go odnowić w dowolnym momencie przed wygaśnięciem jego ważności. Jeśli zarejestrujesz się w celu otrzymywania powiadomień e-mail, otrzymasz również wiadomości e-mail, gdy akcja jest wymagana od Twojej strony. Ten błąd zostanie wyświetlony dwa miesiące przed datą wygaśnięcia i zmieni się na błąd krytyczny, jeśli certyfikat wygasł. Po wygaśnięciu certyfikatu automatyczna aktualizacja nie będzie działać, dopóki nie odnowisz tego samego certyfikatu.
Zalecana akcja: Aby rozwiązać ten problem, wybierz pozycję Napraw, a następnie odnów certyfikat.
Uwaga
Po odnowieniu certyfikatu odśwież stronę, aby wyświetlić bieżący stan.
Następne kroki
Dowiedz się więcej na temat migrowania typu uwierzytelniania kont usługi Automation do tożsamości zarządzanych.