How to Configure Ansible

Ansible Configuration

Certain settings in Ansible are adjustable via a configuration file. The stock configuration should be sufficient for most users, but there may be reasons you would want to change them.
Changes can be made in global ansible.cfg file /etc/ansible/ansible.cfg or you can create your own ansible.cfg (current working directory) which will have higher precedence over the global file. 

$ cat ansible.cfg 
[defaults]
hostfile = inventory_prod
host_key_checking=False
#ask_sudo_pass = True
This ansible.cfg file is located at the same place where you have the inventory file.
Explanation
1. [defaults] is the main section of ansible.cfg
2. hostfile will have the value where inventory file is located if it’s in the current working directory specify the name or else complete path of the file should be specified. After mentioning inventory path in ansible.cfg its not required to pass the inventory path with -i option.
3. host_key_checking=False tells ansible to not check the host fingerprints before doing ssh to the host. There long list of ansible config parameters that you can choose from. List of ansible configuration is specified in ansible documentation.
https://docs.ansible.com/ansible/intro_configuration.html

Setup - Gathers facts about remote hosts
It can be executed directly by /usr/bin/ansible to check what variables are available to a host. Ansible provides many facts about the system, automatically.
$ ansible -m setup web1
web1 | SUCCESS =>{
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"10.0.2.15",
"192.168.1.13"
],
"ansible_all_ipv6_addresses": [
"fe80::a00:27ff:fe15:d519",
"fe80::a00:27ff:febf:5936"
],
"ansible_architecture": "x86_64",
"ansible_bios_date": "12/01/2006",
"ansible_bios_version": "VirtualBox",
"ansible_cmdline": {

output trimmed
"ohai_uptime": "1 hours 38 minutes 26 seconds",
"ohai_uptime_seconds": 5906,
"ohai_virtualization": {
"role": "guest",
"system": "vbox"
}
},
"changed": false


# Display facts from all hosts and store them indexed by I(hostname) at C(/tmp/facts).
# ansible all -m setup --tree /tmp/facts
# Display only facts regarding memory found by ansible on all hosts and output them.
# ansible all -m setup -a 'filter=ansible_*_mb'
# Display only facts returned by facter.
# ansible all -m setup -a 'filter=facter_*'
# Display only facts about certain interfaces.
# ansible all -m setup -a 'filter=ansible_eth[0-2]'
# Restrict additional gathered facts to network and virtual.
# ansible all -m setup -a 'gather_subset=network,virtual'
# Do not call puppet facter or ohai even if present.
# ansible all -m setup -a 'gather_subset=!facter,!ohai'
# Only collect the minimum amount of facts:
# ansible all -m setup -a 'gather_subset=!all'
# Display facts from Windows hosts with custom facts stored in C(C:\custom_facts).
# ansible windows -m setup -a "fact_path='c:\custom_facts'"

Playbooks

Playbooks are Ansible’s configuration, deployment, and orchestration language. They can describe a policy you want your remote systems to enforce, or a set of steps in a general IT process.
If Ansible modules are the tools in your workshop, playbooks are your instruction manuals, and your inventory of hosts are your raw material.
At a basic level, playbooks can be used to manage configurations of and deployments to remote machines. At a more advanced level, they can sequence multi-tier rollouts involving rolling updates, and can delegate actions to other hosts, interacting with monitoring servers and load balancers along the way.
Playbooks are a completely different way to use ansible than in adhoc task execution mode, and are particularly powerful. While you might run the main /usr/bin/ansible program for ad-hoc tasks, playbooks are more likely to be kept in source control and used to push out your configuration or assure the configurations of your remote systems are in spec.
Playbook Language Example
Playbooks are expressed in YAML format and have a minimum of syntax, which intentionally tries to not be a programming language or script, but rather a model of a configuration or a process. Each playbook is composed of one or more ‘plays’ in a list. The goal of a play is to map a group of hosts to some well-defined roles, represented by things ansible calls tasks. At a basic level, a task is nothing more than a call to an ansible module.
Playbook for starters
$ cat web_db.yml
---
- hosts: webservers
become: yes
tasks:
- name: Ensure Apache installed
yum: name=httpd state=present
- name: Creates directoy
file: path=/var/www/html/ansible state=directory
- name: Ensure Apache is running
service: name=httpd enabled=yes state=started
- hosts: dbservers
become: yes
tasks:
- name: Ensure mysql server installed
yum: name=mysql-server state=present
- name: Ensure mysql running
service: name=mysqld state=started

YAML Basics
For Ansible, nearly every YAML file starts with a list. Each item in the list is a list of key/value pairs, commonly called a “hash” or a “dictionary”. So, we need to know how to write lists and dictionaries in YAML.
There’s another small quirk to YAML. All YAML files (regardless of their association with Ansible or not) can optionally begin with --- and end with .... This is part of the YAML format and indicates the start and end of a document.
All members of a list are lines beginning at the same indentation level starting with a "- " (a dash and a space):
# A list of tasty fruits
fruits:
- Apple
- Orange
- Strawberry
- Mango
...
A dictionary is represented in a simple key: value form (the colon must be followed by a space):
# An employee record
martin:
name: Martin D'vloper
job: Developer
skill: Elite
More complicated data structures are possible, such as lists of dictionaries, dictionaries whose values are lists or a mix of both:
# Employee records
- martin:
name: Martin D'vloper
job: Developer
skills:
- python
- perl
- pascal
- tabitha:
name: Tabitha Bitumen
job: Developer
skills:
- lisp
- fortran
- erlang
Dictionaries and lists can also be represented in an abbreviated form if you really want to:
---
martin: {name: Martin D'vloper, job: Developer, skill: Elite}
fruits: ['Apple', 'Orange', 'Strawberry', 'Mango']

First Playbook exercise.We need two centos 6 servers for this exercise. We will deploy a apache webserver to web1 with a sample website and MySQL db to db1 node.
Inventory file

$ cat inventory-dev
web1 ansible_ssh_host=192.168.1.13
db1 ansible_ssh_host=192.168.1.14
[webservers]
web1
[dbservers]
db1
[datacenter:children]
webservers
dbservers
[datacenter:vars]
ansible_ssh_user=vagrant
ansible_ssh_pass='vagrant'
Ansible configuration file
$ cat ansible.cfg
[defaults]
hostfile=inventory-dev
host_key_checking=False

Sample webpage
Playbook
$ cat web_db.yaml
---
- hosts: webservers
become: yes
tasks:
- name: Ensure Apache installed
yum: name=httpd state=present
- name: Creates directory
file: path=/var/www/html/ansible state=directory
- name: Deploy webpage to path=/var/www/html/ansible
copy: src=index.html dest=/var/www/html/ansible/ mode=0644
- name: Ensure Apache is running
service: name=httpd enabled=yes state=started
- name: Flush all temporary rules
service: name=iptables state=restarted
- name: Allow port 80/http access from anywhere
iptables:
action: insert
chain: INPUT
protocol: tcp
destination_port: 80
state: present
source: 0.0.0.0/0
jump: ACCEPT
- hosts: dbservers
become: yes
tasks:
- name: Ensure mysql server installed
yum: name=mysql-server state=present
- name: Ensure mysql running
service: name=mysqld state=started
- name: Ensure MySQL-python is installed
yum: name=MySQL-python state=present
- name: Create Database
mysql_db: name=devops state=present
- name: Create user named mint
mysql_user: name=mint password=12345 priv='*.*:ALL'state=present
Explanation
1. --- is not mandatory but specifies a start of YAML file
2. - hosts: webservers represent the host/group name where tasks will get executed. It is the start of a play.
3. become: yes tell ansible to execute all the tasks with sudo privileges older version of ansible has sudo:yes
4. tasks: specifies the list of task or modules that will be executed against webserver group.
5. - name: is not a mandatory option but will always help us read the output of task when executed. If -name option is not specified then the module name should start with a “ - ” for example “– yum:”
6. yum: is the name of the module that will get executed along with the arguments “name=httpd state=present” . If -name option is not provided then yum will begin with a “– “ that represents the element in the YAML list as specified below.
tasks:
- yum: name=httpd state=present
Ansible documentation gives very nice description of every module with examples.
https://docs.ansible.com/ansible/list_of_all_modules.html https://docs.ansible.com/ansible/yum_module.html
https://docs.ansible.com/ansible/file_module.html
https://docs.ansible.com/ansible/copy_module.html
https://docs.ansible.com/ansible/service_module.html https://docs.ansible.com/ansible/iptables_module.html

New and Old argument style
Old Style
tasks:
- yum: name=httpd state=present
New Style
tasks:
- yum:
name: httpd
state: present
1. iptables module modifies the systems firewall rule, knowledge of iptables is required to understand its options. We are allowing port 80/http access from everywhere.
2. - hosts:dbservers is the start of a next play that will get executed on dbservers group. As mentioned earlier playbook is the list of Plays, os -hosts: dbservers is just the second play in the playbook. Likewise we can have multiple plays in the same playbook.
3. mysql_db module is used to create/delete databases in mysql db service. https://docs.ansible.com/ansible/mysql_db_module.html
4. mysql_user module is used to create user in mysql db service. https://docs.ansible.com/ansible/mysql_user_module.html
NOTE: Its highly recommended to read ansible module documentation to understand more about modules used in the playbook.
Playbook Execution
ansible-playbook command is used to execute the playbook as shown below.

$ ansible-playbook web_db.yaml

PLAY [webservers] ****************************************************************
TASK [Gathering Facts] ***********************************************************
ok: [web1]

TASK [Ensure Apache installed] ***************************************************
changed: [web1]

TASK [Creates directory] **********************************************************
changed: [web1]

TASK [Deploy webpage to path=/var/www/html/ansible] ******************************
changed: [web1]

TASK [Ensure Apache is running] **************************************************
changed: [web1]

TASK [Flush all temporary rules] *************************************************
changed: [web1] TASK [Allow port 80/http access from anywhere] ***********************************
changed: [web1]

PLAY [dbservers] *****************************************************************
TASK [Gathering Facts] ***********************************************************
ok: [db1]

TASK [Ensure mysql server installed] *********************************************
changed: [db1]

TASK [Ensure mysql running] ******************************************************
changed: [db1]

TASK [Ensure MySQL-python is installed] ******************************************
changed: [db1]

TASK [Create Database] ***********************************************************
changed: [db1]

TASK [Create user named mint] ****************************************************
changed: [db1]

PLAY RECAP ***********************************************************************
db1 : ok=6 changed=5 unreachable=0 failed=0
web1 : ok=7 changed=6 unreachable=0 failed=0
Explanation
1. Playbook gets executed in top to down order. First play is PLAY [webservers].
2. TASK [Gathering Facts] is a default task that runs the setup module for every host in the play. We can disable gathering facts by specifying gather_facts: False in playbook as shown below.
---
- hosts: webservers
become: yes
gather_facts: False
Tasks:
1. If the -name option is used in the task then it will display the content from it.
2. changed: [web1] is a status message for the task, it means that the task made changes to the target host.
3. ok: [web1] means that the task has not made any changes on the target host. It could be due to the nature of the module which could be for information gathering like setup module. It could also mean that the system is in the same state for example httpd is already installed so it will return ok:
4. PLAY RECAP Display the summary of all the tasks got executed on all the hosts. unreachable display the number of hosts that does not have proper connectivity with ansible server. failed displays number of failed tasks.

For more information about Visualpath, visit www.visualpath.in and follow the company on Facebook and Twitter.

Comments