PowerShell を使用したエラスティック ジョブの作成と管理
適用対象: Azure SQL データベース
この記事では、PowerShell を使用してエラスティック ジョブを使い始めるためのシナリオの例を提供します。 エラスティック ジョブを使用すると、複数のデータベースにわたって 1 つまたは複数の Transact-SQL (T-SQL) スクリプトを同時に実行できます。
このエンドツーエンドのチュートリアルでは、複数のデータベースにわたってクエリを実行するために必要な手順を学習します。
- エラスティック ジョブ エージェントを作成する
- ジョブによってターゲット上でスクリプトを実行できるようにジョブ認証情報を作成する
- ジョブを実行するターゲット (サーバー、エラスティック プール、データベース) を定義する
- エージェントが接続してジョブを実行できるように、ターゲット データベースにデータベース スコープ資格情報を作成する
- ジョブの作成
- ジョブにジョブ ステップを追加する
- ジョブの実行を開始する
- ジョブを監視する
前提条件
エラスティック データベース ジョブには、一連の PowerShell コマンドレットがあります。
これらのコマンドレットは、2023 年 11 月に更新されました。
最新のエラスティック ジョブ コマンドレットをインストールする
Azure サブスクリプションをお持ちでない場合は、始める前に無料アカウントを作成してください。
まだ存在しない場合は、最新バージョンのAz.Sql
モジュールと SqlServer
モジュールをインストールします。 管理アクセス権で次の PowerShell コマンドを実行します。
# installs the latest PackageManagement and PowerShellGet packages
Find-Package PackageManagement | Install-Package -Force
Find-Package PowerShellGet | Install-Package -Force
# Restart your powershell session with administrative access
# Install and import the Az.Sql module, then confirm
Install-Module -Name Az.Sql
Import-Module Az.Sql
Install-Module -Name SqlServer
Import-Module SqlServer
詳細については、「SQL Server PowerShell モジュールのインストール」を参照してください。
必要なリソースを作成する
エラスティック ジョブ エージェントを作成するには、エラスティック ジョブ データベースとして使用するデータベース (S1 以上) が必要です。
次のスクリプトを実行すると、エラスティック ジョブ データベースとして使用する新しいリソース グループ、サーバー、およびデータベースが作成されます。 2 番目のスクリプトを実行すると、ジョブを実行する対象の、2 つの空のデータベースを含む 2 番目のサーバーが作成されます。
エラスティック ジョブには特定の命名要件がないため、Azure 要件に準拠している限り、任意の命名規則を使用できます。 エラスティック ジョブ データベースとして機能する空のデータベースをサーバーに既に作成している場合は、[エラスティック ジョブ エージェントの作成] に進みます。
エラスティック ジョブのプライベート エンドポイントを使用する場合、New-AzSqlServerFirewallRule
でファイアウォール規則を構成する必要はありません。
# Sign in to your Azure account
Connect-AzAccount
# The SubscriptionId in which to create these objects
$SubscriptionId = '<your subscription id>'
# Set subscription context, important if you have access to more than one subscription.
Set-AzContext -SubscriptionId $subscriptionId
# Create a resource group
Write-Output "Creating a resource group..."
$resourceGroupName = Read-Host "Please enter a resource group name"
$location = Read-Host "Please enter an Azure Region, for example westus2"
$rg = New-AzResourceGroup -Name $resourceGroupName -Location $location
$rg
# Create an Azure SQL logical server
Write-Output "Creating a server..."
$agentServerName = Read-Host "Please enter an agent server name"
$agentServerName = $agentServerName + "-" + [guid]::NewGuid()
$adminLogin = Read-Host "Please enter the server admin name"
$adminPassword = Read-Host "Please enter the server admin password"
$adminPasswordSecure = ConvertTo-SecureString -String $AdminPassword -AsPlainText -Force
$adminCred = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $adminLogin, $adminPasswordSecure
$parameters = @{
ResourceGroupName = $resourceGroupName
Location = $location
ServerName = $agentServerName
SqlAdministratorCredentials = ($adminCred)
}
$agentServer = New-AzSqlServer @parameters
# Set server firewall rules to allow all Azure IPs
# Unnecessary if using an elastic jobs private endpoint
Write-Output "Creating a server firewall rule..."
$agentServer | New-AzSqlServerFirewallRule -AllowAllAzureIPs -FirewallRuleName "Allowed IPs"
$agentServer
# Create the job database
Write-Output "Creating a blank database to be used as the Job Database..."
$jobDatabaseName = "JobDatabase"
$parameters = @{
ResourceGroupName = $resourceGroupName
ServerName = $agentServerName
DatabaseName = $jobDatabaseName
RequestedServiceObjectiveName = "S1"
}
$jobDatabase = New-AzSqlDatabase @parameters
$jobDatabase
# Create a target server and sample databases - uses the same credentials
Write-Output "Creating target server..."
$targetServerName = Read-Host "Please enter a target server name"
$targetServerName = $targetServerName + "-" + [guid]::NewGuid()
$parameters = @{
ResourceGroupName= $resourceGroupName
Location= $location
ServerName= $targetServerName
ServerVersion= "12.0"
SqlAdministratorCredentials= ($adminCred)
}
$targetServer = New-AzSqlServer @parameters
# Set target server firewall rules to allow all Azure IPs
# Unnecessary if using an elastic jobs private endpoint
$targetServer | New-AzSqlServerFirewallRule -AllowAllAzureIPs
# Set the target firewall to include your desired IP range.
# Change the following -StartIpAddress and -EndIpAddress values.
$parameters = @{
StartIpAddress = "0.0.0.0"
EndIpAddress = "0.0.0.0"
FirewallRuleName = "AllowAll"
}
$targetServer | New-AzSqlServerFirewallRule @parameters
$targetServer
# Create two sample databases to execute jobs against
$parameters = @{
ResourceGroupName = $resourceGroupName
ServerName = $targetServerName
DatabaseName = "database1"
}
$db1 = New-AzSqlDatabase @parameters
$db1
$parameters = @{
ResourceGroupName = $resourceGroupName
ServerName = $targetServerName
DatabaseName = "database2"
}
$db2 = New-AzSqlDatabase @parameters
$db2
エラスティック ジョブ エージェントを作成する
エラスティック ジョブ エージェントは、ジョブを作成、実行、および管理するための Azure リソースです。 エージェントは、スケジュールに基づいて、または 1 回だけのジョブとして、ジョブを実行します。 エラスティック ジョブのすべての日付と時刻には、UTC タイム ゾーンが適用されます。
New-AzSqlElasticJobAgent コマンドレットを実行するには、Azure SQL Database のデータベースが既に存在する必要があるため、resourceGroupName
、serverName
、および databaseName
のすべてのパラメーターが既存のリソースを指している必要があります。 同様に、 Set-AzSqlElasticJobAgent を使用してエラスティック ジョブ エージェントを変更できます。
ユーザー割り当てマネージド ID で Microsoft Entra 認証を使用して新しいエラスティック ジョブ エージェントを作成するには、次の New-AzSqlElasticJobAgent
の IdentityType
と IdentityID
の引数を使用します。
Write-Output "Creating job agent..."
$agentName = Read-Host "Please enter a name for your new elastic job agent"
$parameters = @{
Name = $agentName
IdentityType = "UserAssigned"
IdentityID = "/subscriptions/abcd1234-caaf-4ba9-875d-f1234/resourceGroups/contoso-jobDemoRG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/contoso-UMI"
}
$jobAgent = $jobDatabase | New-AzSqlElasticJobAgent @parameters
$jobAgent
データベース スコープの資格情報を使用して新しいエラスティック ジョブ エージェントを作成する場合は、IdentityType
IdentityID
は提供されません。
ジョブ認証を作成する
エラスティック ジョブ エージェントは、各ターゲット サーバーまたはデータベースに対して認証可能である必要があります。
「ジョブ エージェント認証の作成」で説明されているように、次の手順を実行します。
- ユーザー割り当てマネージド ID (UMI) にマップされたデータベース ユーザーを使用して、ターゲット サーバー/データベースに対する認証を行います。
- Microsoft Entra 認証 (旧称 Azure Active Directory) で UMI を使用することをお勧めします。 PowerShell コマンドレットに、UMI を使用した Microsoft Entra 認証をサポートするための新しい引数が追加されました。
- これは、推奨されている認証方法です。
- 各データベースのデータベース スコープの資格情報にマップされたデータベース ユーザーを使用します。
- 以前は、データベース スコープの資格情報が、エラスティック ジョブ エージェントがターゲットに対して認証するための唯一のオプションでした。
ターゲットへの認証に UMI で Microsoft Entra 認証を使用する
ユーザー割り当てマネージド ID (UMI) に対する Microsoft Entra (旧称 Azure Active Directory) 認証の推奨される方法を使用するには、次の手順に従います。 エラスティック ジョブ エージェントは、Entra 認証を介して目的のターゲット論理サーバー/データベースに接続します。
ログイン ユーザーとデータベース ユーザーに加えて、次のスクリプトに GRANT
コマンドが追加されていることに注意してください。 これらのアクセス許可は、このサンプル ジョブ用に選択したスクリプトに必要です。 ジョブには、異なるアクセス許可が必要な場合があります。 この例では、ターゲット データベースに新しいテーブルを作成するため、正常に実行するには各ターゲット データベースのデータベース ユーザーに適切なアクセス許可が必要です。
各ターゲット サーバー/データベースで、UMI にマップされた包含ユーザーを作成します。
- エラスティック ジョブに論理サーバーまたはプール ターゲットがある場合は、ターゲット論理サーバーの
master
データベース内の UMI にマップされた包含ユーザーを作成する必要があります。 - たとえば、
job-agent-UMI
という名前のユーザー割り当てマネージド ID (UMI) に基づいて、包含データベース ログインをmaster
データベースに作成し、ユーザー データベース内のユーザーを作成します。
$targetServer = '<target server name>'
$adminLogin = '<username>'
$adminPassword = '<password>'
# For the target logical server, in the master database
# Create the login named [job-agent-UMI] based on the UMI [job-agent-UMI], and a user
$params = @{
'database' = 'master'
'serverInstance' = $targetServer.ServerName + '.database.windows.net'
'username' = $adminLogin
'password' = $adminPassword
'outputSqlErrors' = $true
'query' = 'CREATE LOGIN [job-agent-UMI] FROM EXTERNAL PROVIDER;'
}
Invoke-SqlCmd @params
$params.query = "CREATE USER [job-agent-UMI] FROM LOGIN [job-agent-UMI]"
Invoke-SqlCmd @params
# For each target database in the target logical server
# Create a database user from the job-agent-UMI login
$targetDatabases = @( $db1.DatabaseName, $Db2.DatabaseName )
$createJobUserScript = "CREATE USER [job-agent-UMI] FROM LOGIN [job-agent-UMI]"
# Grant permissions as necessary. For example ALTER and CREATE TABLE:
$grantAlterSchemaScript = "GRANT ALTER ON SCHEMA::dbo TO [job-agent-UMI]"
$grantCreateScript = "GRANT CREATE TABLE TO [job-agent-UMI]"
$targetDatabases | % {
$params.database = $_
$params.query = $createJobUserScript
Invoke-SqlCmd @params
$params.query = $grantAlterSchemaScript
Invoke-SqlCmd @params
$params.query = $grantCreateScript
Invoke-SqlCmd @params
}
ターゲットへの認証にデータベース スコープの資格情報を使用する
ジョブ エージェントは、実行時にターゲット グループによって指定された資格情報を使用してスクリプトを実行します。 これらのデータベース スコープ資格情報は、サーバーまたはエラスティック プールのいずれかがターゲット グループ メンバー タイプとして使用されているときに master
データベースに接続してサーバーまたはエラスティック プール内のすべてのデータベースを検出するためにも使用されます。
データベース スコープ資格情報はジョブ データベースに作成する必要があります。 すべてのターゲット データベースには、ジョブが正常に完了するのに十分なアクセス許可を持つログインが必要です。
画像内の資格情報に加えて、次のスクリプトに GRANT
コマンドが追加されていることに注意してください。 これらのアクセス許可は、このサンプル ジョブ用に選択したスクリプトに必要です。 ジョブには、異なるアクセス許可が必要な場合があります。 この例では、ターゲット データベースに新しいテーブルを作成するため、正常に実行するには各ターゲット データベースのデータベース ユーザーに適切なアクセス許可が必要です。
各ターゲット サーバー/データベースのログイン/ユーザーには、ジョブ ユーザーのデータベース スコープ資格情報の ID と同じ名前と、ジョブ ユーザーのデータベース スコープ資格情報と同じパスワードが必要です。 PowerShell スクリプトで <strong jobuser password here>
を使用する場合は、全体で同じパスワードを使用します。
次の例では、データベース スコープの資格情報を使用します。 必要なジョブ資格情報を (ジョブ データベース内に) 作成するには、SQL 認証を使用してターゲット サーバー/データベースに接続する次のスクリプトを実行します。
# For the target logical server, in the master database
# Create the master user login, master user, and job user login
$targetServer = '<target server name>'
$adminLogin = '<username>'
$adminPassword = '<password>'
$params = @{
'database' = 'master'
'serverInstance' = $targetServer.ServerName + '.database.windows.net'
'username' = $adminLogin
'password' = $adminPassword
'outputSqlErrors' = $true
'query' = 'CREATE LOGIN adminuser WITH PASSWORD=''<strong adminuser password here>'''
}
Invoke-SqlCmd @params
$params.query = "CREATE USER adminuser FROM LOGIN adminuser"
Invoke-SqlCmd @params
$params.query = 'CREATE LOGIN jobuser WITH PASSWORD=''<strong jobuser password here>'''
Invoke-SqlCmd @params
# For each target database in the target logical server
# Create the jobuser from jobuser login and check permission for script execution
$targetDatabases = @( $db1.DatabaseName, $Db2.DatabaseName )
$createJobUserScript = "CREATE USER jobuser FROM LOGIN jobuser"
# Grant permissions as necessary. For example ALTER and CREATE TABLE:
$grantAlterSchemaScript = "GRANT ALTER ON SCHEMA::dbo TO jobuser"
$grantCreateScript = "GRANT CREATE TABLE TO jobuser"
$targetDatabases | % {
$params.database = $_
$params.query = $createJobUserScript
Invoke-SqlCmd @params
$params.query = $grantAlterSchemaScript
Invoke-SqlCmd @params
$params.query = $grantCreateScript
Invoke-SqlCmd @params
}
# Create job credential in job database for admin user
Write-Output "Creating job credentials..."
$loginPasswordSecure = (ConvertTo-SecureString -String '<strong jobuser password here>' -AsPlainText -Force)
$loginadminuserPasswordSecure = (ConvertTo-SecureString -String '<strong adminuser password here>' -AsPlainText -Force)
$adminCred = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList "adminuser", $loginadminuserPasswordSecure
$adminCred = $jobAgent | New-AzSqlElasticJobCredential -Name "adminuser" -Credential $adminCred
$jobCred = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList "jobuser", $loginPasswordSecure
$jobCred = $jobAgent | New-AzSqlElasticJobCredential -Name "jobuser" -Credential $jobCred
ターゲット サーバーとデータベースを定義する
ターゲット グループは、ジョブ ステップによって実行される 1 つまたは複数のデータベースのセットを定義します。
次のスニペットは、serverGroup
と serverGroupExcludingDb2
の 2 つのターゲット グループを作成します serverGroup
では、実行時にサーバー上に存在するすべてのデータベースがターゲットになります。serverGroupExcludingDb2
では、TargetDb2
を除くサーバー上のすべてのデータベースがターゲットになります。
Write-Output "Creating test target groups..."
# create ServerGroup target group
$serverGroup = $jobAgent | New-AzSqlElasticJobTargetGroup -Name 'ServerGroup'
$serverGroup | Add-AzSqlElasticJobTarget -ServerName $targetServerName -RefreshCredentialName $adminCred.CredentialName
# create ServerGroup with an exclusion of db2
$serverGroupExcludingDb2 = $jobAgent | New-AzSqlElasticJobTargetGroup -Name 'ServerGroupExcludingDb2'
$serverGroupExcludingDb2 | Add-AzSqlElasticJobTarget -ServerName $targetServerName -RefreshCredentialName $adminCred.CredentialName
$serverGroupExcludingDb2 | Add-AzSqlElasticJobTarget -ServerName $targetServerName -Database $db2.DatabaseName -Exclude
ジョブとステップを作成する
この例では、1 つのジョブと、そのジョブを実行するための 2 つのジョブ ステップを定義します。 最初のジョブ ステップ (step1
) では、ターゲット グループ Step1Table
内のすべてのデータベースに新しいテーブル (ServerGroup
) を作成します。 2 番目のジョブ ステップ (step2
) では、TargetDb2
を除くすべてのデータベースに新しいテーブル (Step2Table
) を作成します。これは、事前に定義されたターゲット グループがテーブルを除外するように指定されているためです。
Write-Output "Creating a new job..."
$jobName = "Job1"
$job = $jobAgent | New-AzSqlElasticJob -Name $jobName -RunOnce
$job
Write-Output "Creating job steps..."
$sqlText1 = "IF NOT EXISTS (SELECT * FROM sys.tables WHERE object_id = object_id('Step1Table')) CREATE TABLE [dbo].[Step1Table]([TestId] [int] NOT NULL);"
$sqlText2 = "IF NOT EXISTS (SELECT * FROM sys.tables WHERE object_id = object_id('Step2Table')) CREATE TABLE [dbo].[Step2Table]([TestId] [int] NOT NULL);"
$job | Add-AzSqlElasticJobStep -Name "step1" -TargetGroupName $serverGroup.TargetGroupName -CredentialName $jobCred.CredentialName -CommandText $sqlText1
$job | Add-AzSqlElasticJobStep -Name "step2" -TargetGroupName $serverGroupExcludingDb2.TargetGroupName -CredentialName $jobCred.CredentialName -CommandText $sqlText2
ジョブの実行
ジョブをすぐに開始するには、次のコマンドを実行します。
Write-Output "Start a new execution of the job..."
$jobExecution = $job | Start-AzSqlElasticJob
$jobExecution
正常に完了すると、TargetDb1
に新しいテーブルが 2 つ、TargetDb2
に新しいテーブルが 1 つだけ表示されます。
ジョブを後で実行するようにスケジュールすることもできます。
重要
エラスティック ジョブのすべての開始時刻は UTC タイム ゾーンが適用されます。
特定の時刻にジョブを実行するようにスケジュールを設定するには、次のコマンドを実行します。
# run every hour starting from now
$job | Set-AzSqlElasticJob -IntervalType Hour -IntervalCount 1 -StartTime (Get-Date) -Enable
ジョブの実行状態を監視する
次のスニペットを実行すると、ジョブの実行の詳細を取得できます。
# get the latest 10 executions run
$jobAgent | Get-AzSqlElasticJobExecution -Count 10
# get the job step execution details
$jobExecution | Get-AzSqlElasticJobStepExecution
# get the job target execution details
$jobExecution | Get-AzSqlElasticJobTargetExecution -Count 2
可能なジョブの実行状態を次の表に示します。
State | 説明 |
---|---|
Created | ジョブの実行は作成されたばかりで、まだ進行中ではありません。 |
InProgress | ジョブの実行は現在進行中です。 |
WaitingForRetry | ジョブ実行はそのアクションを完了できず、再試行を待機しています。 |
Succeeded | ジョブの実行は正常に完了しました。 |
SucceededWithSkipped | ジョブの実行は正常に完了しましたが、その子の一部がスキップされました。 |
Failed | ジョブの実行は失敗し、再試行回数の上限に達しました。 |
TimedOut | ジョブの実行はタイムアウトしました。 |
Canceled | ジョブの実行は取り消されました。 |
Skipped | 同じジョブ手順の別の実行が同じターゲットに対して既に実行されていたため、ジョブの実行はスキップされました。 |
WaitingForChildJobExecutions | ジョブの実行は、その子の実行が完了するまで待機しています。 |
リソースをクリーンアップする
リソース グループを削除して、このチュートリアルで作成した Azure リソースを削除します。
ヒント
引き続きこれらのジョブを使用する場合は、この記事で作成したリソースをクリーンアップしないでください。
Remove-AzResourceGroup -ResourceGroupName $resourceGroupName