Here is a basic understanding of ansible configuration file, playbooks, modules, plugins, Handlers, Roles, Collections, and jinja2 Templates.
Ansible Configuration File
when you install, it creates a default configuration at the location :- /etc/ansible/ansible.cfg
but what if you want your custom config file outside of your playbook file ?
you can place your config file outside of your playbook file and specify the location of this configuration file through an environmental variable before running the ansible playbook.
ANSIBLE_CONFIG=/opt/ansibleweb.cfg ansible-playbook playbook.yaml
this time when a playbook runs, this time it will pick the custom config file.
and suppose you have configured all these files with different values for different different parameters, then which files will have what priority ?
the first priority will be for the configuration file you are specifying through environment variables
followed by the ansible.cfg in the current directory, where the ansible playbooks are running and then followed by the .ansible.cfg file in user home directory
and last the default configuration file.
Also if you want to change a single parameter for your playbook you can over-write the single parameter value by an environment variable.
you can set it up just right before executing the ansible playbook.
ansible-config list # to list all config files
ansible-config view # shows the current config file
ansible-config dump # shows the current settings
Ansible Inventory
Ansible needs to establish connection with the servers to work with them. There is no need of any agent to be installed in the target servers , That's why ansible is agentless. for Linux servers ansible use SSH based connectivity whereas for windows servers ansible use PowerShell remoting.
The Information about the target machines are being stored in an Inventory File. Ansible has it's default Inventory file located at /etc/ansible/hosts and if you don't create any new inventory file, ansible use it's default inventory file. we can specify our target machines in the inventory file
[common]
database_server1.learning.com
Loggingserver2.learning.com
webserver3.learning.com
[database]
database_server1.learning.com
database_server2.learning.com
database_server3.learning.com
[messaging]
messaging_server1.learning.com
messaging_server1.learning.com
messaging_server1.learning.com
we can add alias name for the servers by using ansible_host parameter.
database ansible_host=database_server1.learning.com
ansible_host is ana inventory parameter used to specify the FQDN or IP address of a server
Inventory parameters
there are multiple ansible inventory parameters are available.
ansible_connection-ssh/localhost/winrm
ansible_port-22
ansible_usr-root-admin
ansible_ssh_pass-mypassword
Inventory formats
INI
yaml
yaml format : Its more structured.
all:
childeren:
database:
hosts:
database_server1.learning.com
database_server2.learning.com
database_server3.learning.com
messaging:
hosts:
messaging_server1.learning.com
messaging_server1.learning.com
messaging_server1.learning.com
Verifying playbooks
we can use check mode and diff mode to verify our ansible playbooks.
check:
Using this mode you can do the DRY RUN of your playbook and no actual modification happens here.
ansible-playbook install-nginx.yml --check
Note: all ansible modules does not support check mode. If a task uses a module that does not support check mode then task will be skipped when you run the playbook in check mode.
**diff:
**Using diff mode you can check the difference in playbook before and after changing
ansible-playbook install-nginx.yml --diff
ansible-playbook install-nginx.yml --check --diff # check and diff option both
Syntax check:
This helps us to ensure our playbook syntax is error free.
ansible-playbook install-nginx.yml --syntax-check
ansible-lint:
It checks our code for potential issues, bugs and stylistic errors etc.
ansible-lint install-nginx.yml
Conditions:
we can use conditional statements like when to execute a particular task if the condition satisfies.
---
- name: install-nginx
hosts: all
tasks:
- name: install nginx on debian
apt:
name: nginx
state: present
when: ansible_os_family == 'Debian' and
ansible_distribution_version == "16.04"
- name: install nginx on Redhat
apt:
name: nginx
state: present
when: ansible_os_family == 'Redhat' or
ansible_os_family == 'SUSE'
we can use variables as well.
---
- name: install-multiple-packages.yml
hosts: all
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 }}"
register:
to record a output of one task we can use register directive. and we can use this for next task as required.
---
- name: send a email if service is down
hosts: all
tasks:
- name: check service status
command: service httpd status
register: result
- mail:
to: abinashmishra@005gmail.com
subject: service alerts
body: http is down
when: result.stdout.find('down') != -1
ansible facts
Variables related to remote systems are called facts in ansible. ansible facts are system defined variables that can be used in the playbooks. To see all available facts, add this task to a play:
- name: Print all available facts
ansible.builtin.debug:
var: ansible_facts
ansible facts collects information about the server during the execution of the playbook.
- name: install nginx
apt:
name: nginx=1.18.0
state: present
when: ansible_facts{os_family} == 'Debian' and ansible_facts{distribution_major_version} == '18'
another example:
- name: start service
service:
name: abiapp
state: started
when: environment == 'production'
loops:
loop is a looping directive that executes same task multiple number of times. Each time it runs, It store value of each item in the loop in a variable named item. and then you can simply replace the user name as variable like this '{{ item }}' general way:
- name: create users
hosts: localhost
tasks:
user: name=abi state: present
user: name=krishna state: present
user: name=john state: present
using loops:
- name: create users
hosts: localhost
tasks:
- user: name='{{ item.name }}' state: present UID: '{{ item.UID }}'
loop:
- name: abi
UID: 1234
- name: krishna
UID: 0001
- name: john
UID: 4567
with_*
- name: create users
hosts: localhost
tasks:
- user: name='{{ item.name }}' state: present UID: '{{ item.UID }}'
with_item:
- name: abi
UID: 0002
- name: krishna
UID: 0001
- name: john
UID: 4567
many other options:
with_file
with_url
with_mangodb
with_env
with_filetree
Modules
click here for ansible modules documentation page.
Idempotency:
An action which, when performed multiple times, has no further effect on its subject after the first time it is performed.
command:
executes a command on a remote node.
- name: add dns entry to resolve.conf
host: localhost
tasks:
- name: execute a command
command: date
- name: display a file content
command: cat abc.txt
script:
run a local script on a remote node after transferring it.
it works in 2 steps
copy script in all remote server nodes
execute the script in those nodes
- name: run a local script
host: localhost
tasks:
- name: execute a script
script: /usr/abi/abc.sh
service:
manage services such as srtart stop restart
- name: add dns entry to resolve.conf
host: localhost
tasks:
- name: start nginxservice
service:
name: nginx
state: started
or,
service: name=nginx state=started
lineinfile:
This module search for a line in a file and replace it or add if doesn't exist.
- name: add dns entry to resolve.conf
host: localhost
tasks:
- linefile:
path: /etc/resolve.conf
line: nameserver 10.250.0.1
plugins
In ansible plugin is a piece of code which augments ansible's core functionality.
Plugins can be used to enhance various functionality of ansible such as inventory, filters, callback and modules etc.
click here for ansible plugin documentation page
dynamic inventory plugin: It helps ansible to fetch data from various sources like cloud provider
module plugin: Modules are the main building blocks of Ansible playbooks. Although we do not generally speak of “module plugins”, a module is a type of plugin.
action plugin: Action plugins act in conjunction with modules to execute the actions required by playbook tasks. They usually execute automatically in the background doing prerequisite work before modules execute.
lookup plugin - fetch data from external sources like databases and APIs and allow you to use the data in your playbook.
filter plugins: It manipulates data. With the right filter, you can extract a particular value, transform data types and formats, perform mathematical calculations etc.
connection plugin: It helps ansible to connect various target system like SSH, WinRM, docker
Callback plugins : It allows you to capture events and perform custom actions during execution of playbook
Also we have modules and plugins index to check what to use and how to