Ansible is an opensource, agentless IT automation tool that can be used to automatically provision, configure, manage and deploy software. Ansible is considered agentless because it uses ssh and winrm to communicate with Linux and windows hosts so no software(i.e. agent) needs to be installed on the target servers.
-
Inventory
-
Inventory File
- Default Inventory file is located as
/etc/ansible/hosts
- uses similar syntax to an ini file.
- Default Inventory file is located as
-
Inventory Parameters a.k.a variables
ansible_connection
: defines how Ansible connects to target server- ssh
- winrm
- localhost (Ansible will not connect to remote machines)
ansible_host
: defines the host nameansible_port
: Specifies which port Ansible connects over- Defaults to 22 for SSH
ansible_user
: defines the user Ansible connects as- Defaults to root for Linux systems.
ansible_ssh_pass
: The password to use for ssh connections.ansible_password
: The password to use form winrm connections.- Any number of arbitrary parameters can be defined as well and used as variables for each host as needed. note: these will be interpreted as strings and not python literals
web1 ansible_host=web1.xyz.com custom_variable=1337
note: it is recommended to use Ansible Vault for passwords
-
Alias
- Servers must be specified using their FQDN.
- The FQDN can be aliased using the
ansible_host
parameter.
# web and db are the aliases for the FQDN's in the example. web = ansible_host=frontend.xyz.com db = ansible_host=postgres.xyz.com
-
Grouping
- Servers can be grouped together and the group can be targeted so every server in a group will be acted upon.
- If aliased the alias name should be used for the group instead of the FQDN
# web_servers and databases are the groups in this example db ansible_host=postgres.xyz.com [web_servers] webserver1.xyz.com webserver2.xyz.com [databases] db
- Additionally Groups of Groups can be specified using the
[groupname:children]
syntax# all is the group of groups while web_servers and databases are the groups in contains db ansible_host=postgres.xyz.com [web_servers] webserver1.xyz.com webserver2.xyz.com [databases] db [all:children] web_servers databases
-
-
Playbooks
- The Orchestration Language of Ansible. Playbooks define what we want Ansible to do.
- Written in YAML
- Terminology
Task
: An action to take on a hostPlay
: A series of tasksModule
: The actions run in a task i.e. (shell, command, yum, service etc.)
- Each Playbook contains a set of plays
- Each YAML file is a different Playbook
- # This is considered the Play level name: Sample Play hosts: localhost # This can be an array of hosts or groups found in the inventory file tasks: # This is considered the task level - name: Say Hello shell: echo 'Hello World!'
-
Modules
-
The actions run in a Play's task. i.e (shell, command, yum, etc.)
-
All modules can be found on the Module Index or by running
ansible-doc -l
from command line -
Modules are categorized based on their functionality. These are a few of the categories
System
: Actions perfomed at a system level (i.e. shutdown, restart etc.)Commands
: Actions used to execute commands or scripts- Use the
win_command
module when working with Windows
- Use the
Script
: Transfers a local script to remote nodes and runs itFiles
: Actions performed on files that live on the targetDatabase
: Actions for managing databasesCloud
: Actions for the various cloud providersWindows
: Actions specifically for Windows
-
Idempotency
- Most modules are idempotent meaning that running the playbook multiple times would result in the same system state.
- Example If httpd is already started this play does nothing otherwise httpd is started
... tasks: - name: Start httpd service: name=httpd state=started # Note the above is the same as tasks: - name: Start httpd service: name: httpd state: started
-
-
Variables
- Stores information that vary between hosts
- Jinja2 templating is used for accessing variables
- Variables can be declared in inside a(n)
- Inventory file
- ansible_host, ansible_user and ansible_ssh_pass etc. are examples of variables.
- Playbook using the
vars
keynote the jinja2 syntax is only used in this example because the variable is being used within a string.- name: Sample Play hosts: localhost vars: greeting: Hello tasks: - name: Say Hello command: echo '{{ greeting }} World!' # Note the Jinja2 syntax {{ var_name }}
- Standalone Variables file
# vars.yml greeting: Hello salutation: Hasta La Vista Baby
# greetings.yml - name: Converse hosts: localhost vars_files: #note to include variables we have to use the vars_files keyword - vars.yml tasks: - name: Say Hello command: echo '{{ greeting }} World!' - name: Say Good-bye command: echo '{{ salutation }}!'
- Using a variable from the inventory file in the playbook
#inventory file localhost ansible_connection=localhost nameserver_ip=192.168.0.0
note: if the playbook specifies a host that does not have the variable being referenced the play will fail.# Playbook - name: Add nameserver hosts: localhost tasks: - name: Ensure nameserver line exists lineinfile: path=/etc/resolv.conf line='{{ nameserver_ip }}' # Note the quotes are required here.
- Inventory file
-
Conditionals
- Used to control when a task is run
- Conditionals are only used in a Playbook
- The full list of supported operators can be found on the docs.ansible.com Tests Page
- keywords
when
: What actually performs the checknote this is not an ideal use of conditionals since ssh and winrm servers should have separate plays... tasks: - name: conditionally restart SSH servers commmand: /sbin/shutdown -r when: ansible_connection == 'ssh' or ansible_host == 'sample.xyz.com'
register
: Used to store the output of a module.... tasks: - shell: cat /etc/resolv.conf register: name_servers - shell: echo 'nameserver 192.168.0.0 >> /etc/resolv.conf' when: name_servers.stdout.find('192.168.0.1') == -1
-
Loops
- There are
with_items
: A loop that will take each entry of the with_items array and substitute it with theitems
variable... tasks: name: Install Yum Dependencies yum: name='{{ items }}' state=present with_items: - httpd - git - nodejs
-
Includes
includes
: Can be used to include playbooks, tasks, or variables from another YAML file.# vars.yml greeting: Hello salutation: Hasta La Vista Baby
# conversation_tasks.yml - name: Say hello command: echo '{{ greeting }} World!' - name: Say Good-bye: command: echo '{{ salutation }}'
# converse.yml - name: A Brief Conversation hosts: localhost vars_files: - vars.yml tasks: - include conversation_tasks.yml
-
Roles
- Ansible Roles use a predefined folder structure and standard naming convention to organize an Ansible Project.
- Each Role must have a folder under the
roles
directory in your project. - Each Role contains the following folders.
tasks
: The main list of tasks executed by the role.handlers
: Handlers that can be used inside and outside of the role.defaults
: The default variables used in this role when the variable is not explicitly defined.vars
: Additional variables to be used in the role.files
: Files that can be deployed via this role.templates
: Templats that can be deployed from this role.meta
: A place for meta data about the role.Projects/ | inventory.txt . master_playbook.yml | roles/ . | | . webservers/ . | | files | . . templates . | | tasks | . . vars . | | | . databases/ . | | files | . . templates . | | tasks | . . vars . | |
roles
: assigns a role at the play level so there can be multiple roles in a playbook.- name: Setup Firewall Servers hosts: web_servers roles: - webservers
-
Advanced topics
- Preparing Windows servers
- Ansible Control machines can only be Linux Machines
- winrm has to be enabled for windows systems to be valid targets.
- Ansible Galaxy
- Contains the
ansible-galaxy
cli tools - A repository for Ansible Roles similar to the Docker Store
- Contains the
- Patterns
- Regex like patterns
- Dynamic Inventory
- use
ansible-playbook -i
to specify an inventory file or python script
- use
- Developing Modules
- Written in Python
- module templates can be found on the Ansible Docs.
- Preparing Windows servers