12.3 Azure Automation Runbooks, Alerts, and Troubleshooting Automated Tasks
Key Takeaways
- Azure Automation schedules PowerShell, Python, and graphical runbooks; the Automation account stores runbooks, credentials, variables, schedules, and modules, and runs on Azure workers or on-premises via Hybrid Runbook Worker
- Authenticate runbooks to Azure SQL with a system-assigned managed identity wherever possible - it eliminates secret rotation; service principals and stored credentials are the legacy alternative
- Configure alerts on automated tasks with metric alerts (numeric thresholds) and activity log alerts (control-plane events like a failed runbook job); action groups route notifications to email, webhook, Logic App, or Functions
- Common runbook failures are missing managed-identity permissions, private endpoint/firewall blocking the worker, timeouts, and stale module versions; diagnose via job streams and the activity log
- Choose Elastic Jobs for T-SQL across many Azure SQL Databases, SQL Server Agent for T-SQL/SSIS on MI or VM, and Azure Automation for non-T-SQL orchestration and cross-service workflows
Azure Automation: The Platform for Scheduled Tasks
Where Elastic Jobs handle T-SQL across many databases, Azure Automation is the general-purpose scheduler and orchestrator for any script in Azure. It is the right tool when the automation is not a single T-SQL batch - for example, calling Azure REST APIs, restarting a VM, copying blobs, rotating keys in Key Vault, or orchestrating a sequence of steps that touch more than one service. The DP-300 exam expects you to know what lives in an Automation account, how runbooks authenticate to SQL, and how to alert and troubleshoot.
An Azure Automation account is the container for everything automation-related. Inside it you find:
| Asset | Purpose |
|---|---|
| Runbooks | The scripts themselves - PowerShell, Python, or graphical (PowerShell Workflow / graphical authoring) |
| Credentials | Username/password pairs stored securely |
| Certificates | Certificates for service-principal auth |
| Variables | Named values (string, int, boolean, datetime) reused across runbooks; can be encrypted |
| Schedules | Time-based triggers (one-time or recurring) |
| Modules | PowerShell modules (Az.Accounts, Az.Sql, SqlServer, etc.) available to runbooks |
| Connections | Pre-defined connection objects (Azure classic, ARM) |
A runbook is a single script. Runbook types include:
- PowerShell - native PowerShell script; the most common.
- Python - Python 3 script; useful for teams with Python skills.
- Graphical - a visual flow designed in the portal; good for low-code orchestration and approval workflows.
- PowerShell Workflow - the older workflow-based type that supports checkpoints and parallelism; rarely chosen for new runbooks.
Hybrid Runbook Worker
By default, runbooks run on an Azure-hosted sandbox worker, which has outbound internet access but cannot reach on-premises resources or anything behind a private endpoint without extra configuration. A Hybrid Runbook Worker is a VM (Azure VM or on-premises) with the Hybrid Worker extension installed; runbooks targeted to a hybrid worker run on that VM and can reach whatever that VM can reach. The exam scenario that says "run a script that connects to an on-premises SQL Server" or "run a script against a database behind a private endpoint" points to a hybrid worker - the Azure sandbox cannot reach either.
Authenticating a Runbook to Azure SQL
The cleanest modern pattern is a system-assigned managed identity on the Automation account. The runbook acquires a token with Connect-AzAccount -Identity and uses it to run Azure cmdlets or to obtain a SQL access token. The SQL-side work is to provision the managed identity as a database user:
CREATE USER [myAutomationAccount] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [myAutomationAccount];
-- grant whatever the runbook needs
Then in the runbook, authenticate with the managed identity, acquire a token for https://database.windows.net, and connect with Invoke-Sqlcmd (from the SqlServer PowerShell module) using the access token:
Connect-AzAccount -Identity
$token = (Get-AzAccessToken -ResourceUrl 'https://database.windows.net').Token
Invoke-Sqlcmd -ServerInstance tcp:sql-prod.database.windows.net,1433 `
-Database SalesDB -AccessToken $token -Query 'SELECT @@VERSION'
The legacy pattern is an Automation Credential asset (username + password for a SQL login) or a service principal with a stored secret. Both still work, but the exam prefers managed identities because they eliminate secret rotation - a point worth citing explicitly in scenario answers.
Schedules and Variables
A schedule is a recurring or one-time trigger you link to a runbook with Register-AzAutomationScheduledRunbook (PowerShell) or via the portal. You can link multiple runbooks to one schedule, and a runbook can be linked to multiple schedules with different parameter sets. Variables are how you share configuration (server name, database name, retention days) across runbooks without editing scripts; mark sensitive values as encrypted when stored.
Alerts and Notifications on Database Tasks
DP-300 explicitly tests configure alerts and notifications on database tasks. Azure has two alert types that matter for automation:
- Metric alerts fire on numeric thresholds. For Azure SQL Database, useful metrics include
cpu_percent,storage_percent,deadlock,connection_successful(and its failed counterpart), andtempdb_data_file_size_percent. You set a threshold (e.g., cpu_percent > 80 for 5 minutes), an evaluation frequency, and an action group. - Activity log alerts fire on control-plane events - resource write operations, service health, recommendations, and (critically for this objective) Automation job status. You can alert whenever a runbook job fails (
Job status= Failed) or whenever a specific runbook completes.
An action group is the reusable delivery layer: a named set of one or more actions that fire when an alert triggers. Supported action types:
| Action | What it does |
|---|---|
| Email / SMS / push | Send a notification to a person or distribution list |
| Webhook | POST a JSON payload to an HTTP endpoint |
| Azure Function | Invoke a function (custom code) |
| Logic App | Trigger a Logic App workflow (approval, ticket creation, Teams post) |
| Automation runbook | Kick off a remediation runbook |
| ITSM | Create a ticket in a connected ITSM tool (ServiceNow, etc.) |
The pattern the exam rewards: create one action group per notification persona (e.g., DBA-on-call, ops-team-channel) and reuse it across multiple alerts, rather than defining ad-hoc recipients on every alert. Metric alerts on cpu_percent and storage_percent with a single DBA action group cover most day-to-day Azure SQL alerting.
Monitoring Automation Jobs
Every runbook execution is a job. You inspect jobs through:
- Job streams - PowerShell output, error, warning, and verbose streams captured per job.
Get-AzAutomationJobOutputandGet-AzAutomationJobStreamreturn the streams; in the portal, the job page shows them inline. - Job status - New, Running, Completed, Failed, Stopped, Suspended.
Get-AzAutomationJob -Status Failedlists recent failures. - Activity log - every Automation job write is recorded, so activity-log alerts on job status are the canonical way to alert on automation failures.
A robust pattern: a runbook wraps its real work in try/catch, writes a structured error to the verbose stream, and lets the job status reflect success/failure so the activity-log alert fires only on real failures (not on handled warnings).
You need a runbook to connect to an Azure SQL Database that is reachable only through a private endpoint inside a virtual network. The runbook must authenticate without storing any password. What is the correct setup?
Common Runbook Failures and How to Troubleshoot
The exam will show you a failing runbook and ask what is wrong. Most failures fall into five buckets:
| Symptom | Likely cause | Diagnostic step |
|---|---|---|
Connect-AzAccount -Identity returns a token error | Managed identity not enabled on the Automation account, or not granted access to the target | Confirm system-assigned identity is on; verify the identity exists as a user in the target database |
Login failed for user against SQL | SQL-side user for the managed identity or SQL login missing or lacks permissions | SELECT * FROM sys.database_principals and check role membership on the target |
Connection timeout or network path was not found | Private endpoint / firewall / NSG blocking the runbook worker | From a Hybrid Worker in the same VNet, test Test-NetConnection sql-prod.database.windows.net -Port 1433; confirm firewall rules on the logical server |
The job has been running longer than the allowed time | Runbook exceeded its per-job timeout (default varies by sandbox; Hybrid Workers have their own) | Split the work, raise the timeout, or optimize the script; long-running loops belong on a Hybrid Worker |
Could not load file or assembly 'Microsoft.SqlServer...' or cmdlet not found | Stale or missing PowerShell module version in the Automation account | Update the module (Az.Sql, SqlServer) under Modules; pin to a tested version |
| Runbook succeeds in test but fails on schedule | Parameter values differ between test and scheduled run | Verify parameters on the schedule-linked runbook; store shared values in Automation Variables |
A useful troubleshooting order: (1) open the failed job in the portal and read the error stream; (2) if the error is auth, check the identity and SQL user; (3) if the error is connectivity, test from the worker's network; (4) if the error is a missing cmdlet, update modules; (5) if intermittent, check the schedule's parameter set. The job streams and the activity log are your two primary evidence sources.
Module Version Gotchas
Azure Automation ships with a default set of modules, but those versions age. If a runbook calls a cmdlet that exists only in a newer Az.Sql (or SqlServer) module, the runbook fails with a "cmdlet not recognized" error. The fix is to update the module in the Automation account under Modules > Browse Gallery (or via Update-AzAutomationModule). Pinning to a specific module version prevents silent breakage when the platform updates a default module and changes a behavior. The exam tests this as a specific trap: a runbook that worked yesterday fails today after a module auto-update changed a parameter name.
When to Choose Azure Automation vs Elastic Jobs vs SQL Server Agent
The decision comes up repeatedly, so here is the consolidated guidance:
| Scenario | Right tool |
|---|---|
| Apply a T-SQL schema change to 200 Azure SQL Databases in a pool | Elastic Jobs |
Run UPDATE STATISTICS nightly on one Azure SQL Database | Azure Automation runbook (or a single-database Elastic Job) - SQL Agent is not available on single databases |
| Run a SQL Agent job that invokes an SSIS package on SQL MI | SQL Server Agent on the MI |
| Restart a VM, copy a blob, rotate a Key Vault key on a schedule | Azure Automation runbook |
| Run a PowerShell script that connects to an on-premises SQL Server | Azure Automation with a Hybrid Runbook Worker |
| Orchestrate a multi-step workflow: shrink log, back up, send email, update a ticket | Azure Automation (graphical runbook or PowerShell with Logic App action) |
The exam framing: T-SQL across many Azure SQL Databases is the only scenario that always points to Elastic Jobs. MI or VM + SQL Agent job type (T-SQL, SSIS, CmdExec, PowerShell subsystem) points to SQL Server Agent. Anything else - cross-service, non-T-SQL, on-premises, multi-step orchestration - points to Azure Automation.
Putting It Together: A Realistic Automated Task with Alerts
Consider a nightly runbook that backs up each tenant database to blob storage, deletes backups older than 30 days, and pages the on-call DBA if any step fails. The components:
- Automation account with a system-assigned managed identity granted
db_backupoperatoron each tenant database and Storage Blob Data Contributor on the storage account. - Runbook (PowerShell) that loops over databases, runs
BACKUP DATABASE ... TO URL, then deletes blobs older than 30 days usingRemove-AzStorageBlob. - Schedule linked to the runbook, recurring daily at 02:00.
- Action group "DBA-on-call" with an email recipient and a Logic App that posts to the on-call Teams channel.
- Activity log alert on
Job Status = Failedfor this runbook, using the action group above.
When a backup fails (e.g., a tenant database was dropped mid-loop, or storage throttled), the job stream records the specific error, the job status flips to Failed, and the activity-log alert fires the action group, which emails the DBA and posts to Teams. The next morning, the DBA reads the job stream, fixes the root cause, and either re-runs the runbook on demand or waits for the next scheduled run. This is the end-to-end pattern the exam is really testing: not a single cmdlet, but the integration of Automation, managed identity, schedules, action groups, and activity-log alerts into one reliable, observable automated task.
You want to be notified by email whenever a specific Azure Automation runbook job ends in a Failed state. Which combination correctly delivers that notification?
A runbook that ran successfully for weeks now fails immediately with an error that a cmdlet is not recognized. The runbook code has not changed. What is the most likely cause and the correct fix?