tags : System Design, Distributed Systems, Selfhosting, Infrastructure

Primary Concepts

Commands

  • ansible : ad-hoc(single task playbook)
  • ansible-playbook : Executing playbooks
  • ansible-inventory : Dump the configured inventory as Ansible sees it.
  • ansible-console : REPL for tasks
  • ansible-config : Generates ansible.cfg, also view
  • ansible-galaxy

Configuration

  • ansible.cfg : Config file, can specify inventory etc.

Pattern

  • Whether ad-hoc or via playbook, we always choose node or group via host pattern
  • Patterns let you run commands and playbooks against specific hosts and/or groups in your inventory.
  • Patterns depend on inventory. If a host or group is not listed in your inventory, you cannot use a pattern to target it.
  • Can refer to, A single host, An IP address/FQDN, Alias, Inventory group/set of groups/all groups, More.
  • Using ansible command
    $ ansible <pattern> ...
  • Using playbook
    ​- name: My first play
      hosts: <patten>
  • Patterns: targeting hosts and groups — Ansible Documentation
  • --limit <pattern> flag can help modify pattern in adhoc manner. This is useful for running playbooks for certain hosts/groups. Eg. ansible-playbook site.yml --limit datacenter2

Inventory

A managed list of nodes/hosts in your infrastructure is the inventory.

  • Applies on: Static servers, Dynamic servers(cloud), sub-sets(patterns)
  • Can be: YAML or INI

Forms

Static file/directory or Dynamic inventory(inventory plugin/inventory script), they also can be combined.

# inventory sources in ASCII order,
# so add numeric prefix for ordering if needed
inventory/
01-openstack.yml          # inventory plugin from OpenStack cloud
02-dynamic-inventory.py   # additional hosts w dyn inventory script
03-on-prem                # static hosts and groups
04-parent-groups          # static hosts and groups
  • Inventory plugins: Can take advantage of the most recent updates to the Ansible core code. (Recommended)
  • Inventory script: …

Group

  • Every host will always belong to at least 2 groups (all and ungrouped or all and some other group)
  • You can (and probably will) put each host in more than one group.
  • Parent groups = nested groups = group of groups
  • Groups can have multiple parents and children, but not circular relationships. (Useful to create metagroups)
  • Group hosts in your inventory logically according to their What(db/web), Where(onprem/cloud), and When(prod/stag).

Variables

  • Can be set for: nodes/hosts, groups
  • 3 ways to assign variables to inventory hosts
    • Right in the inventory file. (Okay for smaller setups)
      webservers:
        hosts:
          webserver01:
            ansible_host: 192.0.2.140
            http_port: 80
          webserver02:
            ansible_host: 192.0.2.150
            http_port: 443
        vars:
          ansible_user: my_server_user
    • Separate variable files. (Robust, Recommended)
      • Can use lists and hash data in host and group variables files. (Can’t do in inventory file)
      • Stored in host_vars and group_vars directory relative to the inventory.
        # group_vars / host_vars can be a file
        # or a directory (if single file becomes too large)
        ├── group_vars
          ├── another_group # read lexicographically
            ├── db_settings.yaml
            └── webserver_settings.yaml
          └── some_group.yaml
         
    • via CLI using -e option
  • If host is a member of multiple groups, ansible reads variable values from all of those groups and merges. If values differ for the same variable in different groups, internal rules for merging is used.
  • Precedence: Host > Child Group > Parent Group > All Group. Configurable via ansible_group_priority and DEFAULT_HASH_BEHAVIOUR
  • When you pass multiple inventory sources at the command line, Ansible merges variables in the order you pass those parameters.

Aliases

Hosts can have aliases.

# without aliases
linux:
  hosts:
    server1.example.com:
    server2.example.com:
    server3.example.com:
windows:
  hosts:
    server4.example.com:
    server5.example.com:
    server6.example.com:
 

# with aliases, serverX is the alias
linux:
  hosts:
    server1:
      ansible_host: server1.example.com # not needed if server1(alias) is already fqdn
    server2:
      ansisle_host: 10.17.4.56
    server3:
      ansible_host: server3.example.com
windows:
  hosts:
    server4:
      ansible_host: server4.example.com
    server5:
      ansible_host: server5.example.com
    server6:
      ansible_host: 10.17.4.60
  • inventory_hostname variable should contain the hostname alias.

Playbook

Playbooks are automation blueprints

Playbook > Play > Task > Ansible Module
  • Runs in order from top to bottom
  • Playbook Keywords can be applied at different levels of the playbook: Play, Role, Block, Task (can be overriden via cli)
  • Ansible allows Jinja2 loops and conditionals in templates but not in playbooks.
  • The output of adhoc ansible and playbook is different, eg. in adhoc you’ll probably get an output if you execute echo on target machine, when executing a playbook, you’ll probably have to add -v flags to get the same

Play

  • Basic unit of Ansible execution. Maps managed nodes (hosts) to tasks.
  • Contains: variables, roles and list of tasks

Task

  • An ‘action’ to be applied to the managed host.
  • Handler: Special form of a task, that only executes when notified via something. tasks can use the notify keyword.
    • Handlers run after all the tasks in a particular play have been completed
  • If a task fails on a host, Ansible takes that host out of the rotation for the rest of the playbook. See strategies
  • Blocks create logical groups of tasks. Blocks also offer ways to handle task errors. Directive does not affect the block itself, it is only inherited by the tasks enclosed by a block

Module

  • Ansible modules are the tools in your workshop, playbooks are your instruction manuals
  • Each task calls an Ansible module. Invoke several different modules in a playbook.
  • The code or binaries that Ansible copies to and executes on each managed node (when needed) to accomplish the action defined in each Task.
  • Multiple collections can contain modules with the same name, hence use FQCN in playbooks to ensure the correct module is selected,
  • Not all modules behave idempotently

Variables in details

  • Ansible facts: Variables you retrieve from remote systems. You can access this data in the ansible_facts variable.
  • Registers: You can create variables from the output of an Ansible task with the task keyword register (stored in memory)
  • Magic Variables: Variables related to Ansible are called magic variables.
  • Special Variables — Ansible Documentation

Secondary Concepts

Collections

  • Collections are a distribution format for Ansible content that can include playbooks, roles, modules, filters, and plugins.
  • You can install and use collections through Ansible Galaxy.
  • You don’t develop a collection, you develop a role, plugin, playbook etc. Then you use all that to build a collection (ansible-galaxy collection build ...)

Role

  • You can call it a certain way to structure a set of playbooks, tasks, handlers, variables, plugins, templates, files etc. Gives you some structure.
  • It has a defined directory structure with 8 main standard directories. Must include at least one of these directories.
  • For complex use cases, most users find roles easier to read, understand, and maintain than all-in-one playbooks.
  • Roles in collections are a bit annoying. Use stand alone roles when those fit best, there is nothing forcing you to use collections. (Roles in collections do not support plugin embedding)
  • You can use it in a play. The role must be imported into the play. Good to keep your playbooks small.

Plugins

Pieces of code that expand Ansible’s core capabilities

Types

become,cache,callback,cliconf,connection,httpapi,inventory,
lookup,netconf,shell,vars,module,strategy,test,filter,role,keyword

See Indexes of all modules and plugins — Ansible Documentation

  • Become: Ensure that Ansible can use certain privilege escalation systems
  • Cache: Cache plugins allow Ansible to store gathered facts or inventory source data without the performance hit of retrieving them from source.
  • Callback: Control what is displayed in the console
  • CLIConf: Cliconf plugins are abstractions over the CLI interface to network devices.
  • Connection: Control how you connect to a managed node
  • HTTPAPI: Httpapi plugins tell Ansible how to interact with a remote device’s HTTP-based API and execute tasks on the device.
  • Inventory: Inventory plugins allow users to point at data sources to compile the inventory of hosts that Ansible uses to target tasks
  • Lookup: Retrieve data from outside sources such as files, databases, key/value stores, APIs, and other services. How
    # same thing
    loop: " query('inventory_hostnames', 'all') "
    loop: " lookup('inventory_hostnames', 'all', wantlist=True) "
  • NetConf: Netconf plugins are abstractions over the Netconf interface to network devices.
  • Shell: Shell plugins work to ensure that the basic commands
  • Vars: Vars plugins inject additional variable data into Ansible runs that did not come from an inventory source, playbook, or command line.
  • 🌟 Module(Task Plugins/Library Plugins): Can be used from the command line or in a playbook task. They can optionally have an action plugin to do preparation stuff.
  • Strategy: Strategy plugins control the flow of play execution by handling task and host scheduling.
  • Test: Used for comparisons. How, Jinja builtin
  • Filter: Manipulate data. How, Jinja builtin
  • Keyword: What

Vault

Loops

Reuse stuff

See Re-using Ansible artifacts — Ansible Documentation

Include : Dynamic

  • Included tasks can be affected by the results of earlier tasks within the top-level playbook. (See handler usage for differences)
  • When a loop is used with an include, the included tasks or role will be executed once for each item in the loop.
  • what? include_role, include_tasks, include_vars

Import : Static

  • Imported content is never affected by other tasks within the top-level playbook. (See handler usage for differences)
  • what? import_role, import_tasks

Background

SSH connection

  • Defaults to OpenSSH, if not available, uses paramiko (py openssh)
  • User can be set via remote_user (playbook) or ansible_user (variable)

Ansible behavior priority

  • Configuration settings
  • Command-line options: Any command-line option will override any configuration setting.
  • Playbook keywords: Any playbook keyword will override any command-line option and any configuration setting.
  • Variables: Any variable will override any playbook keyword, any command-line option, and any configuration setting.
  • -e: To override all other settings in all other categories, you can use extra variables: —extra-vars or -e at the command line.

Templating

  • All templating happens on the controller. Therefore filters, tests, lookup also execute on the controller.
  • One cen create a template for a file or use templating in playbooks(templating task names etc.)

Resources