Azure Automation Powershell 刷新较低级别数据库

问题描述 投票:0回答:1

我正在使用下面网站中的脚本来自动刷新我们的生产数据库中的较低环境数据库。

https://techcommunity.microsoft.com/t5/azure-sql-blog/how-to-automate-azure-sql-management-instance-database-copy-and/ba-p/3874505

如果我从本地计算机运行此脚本,它会完全执行其应该执行的操作。但是,当我发布它并从 Azure 作为 Runbook 运行它时,它却没有。但是,我不知道如何获得某种错误消息来告诉我出了什么问题。

我正在使用脚本中定义的托管身份。我已经打开了详细日志记录,但仍然无法找出缺少的内容。由于脚本在本地完美运行,在我看来问题必须是权限,对吗?但我无法弄清楚缺少什么权限(或者是否存在其他问题)。

这是我第一次尝试 Azure 自动化,我看到使用它有很多好处,但我必须克服第一个障碍。以下是我现有的代码:

# Newest version for testing
Disable-AzContextAutosave -Scope Process

# Connect to Azure with user-assigned managed identity
$AzureContext = (Connect-AzAccount -Identity -AccountId "user-defined-managed-id here").context

# set and store context
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription -DefaultProfile $AzureContext

# Select UAT Subscription
Select-AzSubscription -SubscriptionId [non-prod subscription id here]

$dbNames = @("Mv_SISD", "Mv_SISD_GEO", "Mv_SISD_WO")
$sourceMi = "sqlmi-prd-02"
$sourceRg = "SQL-Prod"
$targetMi = "sqlmi-dev-02"
$targetRg = "SQL-UAT"

$timeout = $false

$expectedDuration = New-TimeSpan -Days 0 -Hours 1 -Minutes 30
$startTime = Get-Date

Write-Host "Starting drop operation for databases: "
for ( $i = 0; $i -lt $dbNames.count; $i++) { Write-Host $dbNames[$i] " "}

## Start drop for all databases in the list.
##
for ( $i = 0; $i -lt $dbNames.count; $i++)
{
    $vmExists = Get-AzResource -Name $dbNames[$i] -ResourceGroupName $targetRg
    if ($vmExists) {
    Remove-AzSqlInstanceDatabase -Name $dbNames[$i] -InstanceName $targetMi -ResourceGroupName $targetRg -Force}
    else {
        Write-Output "VM $dbnames[$i] does not exist, skipping."
    }
}

##$allDropsSucceeded = $true

# Select PROD Subscription
Write-Host "Switch to Prod subscription: "
Select-AzSubscription -SubscriptionId [prod subscription id here] 

Write-Host "Starting copy operation for databases: "
for ( $i = 0; $i -lt $dbNames.count; $i++) { Write-Host $dbNames[$i] " "}

## Start copy for all databases in the list.
##
for ( $i = 0; $i -lt $dbNames.count; $i++)
{
    Copy-AzSqlInstanceDatabase -DatabaseName $dbNames[$i] -InstanceName $sourceMi -ResourceGroupName $sourceRg -TargetInstanceName $targetMi -TargetResourceGroupName $targetRg -AsJob | Format-Table -Property Name, PSBeginTime, State
}

$allCopiesSucceeded = $true

while($true)
{
    if ((Get-Date) -gt $startTime + $expectedDuration)
    {
        Write-Host "Script timeout. Terminating the script."
        $timeout = $true
        break
    }

    Write-Host "Getting the status of operations..."
    Start-Sleep -Seconds 10
    $operations = [System.Collections.ArrayList]@()

    ## Get status of all copy operations.
    ##
    for ( $i = 0; $i -lt $dbNames.count; $i++)
    {
        $operations += Get-AzSqlInstanceDatabaseCopyOperation -DatabaseName $dbNames[$i] -InstanceName $sourceMi -ResourceGroupName $sourceRg -TargetInstanceName $targetMi -TargetResourceGroupName $targetRg -OnlyLatestPerDatabase
    }

    try
    {
        $allCopiesSucceeded = $true;
        for ( $i = 0; $i -lt $dbNames.count; $i++)
        {
            ## Call with -AsJob, because this is long running operation (size of data),
            ## and we want to parallelize calls for multiple databases.
            ##
            Write-Host "Status of copy for " $dbNames[$i] " is " $operations[$i].State
            if (!($operations[$i].State -eq "Succeeded")) { $allCopiesSucceeded = $false; }
        }
    }
    catch { $allCopiesSucceeded = $false; Write-Host "Oops, something went wrong. Retrying..." }

    if ($allCopiesSucceeded)
    {
        Write-Host "All operations ready for completion!"
        break
    }
    else { Write-Host "Copying in progress..." }

    Write-Host "Waiting a bit..."
    Start-Sleep -Seconds 5
}

if ($allCopiesSucceeded -and !$timeout) 
{
    ## Let's complete all database copy operations.
    ##
    Write-Host "Completing all database copy operations..."

    for ( $i = 0; $i -lt $dbNames.count; $i++)
    {
        ## Call with -AsJob, because this is not super quick operation
        ## and we want to parallelize calls for multiple databases.
        ##
        Complete-AzSqlInstanceDatabaseCopy -DatabaseName $dbNames[$i] -InstanceName $sourceMi -ResourceGroupName $sourceRg -TargetInstanceName $targetMi -TargetResourceGroupName $targetRg -AsJob | Format-Table -Property Name, PSBeginTime, State
    }

    $completeDone = $true

    while($true)
    {
        Write-Host "Getting the status of copy complete operations..."
        $completeOperations = [System.Collections.ArrayList]@()

        for ( $i = 0; $i -lt $dbNames.count; $i++)
        {
            $completeOperations += Get-AzSqlInstanceDatabaseCopyOperation -DatabaseName $dbNames[$i] -InstanceName $sourceMi -ResourceGroupName $sourceRg -TargetInstanceName $targetMi -TargetResourceGroupName $targetRg -OnlyLatestPerDatabase
        }

        try
        {
            $completeDone = $true
            for ( $i = 0; $i -lt $dbNames.count; $i++)
            {
                Write-Host "Status of copy completion for " $dbNames[$i] " is " $completeOperations[$i].State
                if (!($completeOperations[$i].State -eq "Succeeded")) { $completeDone = $false; }
            }
        }
        catch { Write-Host "Oops, something went wrong. Retrying..." }

        if ($completeDone)
        {
            Write-Host "Database copy succeeded for databases: "
            for ( $i = 0; $i -lt $dbNames.count; $i++) { Write-Host $dbNames[$i] " "}

            break
        }
        else { Write-Host "Complete in progress..." }

        Write-Host "Waiting a bit..."
        Start-Sleep -Seconds 5
    }
}
azure powershell automation
1个回答
0
投票

在本地运行 PowerShell 脚本时,您可能不需要特定资源的显式权限。但是,在 Azure 自动化 Runbook 中执行相同的脚本时,必须向相关用户或管理员或托管标识授予必要的权限。

要访问 SQL 托管实例并与之交互,您必须向用户分配

"SQL Managed Instance Contributor"
角色。这可以通过访问
"Access Control"
并在两个 SQL 托管实例下添加
role assignment
来完成,如下所示。

此外,请确保

system managed identity or user managed identity
在 Azure 自动化帐户中启用了
"Automation Contributor"
角色。

enter image description here

我尝试在使用系统管理身份设置的自动化帐户中执行您的脚本,并且能够按预期执行。

Connect-AzAccount -Identity
$dbNames = @("mydb","mydbj")
$sourceMi = "instance12"
$sourceRg = "xxx"
$targetMi = "instance22"
$targetRg = "xxx"
$timeout = $false

$expectedDuration = New-TimeSpan -Days 0 -Hours 1 -Minutes 30
$startTime = Get-Date
Write-Host "Starting drop operation for databases: "
for ( $i = 0; $i -lt $dbNames.count; $i++) { Write-Host $dbNames[$i] " "}
for ( $i = 0; $i -lt $dbNames.count; $i++)
{
    $vmExists = Get-AzResource -Name $dbNames[$i] -ResourceGroupName $targetRg
    if ($vmExists) {
    Remove-AzSqlInstanceDatabase -Name $dbNames[$i] -InstanceName $targetMi -ResourceGroupName $targetRg -Force}
    else {
        Write-Output "VM $dbnames[$i] does not exist, skipping."
    }
}

Write-Host "Starting copy operation for databases: "
for ( $i = 0; $i -lt $dbNames.count; $i++) { Write-Host $dbNames[$i] " "}

## Start copy for all databases in the list.
##
for ( $i = 0; $i -lt $dbNames.count; $i++)
{
    Copy-AzSqlInstanceDatabase -DatabaseName $dbNames[$i] -InstanceName $sourceMi -ResourceGroupName $sourceRg -TargetInstanceName $targetMi -TargetResourceGroupName $targetRg -AsJob | Format-Table -Property Name, PSBeginTime, State
}

$allCopiesSucceeded = $true

while($true)
{
    if ((Get-Date) -gt $startTime + $expectedDuration)
    {
        Write-Host "Script timeout. Terminating the script."
        $timeout = $true
        break
    }

    Write-Host "Getting the status of operations..."
    Start-Sleep -Seconds 10
    $operations = [System.Collections.ArrayList]@()
    for ( $i = 0; $i -lt $dbNames.count; $i++)
    {
        $operations += Get-AzSqlInstanceDatabaseCopyOperation -DatabaseName $dbNames[$i] -InstanceName $sourceMi -ResourceGroupName $sourceRg -TargetInstanceName $targetMi -TargetResourceGroupName $targetRg -OnlyLatestPerDatabase
    }

    try
    {
        $allCopiesSucceeded = $true;
        for ( $i = 0; $i -lt $dbNames.count; $i++)
        {
            ## Call with -AsJob, because this is long running operation (size of data),
            ## and we want to parallelize calls for multiple databases.
            ##
            Write-Host "Status of copy for " $dbNames[$i] " is " $operations[$i].State
            if (!($operations[$i].State -eq "Succeeded")) { $allCopiesSucceeded = $false; }
        }
    }
    catch { $allCopiesSucceeded = $false; Write-Host "Oops, something went wrong. Retrying..." }

    if ($allCopiesSucceeded)
    {
        Write-Host "All operations ready for completion!"
        break
    }
    else { Write-Host "Copying in progress..." }

    Write-Host "Waiting a bit..."
    Start-Sleep -Seconds 5
}

if ($allCopiesSucceeded -and !$timeout) 
{
    ## Let's complete all database copy operations.
    ##
    Write-Host "Completing all database copy operations..."

    for ( $i = 0; $i -lt $dbNames.count; $i++)
    {
        ## Call with -AsJob, because this is not super quick operation
        ## and we want to parallelize calls for multiple databases.
        ##
        Complete-AzSqlInstanceDatabaseCopy -DatabaseName $dbNames[$i] -InstanceName $sourceMi -ResourceGroupName $sourceRg -TargetInstanceName $targetMi -TargetResourceGroupName $targetRg -AsJob | Format-Table -Property Name, PSBeginTime, State
    }

    $completeDone = $true

    while($true)
    {
        Write-Host "Getting the status of copy complete operations..."
        $completeOperations = [System.Collections.ArrayList]@()

        for ( $i = 0; $i -lt $dbNames.count; $i++)
        {
            $completeOperations += Get-AzSqlInstanceDatabaseCopyOperation -DatabaseName $dbNames[$i] -InstanceName $sourceMi -ResourceGroupName $sourceRg -TargetInstanceName $targetMi -TargetResourceGroupName $targetRg -OnlyLatestPerDatabase
        }

        try
        {
            $completeDone = $true
            for ( $i = 0; $i -lt $dbNames.count; $i++)
            {
                Write-Host "Status of copy completion for " $dbNames[$i] " is " $completeOperations[$i].State
                if (!($completeOperations[$i].State -eq "Succeeded")) { $completeDone = $false; }
            }
        }
        catch { Write-Host "Oops, something went wrong. Retrying..." }

        if ($completeDone)
        {
            Write-Host "Database copy succeeded for databases: "
            for ( $i = 0; $i -lt $dbNames.count; $i++) { Write-Host $dbNames[$i] " "}

            break
        }
        else { Write-Host "Complete in progress..." }

        Write-Host "Waiting a bit..."
        Start-Sleep -Seconds 5
    }
}

注意:如果您对资源组中的资源拥有完全控制权,则授予

"Owner"
角色可提供彻底的访问权限,包括读取、修改所有资源以及与所有资源交互的能力。

输出:

enter image description here

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.