Q: An in-place database schema migration task fails halfway through a playbook. How do you use Ansible block, rescue, and always directives to implement automated rollback runbooks and send alert webhooks?
Implement try-catch-finally error handling in Ansible using block, rescue, and always. When a critical database migration task in a block fails, the rescue section triggers automated rollbacks, and always executes telemetry and notification webhooks.
Want to master this scenario in a live sandbox? KodeKloud's CKA & CKAD Hands-On Certification Track covers this exact problem with hands-on terminal drills.
🛠️ Production Runbook & Step-by-Step Resolution
Encapsulate Risky Tasks in a block
Group the forward migration operations inside a logical block structure:
- name: Database Schema Migration Blockblock:- name: Create database snapshot- name: Apply Flyway / Liquibase database schema migration- name: Run post-migration sanity tests
Trigger Automated Rollback with rescue
The rescue section executes exclusively if any task inside the preceding block returns an error:
rescue:- name: Revert schema to previous migration versioncommand: /opt/bin/migrate -rollback- name: Post alert to Slack incident channeluri: url="{{ slack_webhook }}" method=POST body_format=json ...- name: Fail explicitly to halt deployment pipelinefail: msg='Schema migration failed! Automated rollback successfully executed.'
Guarantee Cleanup Operations with always
Tasks declared in always run unconditionally regardless of whether the block succeeded or failed:
always:- name: Remove temporary lock files and credentialsfile: path=/tmp/db_migration.lock state=absent- name: Publish execution metric to CloudWatch / Datadog
- Ansible's 'block' groups tasks logically, functioning as a 'try' block in software engineering.
- The 'rescue' block functions as a 'catch' handler, executing only if any task inside the block fails.
- Use rescue to trigger automated rollbacks (e.g. reverting DB schemas, restoring config backups) and paging SREs via webhook.
- The 'always' block functions as a 'finally' handler, executing unconditionally regardless of success or failure.
- Use always to clean up temporary credential files, release mutex lockfiles, and export pipeline metrics.
- Always include an explicit 'fail' task at the end of rescue to ensure the CI/CD pipeline registers the build failure.
Senior hiring managers and bar raisers evaluate how you prioritize during outages. Avoid these common anti-patterns:
- Omitting a fail module task at the end of the rescue block If all tasks in rescue succeed, Ansible considers the play successful (green), allowing broken builds to progress downstream.
- Attempting rollbacks using ignore_errors: yes Blindly ignores failures and proceeds with dependent tasks, corrupting live database states.
- Neglecting lockfile cleanup in the always block Leaves orphaned mutex lockfiles on target hosts, preventing future deployments until manual SSH intervention.