Skip to main content
RunBook Academy

← All checklists in Ansible

As neededDeployment

Checklist: Canary validation

19 items ·15 critical ·3 warn ·1 info

Run this after the canary has taken the change and before the rolling deployment starts. It is the decision point: everything above the rollout depends on somebody being able to say that one real host took this change and is demonstrably fine.

The commands assume a canary called web01.example.com in the web group. Substitute your own. The uri checks run from the controller with -c local so that the request comes from off the host, which is the point.

What a failure means

A canary finding is not a delay, it is the canary doing its job. The correct response to any critical failure here is to stop the rollout, fix the change, and run the canary again from the top - not to fix it on the canary by hand and proceed, which produces a fleet configured by the playbook and one host configured by you.

The warn items are about whether the rollout will be tidy. They do not invalidate the canary result.

Access this needs

Every command reads. setup, service_facts and uri gather or fetch; --check --diff reports without changing. Two of them are worth naming:

The playbook runs at applied-cleanly and idempotent are real runs, not check-mode runs - they are what puts the change on the canary and then proves it converged. They change the canary and nothing else, because --limit restricts them to it, which is exactly why the limit item comes first.

The journalctl invocation goes through the command module. It reads, but the command module will run whatever you give it, so adapt that item with care.

Where the evidence goes

The recap lines, the uri results and the soak period go in the change record. So does the person who decided the canary passed - because “the canary was green” is a judgement about criteria that were written down beforehand, and the record should show both the criteria and who applied them.

Sign-off

  • Canary run by: ____________ Time: ___________
  • Soak start: _______________ Soak end: _______
  • Promotion approved by: ____ Time: ___________

Critical15 items

  1. ansible -i inventories/production web01.example.com,web02.example.com -m ansible.builtin.setup -a 'filter=ansible_distribution*,ansible_kernel' --one-line
  2. ansible-playbook -i inventories/production playbooks/deploy.yml --limit web01.example.com --list-hosts
  3. ansible-playbook -i inventories/production playbooks/deploy.yml --limit web01.example.com | awk '/failed=[1-9]|unreachable=[1-9]/ {print "FINDING: " $0}'
  4. ansible-playbook -i inventories/production playbooks/deploy.yml --limit web01.example.com | awk '/changed=/ && !/changed=0/ {print "NOT IDEMPOTENT: " $0}'
  5. ansible -i inventories/production web01.example.com -m ansible.builtin.service_facts --one-line
  6. ansible -i inventories/production localhost -c local -m ansible.builtin.uri -a 'url=https://web01.example.com/health status_code=200 timeout=10'
  7. ansible -i inventories/production localhost -c local -m ansible.builtin.uri -a 'url=https://web01.example.com/version return_content=yes status_code=200' | grep -o '"content": "[^"]*"'
  8. ansible -i inventories/production web01.example.com -m ansible.builtin.command -a 'journalctl -u app --since -15min -p err --no-pager' --one-line
  9. ansible -i inventories/production web01.example.com -m ansible.builtin.setup -a 'filter=ansible_uptime_seconds' --one-line

Warning3 items

  1. ansible-playbook -i inventories/production playbooks/deploy.yml --limit web01.example.com --check --diff
  2. ansible -i inventories/production web01.example.com,web02.example.com -m ansible.builtin.setup -a 'filter=ansible_memfree_mb,ansible_mounts' --one-line
  3. ansible-playbook -i inventories/production playbooks/deploy.yml --limit 'web:!web01.example.com' --list-hosts

Info1 item