Ansible Fundamentals

What is Ansible?

  • Ansible is a free, open-source configuration management tool that is designed to install and manage the software on existing servers or systems.

  • It is an agentless tool i.e. we just need to install the Ansible on master node or control machine and it takes care of all the configuration on worker nodes or target machines without needing to install the Ansible on target machines.

Ansible Configuration Files

  • When we install the Ansible on the system, it creates a default configuration file at the location /etc/ansible/ansible.cfg (can change it as well).

  • It is a file that tell the Ansible about the environment. We can use this file to modify the Ansible’s setting to meet our needs.

  • Ansible consider the configuration defined in this file when we run the playbooks anywhere from the control machine.

  • This file includes various default configurations for tasks such as inventory management, logging, privilege escalation, connection setting, etc.

Default Location of ansible.cfg

  • Ansible looks for the configuration file in the following order of precedence:

    1. ANSIBLE_CONFIG environment variable (if set) (we can also set ANSIBLE_<PARAMAETER> to ovverride any one parameter in our config file with new value).

       # /etc/ansible/ansible.cfg
       gathering = implicit                
      
       # can override this while running the playbook as
       ANSIBLE_GATHERING=explicit ansible-playbook -i inventory playbook.yml
      
    2. ansible.cfg in the current working directory.

    3. ~/.ansible.cfg in the home directory.

    4. /etc/ansible/ansible.cfg (global configuration).

  • The first file found in this order is the one Ansible will use.

View Configuration

  • Lists all configurations

    ansible-config list

  • Show the current configuration file

    ansible-config view

  • Shows the current settings

    ansible-config dump


Ansible Inventory

  • Ansible Inventory is a file in INI or YAML format that defines the hosts or group of hosts that Ansible will manage.

  • Inventory file consists of information or details of target servers such as IP addresses, hostnames, connection details, etc.

  • The default location of an inventory file is /etc/ansible/hosts.

Common Inventory Attributes

  • ansible_host: The IP or hostname for the target machine

  • ansible_connection: ssh/winrm/localhost

  • ansible_user: The SSH user to connect as

  • ansible_port: The SSH port to use (default is 22)

  • ansible_ssh_pass: The SSH password (not recommended)

  • ansible_ssh_private_key_file: Path to the SSH private key for authentication

  • ansible_python_interpreter: The path to the Python interpreter on the host

Inventory Formats

  • Ansible supports 2 inventory formats: INI and YAML

  • INI format:

    • The most basic and widely-used format.

    • Hosts and groups are defined in a simple key-value or plain-text style.

        # Groups of hosts
        [webservers]
        web1.example.com
        web2.example.com
      
        [databases]
        db1.example.com ansible_user=dbadmin ansible_port=5432
        db2.example.com ansible_host=192.168.1.10 ansible_user=root
      
        # Ungrouped hosts with variables
        standalone.example.com ansible_user=admin ansible_port=2222
      
  • YAML Format:

    • A modern, structured format that is more readable and flexible.

    • Typically used for more complex inventories, especially with nested groups or hierarchies.

        all:
          children:
            webservers:
              hosts:
                web1.example.com:
                web2.example.com:
            databases:
              hosts:
                db1.example.com:
                  ansible_user: dbadmin
                  ansible_port: 5432
                db2.example.com:
                  ansible_host: 192.168.1.10
                  ansible_user: root
          vars:
            ansible_ssh_private_key_file: /path/to/key.pem
      

Grouping and Parent-Child Relationships

  • In Ansible Inventory, a parent-child relationship refers to a hierarchy where groups (the parent groups) contain other groups (the child groups).

      [datacenters]
      us
      europe
    
      [us]
      web1.us.example.com
      db1.us.example.com
    
      [europe]
      web1.europe.example.com
      db1.europe.example.com
    
      all:
        children:
          datacenters:
            children:
              us:
                hosts:
                  web1.us.example.com:
                  db1.us.example.com:
              europe:
                hosts:
                  web1.europe.example.com:
                  db1.europe.example.com
    

Variable Inheritance

  • Child groups or hosts can inherit variables from their parent groups, while also overriding them if necessary.

      iniCopy code[all:vars]
      ansible_user=admin
      ansible_port=22
    
      [datacenters:vars]
      ansible_port=2222
    
      [us]
      web1.us.example.com
      db1.us.example.com ansible_port=2022
    

    Variable Precedence:

    • Default ansible_user is admin

    • datacenters sets ansible_port to 2222

    • db1.us.example.com overrides it to 2022


Ansible Variables

  • Ansible variables are key-value pairs that allow us to store and use the data dynamically in playbooks.

Syntax

  • Variables are typically written as key: value pairs in YAML files.

  • To reference variables, use the Jinja2 template syntax: {{ variable_name }}.

      ---
      - hosts: localhost
        vars:
          car_model: 'BMW M3'
          country_name: USA
          title: 'Systems Engineer'
        tasks:
          - command: 'echo "My car is {{ car_model }}"'
          - command: 'echo "I live in the {{ country_name }}"'
          - command: 'echo "I work as a {{ title }}"'
    

Variable Types

  1. String Variables

    • Sequences of characters.

        username: "admin"
      
  2. Number Variables

    • Can hold integer or floating-point values.

        max_connections: 50
      
  3. Boolean Variables

    • Can hold either true of false.

        debug_mode: true
      
  4. List Variables

    • Can hold an ordered collection of values.

        packages:
        - nginx
        - postgresql
        - git
      
  5. Dictionary Variables

    • Can hold a collection of key-value pairs.

        user:
            name: admin
            password: secret
      

Types of Variables

  1. Host and Group Variables:

    • Defined in the inventory or host_vars/ and group_vars/ directories.

        # group_vars/webservers.yaml
        web_port: 80
      
  2. Facts:

    • Automatically gathered system information (e.g., ansible_facts).

        codeansible_distribution: "Ubuntu"
        ansible_hostname: "web1"
      
  3. Registered Variables:

    • Store the output of a task to use later in the playbook.

    • Structure of a Registered Variable:

      • stdout: The standard output of the command.

      • stderr: The standard error, if any.

      • rc: The return code (0 indicates success).

      • stdout_lines: The standard output split into lines for easier processing.

          - name: Get uptime
            command: uptime
            register: uptime_output
        
          - debug:
              msg: "Uptime is {{ uptime_output.stdout }}"
        
  4. Role Variables:

    • Variables specific to a role, defined in defaults or vars.
  5. CLI Variables:

    • Passed using the --extra-vars (-e) flag.

        ansible-playbook site.yml -e "web_port=8080 db_host=db.example.com"
      
  6. Environment Variables:

    • System environment variables can be accessed using lookup('env', 'ENV_VAR_NAME').

Variable Precedence

  • Ansible resolves variables based on their precedence. The hierarchy (from lowest to highest) is:

    1. Role defaults (defaults/main.yml)

    2. Inventory group variables

    3. Inventory host variables

    4. Playbook-level variables

    5. Extra variables (-e on the command line)

Variable Scoping

  • A scope defines the accessibility or the visibility of a variable.

  • Scope of Variables:

    1. Global scope:

      • Variables that apply across the entire Ansible execution.

      • Includes variables set in:

        • Configuration files (e.g., ansible.cfg).

        • CLI options (e.g., --extra-vars).

            ansible-playbook site.yml -e "variable=value"
  1. Play scope:

    • Variables defined within a specific playbook or role.

    • Limited to the play or the roles/tasks executed as part of it.

        - name: Example Play
          hosts: all
          vars:
            play_var: "This is a play variable"
          tasks:
            - debug:
                msg: "{{ play_var }}"
      
  2. Host scope:

    • Variables specific to a particular host.

    • Defined in inventory files, host_vars/, or dynamically through facts.

        # host_vars/web1.yaml
        host_specific_var: "This is a host variable"
      
  3. Group scope:

    • Defined per group in inventory files or group variable files.
  4. Task Scope:

    • Variables defined or registered within a task.

    • Limited to the task or subsequent tasks in the same play.

        - name: Get system uptime
          command: uptime
          register: uptime_output
      

Magic Variables

  • Ansible magic variables are special variables that Ansible automatically defines and makes available during the execution of a playbook.

  • This variables provide essential information about the current play, host, tasks etc.

  • (*) ones are important in given below tables.

Common Magic Variables

  1. Play Context Variables

    • Provide the details about the playbook and current execution context.
VariableDescription
inventory_hostnameThe name of the current host as defined in the inventory. (*)
inventory_hostname_shortThe short name of the current host (first part before the dot).
play_hostsList of all hosts in the current play.
ansible_playbook_dirThe directory containing the playbook being executed.
ansible_userThe user Ansible is using to connect to the host.
  1. Host and Group Variables

    • Provide details about the current host and groups in the inventory.
VariableDescription
group_namesList of groups the current host belongs to. (*)
groupsDictionary of all groups and their members. (*)
hostvarsDictionary of all variables for all hosts. (*)
  1. Connection Variables

    • Provide details about the connection to the target host.
VariableDescription
ansible_hostThe IP or hostname of the current host.
ansible_portThe SSH port used to connect to the host.
ansible_userThe user used for the connection.
  1. Task Context Variables

    • Provide information about the currently executing task.
VariableDescription
ansible_check_modeBoolean indicating if Ansible is running in check mode.
ansible_failed_taskDetails of the last failed task (if any).
ansible_factsDictionary of system facts gathered by Ansible.
  1. Loop Variables

    • Used to access details about the current item in a loop.
VariableDescription
itemCurrent item in a loop.
ansible_loop_varThe loop variable name (to avoid conflicts).
item.key, item.valueKey-value pairs when looping over dictionaries.
  1. Playbook Execution Variables

    • Provide details about the playbook execution environment.
VariableDescription
playbook_dirDirectory where the current playbook resides.
role_pathDirectory where the current role resides.

Ansible Facts

  • Ansible facts are pieces of information collected about a targeted machine during the execution of a playbook.

  • These facts includes system details such as operating system, configuration, hardware specifications, etc.

  • Ansible gathers these facts using the setup modules at the beginning of a play automatically.

  • By default, Ansible collects facts when a playbook is run. You can disable this by setting gather_facts: no in your playbook.

      - name: Example Playbook
        hosts: all
        gather_facts: no
        tasks:
          - name: Print a message
            debug:
              msg: "Facts are disabled."
    
  • We can also set this setting in ansible configuration file with a flag named as gathering

    • gathering: smart - gather by default, but don’t regather if already gathered

    • gathering: implicit - gather by default, turn off with gather_facts: False

    • gathering: explicit - do not gather by default, must say gather_facts: True

  • If specified in both playbook and configuration file, the setting in playbook always takes the precedence over the configuration file.


Ansible Playbooks

  • Ansible playbooks are Ansible’s orchestration language.

  • It’s a YAML file that defines a series of tasks that Ansible will perform on the target machines.

Basic structure of Ansible Playbook

  1. Playbook: A single YAML file

  2. Plays: Defines a set of action (tasks) to be performed of the hosts

  3. Task: An action to be performed on the hosts

  4. Modules: The different actions run by tasks are modules (predefined tools to execute specific action e.g. file, command, service)

     # a single play consisting of multiple tasks
     - 
         name: Play 1    
         hosts: localhost
         tasks:
         - name: Execute command ‘date’
           command: date
         - name: Execute script on server
           script: test_script.sh
         - name: Install httpd service
           yum:
               name: httpd
               state: present
         - name: Start web server
           service:
               name: httpd
               state: started
    
     # multiple (2) plays consisting of multiple tasks
     -
         name: Play 1
         hosts: localhost
         tasks:
         - name: Execute command ‘date’
           command: date
         - name: Execute script on server
           script: test_script.sh
     - 
         name: Play 2
         hosts: localhost
         tasks:
         - name: Install web service
           yum:
               name: httpd
               state: present
         - name: Start web server
           service:
               name: httpd
               state: started
    

    Note: The host (target machine) we want to run the actions is defined at the play level. The host can be anything defined in the inventory file.

Run a playbook

  • To execute a playbook:

      # run a playbook
      ansible-playbook <playbook-name>.yaml
    
      # playbook help
      ansible-playbook --help
    

Verifying Playbooks

  • Verifying ansible playbooks ensures that they are syntactically correct and logically valid before running them in production.

    1. Syntax Check:

      • The --syntax-check option validates the syntax of a playbook without executing it.

          ansible-playbook playbook.yml --syntax-check
        
    2. Dry Run (Check Mode)

      • The --check option runs the playbook without making changes to the target systems.

          ansible-playbook playbook.yml --check
        
    3. Diff Mode

      • The --diff option along with --check provides a before-and-after comparison of playbook changes.

          ansible-playbook playbook.yml --check --diff
        

Ansible Lint

  • Ansible Lint is a command-line tool that checks the playbooks against best practices and coding standards.

      # installation
      pip install ansible-lint
    
      #command to run 
      ansible-lint playbook.yml
    
  • It provides warnings or errors for deprecated modules, misuse of variables, inefficient practices, etc.

Ansible Conditionals

  • Ansible Conditionals allows to control the execution of tasks based on specific conditions.

  • The when keyword to specify when a task should execute.

  • Multiple conditions can be combined using or, and and not keywords.

  • Note: Conditional statements should not include jinja2 templating delimiters such a {{ }} or {% %}.

      # Based on Variables 
      -
          name: Play 1    
          hosts: localhost
          tasks:
          - name: Install nginx if required
            apt:
                name: nginx
                state: present
            when: install_nginx == true  # install_nginx is a variable
    
      # Based on facts and Combining Multiple Conditions
      -
          name: Play 2
          hosts: localhost
          tasks:
          - name: Install nginx only if OS is Ubuntu and install_nginx is true
            apt:
                name: nginx
                state: present
            when: ansible_distribution == "Ubuntu" and install_nginx == true
    
      # Conditions in loops
      -
          name: Play 3
          hosts: localhost
          vars:
              packages:
              - name: nginx
                required: True
              - name: mysql
                required : True
              - name: apache
                required : False    
          tasks:
          - name: Install '{{ item.name }}' on Debian
            apt:
                name: '{{ item.name }}'
                state: present
            when: item.required == True
            loop: '{{ packages }}'
    

Ansible Loops

  • Ansible loops are basically a series of iterations that gets performed on a set of data.

  • It provides a variable named as item that can be use t iterate and access a specific data.

    1. Simple List Loop:

       name: Play 1
       hosts: localhost
       tasks:
       - name: Install multiple packages
         apt:
             name: "{{ item }}"
             state: present
         loop:
         - vim
         - git
         - curl
      
    2. Dictionary Loop:

       name: Play 1
       hosts: localhost
       tasks:
       - name: Create users with specific details
         user:
             name: "{{ item.name }}"
             state: present
             uid: "{{ item.uid }}"
         loop:
         - { name: alice, uid: 1001 }       # can also be written as below
         - { name: bob, uid: 1002 }         # - name: alice
         - { name: charlie, uid: 1003 }     #   uid: 1001
      
    3. Range Loop:

       name: Play 1
       hosts: localhost
       tasks:
       - name: Create multiple files
         file:
             path: "/tmp/file{{ item }}"
             state: touch
         loop: "{{ range(1, 6) | list }}"   # This creates /tmp/file1 to /tmp/file5
      

With_*

  • with_ Loop (Legacy Syntax) still supported, with_ loops are being replaced by loop (lookup directive).

      name: Play 1
      hosts: localhost
      tasks:
      - name: Install multiple packages
        yum:
            name: "{{ item }}"
            state: present
        with_items:
        - httpd
        - nginx
    
  • Some of the example of with_:

      with_items
      with_file
      with_url
      with_mongodb
      with_dict
      with_etcd
      with_env
      with_filetree
      With_ini
      With_inventory_hostnames
      With_k8s
      With_manifold
      With_nested
      With_nios
      With_openshift
      With_password
      With_pipe
      With_rabbitmq
      With_redis
      With_sequence
      With_skydive
      With_subelements
      With_template
      With_together
      With_varnames
    

Ansible Modules

  • Ansible Modules are small, reusable scripts that Ansible uses to perform specific tasks on target systems (defined inside the tasks).

  • Idempotency: Modules ensure tasks are only executed when necessary, avoiding redundant changes.

How to use Ansible Modules

  1. In Ad-Hoc Commands: Modules can be used directly in ad-hoc commands without writing a playbook.

     ansible all -m ping
     ansible webservers -m service -a "name=nginx state=started"
    
  2. In Playbooks: Modules are specified within tasks in a playbook.

     - name: Configure web servers
       hosts: webservers
       tasks:
         - name: Install Apache
           apt:
             name: apache2
             state: present
    

Commonly Used Ansible Modules

  1. File and Directory Management:

    • copy: Copies files to remote hosts.

    • template: Renders Jinja2 templates and transfers them to remote hosts.

    • file: Sets file attributes like permissions, ownership, and state.

    • fetch: Retrieves files from remote hosts.

    tasks:
    - name: Copy file to remote server
      copy:
          src: /local/path/to/file
          dest: /remote/path/to/file
  1. Package Management:

    • apt: Manages packages on Debian-based systems.

    • yum: Manages packages on Red Hat-based systems.

    tasks:
    - name: Install nginx
      apt:
          name: nginx
          state: present
  1. Service Management:

    • service: Manages services (start, stop, restart).
    tasks:
    - name: Ensure nginx is running
      service:
          name: nginx
          state: started
  1. User and Group Management:

    • user: Manages users on remote systems.

    • group: Manages groups.

    tasks:
    - name: Create a user
      user:
          name: johndoe
          state: present
  1. Command Execution:

    • command: Executes commands on the remote host (don’t supports idempotency).

    • shell: Executes shell commands (includes environment variables and pipes) (don’t supports idempotency).

    • lineinfile: Search for a line in a file and replace it or add it if it doesn’t exist (supports idempotency).

    tasks:
    - name: Run a command
      command: ls /etc
    - name: Display resolve.conf contents
      command: cat resolv.conf chdir=/etc
  1. Cloud Resource Management:

    • ec2: Manages AWS EC2 instances.

    • gcp_compute_instance: Manages Google Cloud Compute Engine instances.

    tasks:
    - name: Launch an AWS EC2 instance
      ec2:
          key_name: my_key
          instance_type: t2.micro
          image: ami-12345678
          region: us-east-1

Ansible Plugins

  • Ansible Plugin is a piece of code that enhance or extends the functionality of Ansible.

  • They allows to customize or change the default behavior of how Ansible works to process tasks, inventory or data.

Types of Ansible Plugins (some of many)

  1. Inventory Plugins:

    • Manage dynamic inventories from external sources.

    • Examples: aws_ec2, gcp_compute, azure_rm

    • Use Case: Fetch host information dynamically from cloud providers or other databases.

  2. Action Plugins:

    • Modify or enhance the behavior of modules in playbooks.

    • Examples: normal, accelerate

    • Use Case: Add logic to change how a task executes.

  3. Callback Plugins:

    • Customize the output or logging behavior during playbook execution. Also provides hooks into Ansible’s execution lifecycle, allowing to capture events and perform custom actions during playbook execution.

    • Examples: default, json, yaml

    • Use Case: Change the playbook output format or send notifications.

  4. Connection Plugins:

    • Define how Ansible connects to target hosts.

    • Examples: ssh, paramiko, local

    • Use Case: Support different connection methods, such as SSH, winRM, Docker, or API-based.

  5. Lookup Plugins

    • Retrieve data from external sources.

    • Examples: file, url, password

    • Use Case: Fetch secrets, data files, or content dynamically during playbook execution.

  6. Filter Plugins

    • Manipulate data in templates or tasks.

    • Examples: default, to_json, split

    • Use Case: Transform data in Jinja2 templates.


Ansible Handlers

  • Ansible Handlers are special tasks in Ansible playbooks that are triggered only when notified by other tasks.

  • Handlers are typically used to perform operations that need to occur only when a change is made by another task, such as restarting a service after a configuration file is updated.

  • Handlers are defined under the handlers section in a playbook. They work in conjunction with the notify directive in tasks.

      - name: Example of Ansible Handlers
        hosts: webservers
        tasks:
          - name: Update configuration file
            template:
              src: /path/to/template.j2
              dest: /path/to/destination.conf
            notify: Restart Web Service
    
        handlers:
          - name: Restart Web Service
            service:
              name: apache2
              state: restarted
    
    1. Task:

      • The notify directive triggers a handler when the task makes a change.

      • In the example, if the template task updates the configuration file, it notifies the Restart Web Service handler.

    2. Handler:

      • Defined under handlers with a unique name.

      • Contains the task to be executed, such as restarting the apache2 service.

Key Points:

  • Handlers Are Executed After Tasks: Handlers are not executed immediately when notified but are queued until all tasks in the play are completed.

  • Handlers Run Once: A handler runs only once, even if it is notified multiple times during a play.

  • Notification Without Change: If a task does not change anything, its notify directive does not trigger the handler.

  • Multiple Handlers: A single task can notify multiple handlers, and multiple tasks can notify the same handler.

  • Force Handlers to Run Earlier:

    • Use meta: flush_handlers to execute handlers immediately instead of waiting for the end of the play.

        - name: Flush Handlers Immediately
          meta: flush_handlers
      

Ansible Roles

  • Ansible Roles are a way to organize and modularize reusable configuration playbooks.

  • Roles break down complex playbooks into smaller, reusable components, making them easier to manage, maintain and share.

Why Use Roles?

  1. Reusability: Roles can be reused across multiple playbooks and projects.

  2. Modularity: Break down complex configurations into smaller, manageable components.

  3. Standardization: Provides a consistent and predictable structure for organizing Ansible code.

  4. Maintainability: Easier to update and manage specific parts of the configuration.

  5. Collaboration: Facilitates sharing and collaboration among team members or the broader community.

Structure of an Ansible Role

  • When creating a role, it follows a standard directory structure:

      <role_name>/
      ├── tasks/          # Contains the main list of tasks to be executed.
      │   └── main.yml
      ├── handlers/       # Defines handlers triggered by tasks.
      │   └── main.yml
      ├── templates/      # Stores Jinja2 templates for configuration files.
      ├── files/          # Stores static files to be copied to remote systems.
      ├── vars/           # Defines variables specific to the role.
      │   └── main.yml
      ├── defaults/       # Defines default variables for the role.
      │   └── main.yml
      ├── meta/           # Metadata about the role, including dependencies.
      │   └── main.yml
      ├── tests/          # Test playbooks for the role.
      │   ├── inventory
      │   └── test.yml
      └── README.md       # Documentation for the role.
    

How to Create and Use a Role in a Playbook

  • Create a Role:

      ansible-galaxy init <role_name>
    
  • Reference the Role in a Playbook: Add the role to a playbook using the roles keyword.

      - hosts: webservers
        roles:
          - nginx
    

Roles location

  1. We can define Ansible Roles inside a roles directory under the playbook directory like below:

     my-playbooks/
     ├── playbook.yml
     ├── roles/               # roles directory consisting of all the roles e.g. mysql
     │   └── mysql/
     │       └── README.md
     │       └── templates/
     │       └── tasks/
     │       └── handlers/
     │       └── vars/
     │       └── defaults/
     │       └── meta/
    
  2. We can move the roles to a common directory designated for roles on the system /etc/ansible/roles location.

    • Default location where ansible searches for the roles if it can’t be found in a playbook directory.

    • This is defined inside a Ansible Configuration file i.e. /etc/ansible/ansible.cfg.

        # /etc/ansible/ansible.cfg
        roles_path = /etc/ansible/roles
      

Ansible Galaxy

  • Ansible Galaxy is a community-driven platform for searching, sharing and managing Ansible Roles and Collections.

  • It act as a repository where users can publish their roles and collections.

Ansible Galaxy Operations

  1. Initialize a New Role

     ansible-galaxy init <role-name>
    
  2. Find/Search Roles

     ansible-galaxy search <role-name>
    
  3. Install a Role

     ansible-galaxy install <namespace>.<role-name>
    
  4. List installed Roles

     ansible-galaxy list
    
  5. Remove a Role

     ansible-galaxy remove <namespace>.<role_name>
    
  6. Location where roles would be installed

     ansible-config dump | grep ROLE
    
     # output
     EFAULT_PRIVATE_ROLE_VARS(default) = False
     DEFAULT_ROLES_PATH(default) = [u'/root/.ansible/roles', u'/usr/share/ansible/roles', u'/etc/ansible/roles']
     GALAXY_ROLE_SKELETON(default) = None
     GALAXY_ROLE_SKELETON_IGNORE(default) = ['^.git$', '^.*/.git_keep$']
    
  7. Install the role in current directory under roles

     ansible-galaxy install <namespace>.<role-name> -p ./roles
    

Ansible Collections

  • Ansible Collection is a broader packing format to bundle and distributes Ansible contents such as roles, modules, plugins, and playbooks as a single distribution unit.

Structure of Ansible Collection

  • A collection has a standard directory structure:

      <namespace>/<collection_name>/
      ├── docs/              # Documentation files
      ├── galaxy.yml         # Metadata for the collection
      ├── plugins/           # Plugins (e.g., modules, filters, inventory, etc.)
      │   ├── modules/
      │   ├── connection/
      │   ├── filter/
      │   ├── lookup/
      ├── roles/             # Roles bundled in the collection
      ├── playbooks/         # Example playbooks
      ├── tests/             # Integration or unit tests
      ├── README.md          # Collection overview and usage
    

Creating an Ansible Collection

  1. Initialize a Collection:

     ansible-galaxy collection init <namespace>.<collection_name>
    
  2. List a Collection with version:

     ansible-galaxy collection list <namespace>.<collection_name>
    
  3. Install a Collection:

     ansible-galaxy collection install <namespace>.<collection_name>
    
  4. Uninstall a Collection:

     ansible-galaxy collection uninstall <namespace>.<collection_name>
    

Ansible Template

  • Ansible Template includes the use of Jinja2 templates to dynamically generate configuration files or scripts during playbook execution.

Jinja2 Template Syntax

  1. Variable Substitution:

     Hello, {{ name }}!
    
  2. Filters: Modify variable output.

     {{ hostname | upper }}
    
  3. Default Value:

     {{ value | default('default_value') }}
    
  4. Replace Value:

     {{ value | replace('XYZ', 'ABC') }}
    
  5. Conditionals:

     {% if status == 'active' %}
         Service is running.
     {% else %}
         Service is not running.
     {% endif %}
    
  6. Loops:

     {% for user in users %}
     - {{ user }}
     {% endfor %}
    
  7. Macros: Define reusable code blocks.

     {% macro greet(user) %}
     Hello, {{ user }}!
     {% endmacro %}
    

Creating and Using Templates

  1. Create a Template

    • Templates are typically saved with a .j2 extension. Here's an example for an Nginx configuration:

        # nginx.conf.j2
        server {
            listen {{ nginx_port }};
            server_name {{ server_name }};
            location / {
                proxy_pass http://{{ backend_server }};
            }
        }
      
  2. Use the template module

    • Use the template module to render the template and deploy it to a managed node:

        - name: Deploy Nginx configuration
          template:
            src: templates/nginx.conf.j2
            dest: /etc/nginx/nginx.conf
          vars:
            nginx_port: 80
            server_name: example.com
            backend_server: 127.0.0.1