Créer et gérer des tâches élastiques à l’aide de PowerShell

S’applique à Azure SQL Database

Cet article fournit un tutoriel et des exemples pour commencer à travailler avec des tâches élastiques à l'aide de PowerShell. Les travaux élastique permettent l’exécution d’un ou plusieurs scripts Transact-SQL (T-SQL) en parallèle sur plusieurs bases de données.

Dans ce tutoriel complet, vous apprendrez les étapes nécessaires à l'exécution d'une requête sur plusieurs bases de données :

  • Créer un agent de tâche élastique
  • Créer des informations d’identification de travail afin que les travaux puissent exécuter des scripts sur ses cibles
  • Définir les cibles (serveurs, pools élastiques, bases de données) sur lesquelles vous voulez exécuter le travail
  • Créer des informations d'identification limitées à une base de données dans les bases de données cibles afin que l'agent se connecte et exécute des tâches
  • Créer un travail
  • Ajouter des étapes de travail à un travail
  • Démarrer l’exécution d’un travail
  • Surveiller un travail

Prérequis

Les tâches de base de données élastique ont un ensemble d'applets de commande PowerShell.

Ces cmdlets ont été mises à jour en novembre 2023.

Installer les dernières applets de commande de tâches élastiques

Si vous n’avez pas d’abonnement Azure, créez un compte gratuit avant de commencer.

Si ce n'est pas déjà fait, installez les dernières versions des modules Az.Sql et SqlServer. Exécutez les commandes suivantes dans PowerShell avec un accès administrateur.

# 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

Pour plus d’informations, consultez Installer le module SQL Server PowerShell.

Créer les ressources nécessaires

La création d'un agent de tâches élastiques nécessite une base de données (S1 ou supérieure) à utiliser comme base de données de tâches élastiques.

Le script suivant crée un nouveau groupe de ressources, un nouveau serveur et une nouvelle base de données à utiliser comme base de données de tâches élastiques. Le deuxième script crée un deuxième serveur avec deux bases de données vides sur lesquelles exécuter les travaux.

Les tâches élastiques n'ont aucune exigence d'affectation de noms. C'est la raison pour laquelle vous pouvez utiliser n'importe quelle convention d'affectation de noms, tant qu'elle est conforme aux conditions requises pour Azure. Si vous avez déjà créé une base de données vide sur le serveur comme base de données de tâches élastique, passez à Créer l'agent de tâche élastique.

La configuration d'une règle de pare-feu avec New-AzSqlServerFirewallRule n'est pas nécessaire lors de l'utilisation d'un point de terminaison privé de tâches élastiques.

# 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

Créer l'agent de la tâche élastique

Un agent de tâche élastique est une ressource Azure permettant de créer, exécuter et gérer des tâches. L’agent exécute les travaux selon un calendrier ou de manière ponctuelle. Toutes les dates et heures mentionnées pour les tâches élastiques se rapportent au fuseau horaire UTC.

La cmdlet New-AzSqlElasticJobAgent nécessite l'existence d'une base de données dans Azure SQL Database, de sorte que les paramètres resourceGroupName, serverName, et databaseName doivent tous pointer vers des ressources existantes. De même, Set-AzSqlElasticJobAgent peut être utilisé pour modifier l'agent de tâche élastique.

Pour créer un agent de tâche élastique à l’aide de l’authentification Microsoft Entra avec une identité managée affectée par l’utilisateur, utilisez les arguments IdentityType et IdentityID de New-AzSqlElasticJobAgent :

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

Pour créer un agent de tâche élastique à l’aide d’informations d’identification étendues à la base de données, les arguments IdentityType et IdentityID ne sont pas fournis.

Créer l'authentification de la tâche

L'agent de tâche élastique doit être en mesure de s'authentifier auprès de chaque serveur ou base de données cible.

Comme indiqué dans Créer l'authentification de l'agent de projet :

Utiliser l’authentification Microsoft Entra avec un UMI pour l’authentification des cibles

Pour utiliser la méthode recommandée de l’authentification Microsoft Entra (anciennement Azure Active Directory) à une identité managée affectée par l’utilisateur, procédez comme suit. L'agent de tâche élastique se connecte au ou aux serveurs logiques/bases de données cibles souhaités via l'authentification Entra.

En plus des utilisateurs de connexion et de base de données, notez l’ajout des GRANT commandes dans le script suivant. Ces autorisations sont requises pour le script que nous avons choisi pour cet exemple de travail. Vos tâches peuvent nécessiter des autorisations différentes. Comme l'exemple crée une nouvelle table dans les bases de données ciblées, l'utilisateur de la base de données dans chaque base de données cible doit disposer des autorisations appropriées pour que l'exécution soit réussie.

Dans chacun des serveurs/bases de données cibles, créez un utilisateur autonome mappé à l’UMI.

  • Si la tâche élastique a des cibles de serveur logique ou de pool, vous devez créer l’utilisateur contenu mappé à l’UMI dans la base de données master du serveur logique cible.
  • Par exemple, pour créer une connexion de base de données autonome dans la base de données master et un utilisateur dans la base de données utilisateur, en fonction de l’identité managée affectée par l’utilisateur (UMI) nommée job-agent-UMI :
$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
}

Utiliser des informations d'identification limitées à la base de données pour l'authentification aux cibles

Les agents de projet utilisent les informations d'identification spécifiées par le groupe cible lors de l'exécution et l'exécution de scripts. Ces informations d'identification limitées à la base de données sont également utilisées pour se connecter à la base de données master afin de découvrir toutes les bases de données d'un serveur ou d'un pool élastique, lorsque l'un ou l'autre de ces éléments est utilisé comme type de membre du groupe cible.

Ces informations d'identification limitées à la base de données doivent être créées dans la base de données des tâches. Toutes les bases de données cibles doivent avoir une connexion disposant d’autorisations suffisantes pour que le travail s’exécute avec succès.

Outre les informations d'identification de l'image, notez l'ajout des commandes GRANT dans le script suivant. Ces autorisations sont requises pour le script que nous avons choisi pour cet exemple de travail. Vos tâches peuvent nécessiter des autorisations différentes. Comme l'exemple crée une nouvelle table dans les bases de données ciblées, l'utilisateur de la base de données dans chaque base de données cible doit disposer des autorisations appropriées pour que l'exécution soit réussie.

La connexion/l'utilisateur sur chaque serveur/base de données cible doit avoir le même nom que l'identité des informations d'identification limitées à la base de données pour l'utilisateur de la tâche et le même mot de passe que les informations d'identification limitées à la base de données pour l'utilisateur de la tâche. Lorsque le script PowerShell utilise <strong jobuser password here>, utilisez le même mot de passe.

L'exemple suivant utilise des informations d'identification limitées à la base de données. Pour créer les informations d'identification de projet requises (dans la base de données de tâches), exécutez le script suivant, qui utilise l'authentification SQL pour se connecter au ou aux serveurs cibles/bases de données :

# 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

Définir des serveurs et des bases de données cibles

Un groupe cible définit l’ensemble de base de données sur lequel une étape de travail s’exécute.

L'extrait de code suivant crée deux groupes cibles : serverGroup et serverGroupExcludingDb2. serverGroup cible toutes les bases de données qui existent sur le serveur au moment de l'exécution, et serverGroupExcludingDb2 cible toutes les bases de données sur le serveur, à l'exception de 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

Créer un travail et une tâche

Cet exemple définit un travail et deux étapes de travail pour le travail à exécuter. La première étape de la tâche (step1) crée une nouvelle table (Step1Table) dans chaque base de données du groupe cible ServerGroup. La deuxième étape de la tâche (step2) crée une nouvelle table (Step2Table) dans chaque base de données, à l'exception de TargetDb2, car le groupe cible défini précédemment a spécifié de l'exclure.

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

Exécuter le travail

Pour démarrer le travail immédiatement, utilisez la commande suivante :

Write-Output "Start a new execution of the job..."
$jobExecution = $job | Start-AzSqlElasticJob
$jobExecution

Une fois l'opération réussie, vous devriez voir deux nouvelles tables dans TargetDb1, et une seule nouvelle table dans TargetDb2.

Vous pouvez aussi planifier le travail pour une exécution ultérieure.

Important

Toutes les heures de début dans les tâches élastiques se trouvent dans le fuseau horaire UTC.

Pour planifier l’exécution ultérieure d’un travail, exécutez la commande suivante :

# run every hour starting from now
$job | Set-AzSqlElasticJob -IntervalType Hour -IntervalCount 1 -StartTime (Get-Date) -Enable

Surveiller l’état d’exécution des travaux

L’extrait de code suivant obtient les informations relatives au travail d’exécution :

# 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

Le tableau suivant répertorie les états d’exécution de travail possibles :

State Description
Créé le L’exécution du travail vient d’être créée et n’est pas encore en cours d’exécution.
InProgress L’exécution du travail est en cours.
WaitingForRetry L’exécution du travail n’a pas été en mesure de terminer son action et est en attente d’une nouvelle tentative.
Réussi L’exécution du travail a réussi.
SucceededWithSkipped L’exécution de la tâche s’est terminée avec succès, mais certains de ses enfants ont été ignorés.
Échec L’exécution du travail a échoué et a épuisé ses nouvelles tentatives.
TimedOut L’exécution du travail a expiré.
Canceled L’exécution du travail a été annulée.
Ignoré L’exécution du travail a été ignorée, car une autre exécution de la même étape du travail était déjà en cours d’exécution sur la même cible.
WaitingForChildJobExecutions L’exécution du travail attend que les exécutions de ses enfants se termine.

Nettoyer les ressources

Supprimez les ressources Azure créées dans ce tutoriel en supprimant le groupe de ressources.

Conseil

Si vous envisagez de continuer à utiliser ces travaux, ne nettoyez pas les ressources créées dans cet article.

Remove-AzResourceGroup -ResourceGroupName $resourceGroupName

Étape suivante