Skip to main content

Implementing Advanced Patterns

1. Using Delegation Strategies

Strategy Description Use Case Example
delegate_to Runs the task on a different host than the one specified in the play's hosts When you need to execute a task on a specific host, not the target host
- name: "Run command on specific host"
  command: whoami
  delegate_to: web01
delegate_facts Collects facts from the delegated host and makes them available in the play's context When you want to use facts from a different host in your playbook
- name: "Gather facts from delegated host"
  setup:
  delegate_to: db01
  delegate_facts: yes
delegate_to + delegate_facts Combines delegation and fact gathering for complex workflows When you need to run tasks on a host and use its facts in subsequent tasks
- name: "Run task on host and gather facts"
  command: echo {{ ansible_fqdn }}
  delegate_to: app01
  delegate_facts: yes
Note: delegate_to does not change the inventory or target hosts for other tasks in the play.
Warning: Ensure that the delegated host is reachable and has appropriate permissions to execute the task.

2. Implementing Rolling Updates

Parameter Description Default Value Notes
batch_size Number of hosts to update at once 1 Can be a percentage (e.g., 25%) or integer
delay Seconds to wait between batches 0 Useful for monitoring or cooldown periods
max_fail_percentage Maximum percentage of hosts that can fail before aborting 0 Set to 0 to stop on any failure
serial Number of hosts to update in serial mode 1 Overrides batch_size if set

Example: Rolling Update with Batch Size

- name: Update web servers with rolling updates
  hosts: webservers
  vars:
    batch_size: 25%
  tasks:
    - name: Deploy new version
      ansible.builtin.copy:
        src: app.tar.gz
        dest: /opt/app/app.tar.gz

Example: Rolling Update with Delay

- name: Update database servers with delay
  hosts: databases
  vars:
    delay: 30
  tasks:
    - name: Restart service
      ansible.builtin.systemd:
        name: mysql
        state: restarted
Note: The rolling update strategy is ideal for minimizing downtime during updates. Ensure that your application can handle concurrent access from both old and new versions.
Warning: Setting max_fail_percentage too high may lead to partial rollouts and inconsistent states across hosts.

3. Implementing Blue-Green Deployments

Blue-green deployments are a deployment strategy that reduces downtime and risk by running two identical production environments. One environment (blue) is active, while the other (green) is idle. When a new version is ready, it's deployed to the idle environment, and traffic is switched from blue to green.

Component Description Notes
blue_environment ansible-playbook deploy-blue.yml Active environment with current version
green_environment ansible-playbook deploy-green.yml Idle environment for new version
traffic_switch ansible-playbook switch-traffic.yml Switches traffic from blue to green

Example: Blue-Green Deployment Setup

# deploy-blue.yml
- hosts: web_servers
  vars:
    environment: blue
  tasks:
    - name: Deploy application to blue environment
      ansible.builtin.copy:
        src: app.tar.gz
        dest: /opt/app/app.tar.gz
        mode: '0644'

Example: Switching Traffic to Green

# switch-traffic.yml
- hosts: load_balancer
  tasks:
    - name: Update load balancer to point to green servers
      ansible.builtin.template:
        src: lb_config.j2
        dest: /etc/nginx/conf.d/app.conf
Note: Ensure both environments have identical infrastructure and configurations to avoid inconsistencies during deployment.

Benefits of Blue-Green Deployment

  • Zero Downtime - Traffic is switched instantly.
  • Rollback Simplicity - Easy to switch back if issues arise.
  • Testing - New version can be tested in isolation before going live.

Blue-Green vs Other Deployment Strategies

  • Blue-Green: Two environments, zero downtime
  • Rolling Update: Gradual replacement of instances, some downtime
  • Recreate: Full shutdown and restart, full downtime

4. Using Canary Deployments

Canary deployments in Ansible involve gradually rolling out changes to a subset of servers before deploying to the entire fleet. This approach minimizes risk by allowing you to observe behavior on a small scale before full rollout.

Parameter Description Example
canary_hosts Hosts to include in the canary group webservers:canary_hosts
canary_percentage Percentage of hosts to deploy to in canary phase 10
canary_delay Time (in seconds) to wait between canary phases 30

Example: Canary Deployment Playbook

---
- name: Canary deployment for web app
  hosts: webservers
  vars:
    canary_hosts: 10%
    canary_delay: 30
  tasks:
    - name: Deploy to canary hosts first
      ansible.builtin.copy:
        src: app.tar.gz
        dest: /opt/app.tar.gz
      when: inventory_hostname in groups['canary_hosts']

    - name: Restart service on canary hosts
      ansible.builtin.systemd:
        name: webapp.service
        state: restarted
      when: inventory_hostname in groups['canary_hosts']

    - name: Wait before full rollout
      ansible.builtin.wait_for:
        timeout: "{{ canary_delay }}"
Note: Ensure that your inventory groups are properly defined to support canary host selection.

Canary Deployment Steps

  • Define a subset of hosts to be part of the canary group
  • Deploy changes to canary hosts first
  • Monitor for any issues or performance degradation
  • Gradually expand deployment to remaining hosts

5. Implementing Zero-Downtime Deployments

Zero-downtime deployments ensure that applications remain available during updates. Ansible provides several strategies to achieve this, particularly through load balancing and rolling updates.

Strategy Description Use Case
Rolling Updates Update instances one at a time, ensuring that at least one instance remains active. Web servers, microservices
Blue-Green Deployment Run two identical production environments (blue and green). Switch traffic to the new version once deployed. High availability systems
Canary Releases Deploy to a small subset of instances first, then gradually increase traffic. Testing new features with real users

Example: Rolling Update with Load Balancer

- name: Perform rolling update
  hosts: web_servers
  vars:
    max_fail_percentage: 10
  serial: 2
  tasks:
    - name: Deploy new version
      ansible.builtin.copy:
        src: app.tar.gz
        dest: /opt/app/app.tar.gz

    - name: Restart service
      ansible.builtin.systemd:
        name: app.service
        state: restarted

Example: Blue-Green Deployment

- name: Switch to new environment
  hosts: load_balancer
  tasks:
    - name: Update load balancer to point to new servers
      ansible.builtin.command: |
        haproxy -f /etc/haproxy/haproxy.cfg
Note: Ensure that your load balancer supports dynamic configuration changes and that health checks are in place to detect failed instances.

Best Practices for Zero-Downtime Deployment

  • Use serial execution to control the number of instances updated at once.
  • Implement health checks before and after deployment to ensure service stability.
  • Use load balancers that support graceful draining of connections during updates.

6. Using Pre and Post Tasks

Example: Using pre_task and post_task

---
- name: Example playbook with pre and post tasks
  hosts: all
  pre_tasks:
    - name: Ensure log directory exists
      file:
        path: /var/log/myapp
        state: directory
        mode: '0755'

  tasks:
    - name: Deploy application
      copy:
        src: app.py
        dest: /opt/myapp/app.py
        mode: '0755'

  post_tasks:
    - name: Restart service
      systemd:
        name: myapp.service
        state: restarted
Property Description Values
pre_tasks Tasks to run before the main tasks List of task definitions
post_tasks Tasks to run after the main tasks List of task definitions
Note: pre_tasks and post_tasks are executed in the order they appear, and can include any valid task type.
Warning: These tasks run once per host, not once per play.

Key Points

  • pre_tasks run before the main tasks in a play
  • post_tasks run after the main tasks in a play
  • Both pre_tasks and post_tasks support all task features (handlers, loops, conditionals)
  • Useful for setup and cleanup operations

7. Implementing Health Checks

Check Type Description Configuration Notes
http HTTP health check { "url": "http://localhost:8080/health", "status_code": 200 } Useful for web services
tcp TCP port check { "host": "localhost", "port": 8080 } Verifies port availability
file File existence check { "path": "/var/run/app.pid" } Checks for process files
command Command execution check { "cmd": "pgrep app" } Runs shell command and checks exit code

Example: HTTP Health Check

- name: Check web service health
  uri:
    url: http://localhost:8080/health
    status_code: 200
  register: health_result
  retries: 3
  delay: 5

Example: TCP Port Check

- name: Verify application port
  wait_for:
    host: localhost
    port: 8080
    timeout: 30

Example: File Existence Check

- name: Check if process file exists
  stat:
    path: /var/run/app.pid
  register: pid_file
- name: Fail if file does not exist
  assert:
    that: pid_file.stat.exists
    fail_msg: "Process file missing"

Example: Command Execution Check

- name: Verify application is running
  command: pgrep app
  register: process_check
  ignore_errors: true
- name: Fail if no process found
  assert:
    that: process_check.rc == 0
    fail_msg: "Application not running"

8. Using Smoke Tests

Smoke tests in Ansible are used to quickly verify that a system or service is functioning correctly after deployment. These tests typically run early in the deployment pipeline to catch obvious issues.

Test Type Description Example
HTTP Status Check Verifies that a web service returns an expected HTTP status code. curl -f http://example.com/health
Service Availability Checks that a service is running and accessible.
ansible.builtin.uri:
  url: http://localhost:8080
  status_code: 200
Port Check Ensures that a specific port is open and accepting connections.
ansible.builtin.wait_for:
  host: localhost
  port: 8080
  timeout: 30

Example: Smoke Test Playbook

- name: Run smoke tests
  hosts: all
  tasks:
    - name: Check HTTP status
      ansible.builtin.uri:
        url: http://{{ ansible_host }}/health
        status_code: 200
      register: result

    - name: Fail if service is not healthy
      ansible.builtin.fail:
        msg: "Service is not healthy"
      when: result.status != 200
Note: Smoke tests are intended to be fast and lightweight, focusing on basic functionality rather than comprehensive validation.

9. Implementing Rollback Strategies

Strategy Description Usage
rollback Rollback to a previous state or version of a configuration or deployment ansible-playbook rollback.yml
version_control Use version control to track and revert configurations git checkout <commit>
snapshot Create snapshots of system states before changes ansible-galaxy collection install community.general

Example: Rollback using tags

- name: Deploy application
  hosts: web_servers
  tags:
    - deploy
  tasks:
    - name: Install new version
      apt:
        name: myapp
        state: latest

- name: Rollback to previous version
  hosts: web_servers
  tags:
    - rollback
  tasks:
    - name: Revert to previous version
      apt:
        name: myapp
        state: "2.0.0"
Note: Ensure rollback strategies are tested in a staging environment before applying to production.
Warning: Rollback may not always be possible if the previous state is no longer accessible or has been modified.

10. Using Configuration Drift Detection

Example: Detecting Configuration Drift with Ansible

- name: Check for configuration drift
  hosts: all
  tasks:
    - name: Gather facts about current system
      setup:

    - name: Compare local config with remote
      command: diff /etc/nginx/nginx.conf /tmp/expected.conf
      register: config_diff
      ignore_errors: yes

    - name: Report drift if found
      debug:
        msg: "Configuration drift detected in nginx.conf"
      when: config_diff.rc != 0
Option Values Description
ansible.builtin.setup yes Gathers facts about the target system
ansible.builtin.command diff Compares local and remote configuration files
ansible.builtin.debug msg Reports drift detection results
Note: Configuration drift detection requires that expected configurations are stored in a known location or version-controlled repository.
Warning: The diff command must be available on all target hosts for this approach to work.

Was this article helpful?