ansible-playbook-design

Ansible Playbook Design

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "ansible-playbook-design" with this command: npx skills add basher83/lunar-claude/basher83-lunar-claude-ansible-playbook-design

Ansible Playbook Design

Patterns for designing well-structured, maintainable Ansible playbooks.

State-Based Playbook Pattern

Design playbooks to handle both creation and removal via a state variable.

Core Pattern


  • name: Manage admin user account hosts: all become: true

    vars: admin_state: present # or absent

    tasks:

    • name: Create admin user ansible.builtin.user: name: "{{ admin_name }}" groups: "{{ admin_groups }}" state: "{{ admin_state }}"

    • name: Configure SSH key ansible.posix.authorized_key: user: "{{ admin_name }}" key: "{{ admin_ssh_key }}" state: "{{ admin_state }}" when: admin_state == 'present'

Usage

Create user (default)

uv run ansible-playbook playbooks/manage-admin.yml
-e "admin_name=alice"
-e "admin_ssh_key='ssh-ed25519 AAAA...'"

Remove user

uv run ansible-playbook playbooks/manage-admin.yml
-e "admin_name=alice"
-e "admin_state=absent"

Benefits

  • Single source of truth

  • Consistent interface

  • Less code duplication

  • Follows community role conventions

Play Structure

Recommended Play Sections

Order sections consistently across all playbooks:


  • name: Descriptive play name hosts: target_group become: true gather_facts: true

    vars:

    Play-level variables

    app_version: "2.0.0"

    vars_files:

    External variable files

    • vars/secrets.yml

    pre_tasks:

    Tasks that must run before roles

    • name: Update apt cache ansible.builtin.apt: update_cache: true cache_valid_time: 3600

    roles:

    Role includes

    • role: common
    • role: app_deploy vars: deploy_version: "{{ app_version }}"

    tasks:

    Play-specific tasks

    post_tasks:

    Cleanup or finalization

    • name: Send deployment notification ansible.builtin.debug: msg: "Deployment complete"

    handlers:

    Event-triggered tasks

    • name: restart app ansible.builtin.systemd: name: myapp state: restarted

Variable Organization

Variable Precedence (Key Levels)

From lowest to highest precedence:

  • Role defaults (roles/x/defaults/main.yml )

  • Inventory group_vars (group_vars/all.yml )

  • Inventory host_vars (host_vars/hostname.yml )

  • Play vars (vars: in playbook)

  • Task vars (vars: on task)

  • Extra vars (-e on command line) - highest

Organizing Variables

ansible/ ├── group_vars/ │ ├── all.yml # Variables for ALL hosts │ ├── proxmox.yml # Proxmox cluster hosts │ └── docker_hosts.yml # Docker host group ├── host_vars/ │ ├── node01.yml # Host-specific overrides │ └── node02.yml └── playbooks/ └── deploy.yml # Uses vars: for playbook-specific

Variable Naming by Scope

group_vars/all.yml - Global defaults

default_timezone: "UTC" ntp_servers:

  • 0.pool.ntp.org
  • 1.pool.ntp.org

group_vars/proxmox.yml - Group-specific

proxmox_api_host: "192.168.1.10" proxmox_cluster_name: "production"

host_vars/node01.yml - Host-specific overrides

proxmox_node_id: 1 ceph_osd_devices:

  • /dev/sdb
  • /dev/sdc

Task Organization with Includes

When to Split Tasks

Split playbook tasks into separate files when:

  • Tasks exceed 50 lines

  • Logical groupings emerge (networking, storage, users)

  • Conditional sections can be skipped entirely

Include Patterns

playbooks/setup-cluster.yml


  • name: Setup Proxmox cluster hosts: proxmox become: true

    tasks:

    • name: Configure networking ansible.builtin.include_tasks: tasks/networking.yml

    • name: Setup storage ansible.builtin.include_tasks: tasks/storage.yml when: setup_storage | default(true)

    • name: Initialize cluster ansible.builtin.include_tasks: tasks/cluster-init.yml when: inventory_hostname == groups['proxmox'][0]

import_tasks vs include_tasks

Feature import_tasks include_tasks

When evaluated Parse time (static) Runtime (dynamic)

Supports loops No Yes

Supports conditionals on import Limited Full

Use case Ordered execution Conditional/looped

Static import - always loaded, order matters

  • ansible.builtin.import_tasks: users.yml
  • ansible.builtin.import_tasks: permissions.yml

Dynamic include - conditional, looped

  • ansible.builtin.include_tasks: "setup-{{ ansible_os_family }}.yml"
  • ansible.builtin.include_tasks: deploy-app.yml loop: "{{ applications }}"

Multi-Play Playbooks

Use multiple plays for different host groups or privilege levels:


Play 1: Gather facts from all nodes

  • name: Gather cluster information hosts: proxmox gather_facts: true tasks:
    • name: Set cluster facts ansible.builtin.set_fact: cluster_node_count: "{{ groups['proxmox'] | length }}"

Play 2: Initialize primary node

  • name: Initialize cluster on primary hosts: proxmox[0] become: true tasks:
    • name: Create cluster ansible.builtin.command: pvecm create {{ cluster_name }} when: not cluster_exists

Play 3: Join secondary nodes

  • name: Join cluster on secondary nodes hosts: proxmox[1:] become: true serial: 1 # One node at a time tasks:
    • name: Join cluster ansible.builtin.command: pvecm add {{ primary_node }} when: not node_in_cluster

Handler Best Practices

Define Handlers at Play Level


  • name: Configure web server hosts: webservers become: true

    tasks:

    • name: Update nginx config ansible.builtin.template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf notify: reload nginx

    • name: Update SSL certificates ansible.builtin.copy: src: "{{ item }}" dest: /etc/nginx/ssl/ loop:

      • cert.pem
      • key.pem notify: reload nginx

    handlers:

    • name: reload nginx ansible.builtin.systemd: name: nginx state: reloaded

Handler Execution Order

Handlers run:

  • At the end of each play

  • In the order they are defined (not notified)

  • Only once, even if notified multiple times

Force immediate handler execution:

  • name: Update critical config ansible.builtin.template: src: config.j2 dest: /etc/app/config.yml notify: restart app

  • name: Flush handlers now ansible.builtin.meta: flush_handlers

  • name: Verify app is running ansible.builtin.uri: url: http://localhost:8080/health

Playbook Validation

Pre-flight Checks

Add validation at the start of playbooks:


  • name: Deploy application hosts: app_servers become: true

    tasks:

    • name: Validate required variables ansible.builtin.assert: that: - app_version is defined - app_version | regex_search('^\d+.\d+.\d+$') - deploy_env in ['staging', 'production'] fail_msg: "Invalid configuration. Check app_version and deploy_env."

    • name: Check disk space ansible.builtin.assert: that: ansible_mounts | selectattr('mount', 'equalto', '/') | map(attribute='size_available') | first > 1073741824 fail_msg: "Insufficient disk space. Need at least 1GB free."

Template Patterns

Playbook Template Structure


playbooks/template-playbook.yml

Description: [What this playbook does]

Usage: uv run ansible-playbook playbooks/template-playbook.yml -e "var=value"

Requirements: [Any prerequisites]

  • name: [Descriptive play name] hosts: [target_group] become: [true/false] gather_facts: [true/false]

    vars:

    Configurable variables with defaults

    resource_state: present

    tasks:

    • name: Validate inputs ansible.builtin.assert: that: - required_var is defined fail_msg: "required_var must be defined"

    Main tasks...

    • name: Verify completion ansible.builtin.debug: msg: "Playbook completed successfully"

Additional Resources

For detailed playbook patterns and techniques, consult:

  • references/playbook-role-patterns.md
  • Comprehensive playbook organization patterns, play structure, import strategies

Related Skills

  • ansible-role-design - When to use roles vs playbooks

  • ansible-fundamentals - Core module selection and naming

  • ansible-error-handling - Block/rescue patterns in playbooks

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

ansible-fundamentals

No summary provided by upstream source.

Repository SourceNeeds Review
General

ansible-idempotency

No summary provided by upstream source.

Repository SourceNeeds Review
General

ansible-role-design

No summary provided by upstream source.

Repository SourceNeeds Review
General

ansible-testing

No summary provided by upstream source.

Repository SourceNeeds Review