Chapter 1
Introduction
1.1 About Ansible
Ability
to give instructions to hundreds of servers.
Perform
four different functions which are not standalone.
·
Change
Management
·
Provisioning
·
Automation
·
Orchestration
1.2 Change Management
1.3 Provisioning
·
transition from one system state to another
system state that's expected and this is generally used in building servers.
·
It’s actually installing and configuring the
software each time rather than just copying the image which is not a clean
method.
e.g: On a server having basic operating system, we want to
make it a Web server. Below are the automated steps.
1> Installation
2> Copy configuration
3> Copy web files or some testing codes
4> Install security updates
5> Start the service
1.4 Automation
·
Automation is the most basic part of Ansible
·
Can update files, change network devices, update
the system
E.g:
There is urgent requirement to update a security file on 500
servers ASAP.
Just update the playbook and it will be pushed
automatically. If there is any issue with a particular server, remove it from
load balancer and investigate the cause.
1.5 Orchestration
·
It’s different from automation. Automation used
on a single system whereas orchestration takes the automation and coordinates
the process between multiple systems.
·
Cannot have orchestration without automation.
1.6 Why Use Ansible
·
Agentless
·
Very less dependencies -. More stable, very fast
to implement
·
No database requirement make it portable. Can
move from system to system.
·
No need of DBA to manage performance, indexes or
backups, or dealing with software upgrades when you're trying to upgrade or
update it.
·
Its clean – after playbooks finishes it tasks, modules
and software that was running on it is now gone after it completes its task.
·
Upgrade is easy as there is no other systems
dependencies. No schema updates on a database server or deployment of agent
upgrades.
1.7 YAML
·
It’s not Yet Another Markup Language
·
A Markup language is where you define the kind
of text or the data that you're entering.
·
it's more of the structure of the formatting of
the text than anything else.
1.8 Built-in Security
·
Primary Mode of communication – SSH
·
So, no need to waste time over setup and
security issues
·
Understands using root and on those systems that
can’t use roots. E,g: Ubuntu
·
Ubuntu – uses built in sudo to run its plays.
·
Ansible Vault: encrypt passwds and other
confidential information while still allowing Ansible to use it
·
No need to maintain PKI (Passwd Key Infra) as it
uses SSH.
Chapter 2
Architecture and Process Flow
2.1 System Requirement
The process starts
by having an Ansible control server talking to a remote system(client).
Control Server:
Ansible is installed here.
Deploys all plays and playbooks.
Minimum Requirement:
1>
Ansible is python based. Python 2.6 or higher is
required.
2>
Operating System – Unix or Linux type of
environment.
3>
SSH should be running.
Note: Python 3.x is not supported but don’t uninstall it.
2.2 Components Overview
Five basic components of Ansible's processing:
1>
Inventory
( can be considered Ansible hosts file )
-
A text file that describes the servers and
systems
-
Need to define host-level variables, groups and roles
here.
-
User account details for each systems can be
defined here
-
This file can be static text file or an
executable script to get the managed systems, so no need of a database for
Ansible.
2> Modules
-
Command center of the system
-
Each modules contain set of actions that can be
performed.
-
Core Modules – Ansible developers will fully
support them
-
Extra Modules – comes from community
Ansible-Galaxy
3> Playbook
-
Collection of plays
-
can install an application, copy over a
configuration file and then switch over to your database servers and configure
the databases in that order
e.g: Yum module can
run on Redhat but can’t be run on Debian. For Debian apt module need to be
used. We can add logic in Playbook to select the module accordingly.
4> Configuration File
-
sets up the global configuration variables for
Ansible, and allows to change its defaults
-
how many parallel operations can your system
perform at the same time, or whether you want Ansible to tell you if a host was
skipped or not - these items can be configured here
5> Python
-
Ansible takes all of those components and kind
of pushes it through the Python component to build a package to be delivered to
the remote systemsb
-
Python framework also helps in building
variables
-
Three kind of variables
-
Host Variables: define in the inventory file
where host is defined and is specific to this host only
-
Fact Variables: environment data of the host
-
Dynamic Variables: created during the course of
playbook and destroyed after that.
2.3 Process of Execution and Flow
The process that Ansible takes in order to talk to remote
server.
Evaluate the playbook ->
Playbook identifies the systems to deploy to, and the
modules to grab ->
Playbook packages everything up into a neat little Python
package ->
Identifies the systems to deploy to using the inventory
module ->
Establish an SSH session to the remote system->
Deploy the package according to the Ansible configuration
parameters in /tmp directory on remote system->
Python framework on the remote system will then execute this
package ->
PF will identify which steps completed successfully ->
Remote system will return the results back to Ansible using
JSON->
And before the SSH connection is terminated, the package
will be deleted.
Note: Ansible can
be used to target multiple machines at the exact same time
2.4 Execution Types
Two types:
1>
Default : Remote execution
2>
Local execution:
the local Ansible server is actually
executing the package, not the remote system that is targeted as it can't
receive a Python module. Will discuss this later in
detail.
Chapter 3
Setting up Environment
3.1 Installing Ansible
Installation:
Download file from below link:
https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
#yum install ./epel-release-latest-7.noarch.rpm
Below command will update all the packages. It is required
before we go and install ansible.
#yum update
#yum install ansible
3.2 Start Using Ansible
# mkdir /exercise1
# cat inventory
192.168.56.102
# ansible
192.168.56.102 -i inventory -u root -m ping -k
SSH password:
192.168.56.102
| FAILED! => {
"failed": true,
"msg": "Using a SSH password
instead of a key is not possible because Host Key checking is enabled and
sshpass does not support this. Please
add this host's fingerprint to your known_hosts file to manage this host."
}
The issue is because from this system we never did ssh to
192.168.56.102 system. So, the entry in known_hosts file is not there. We need
to create it first.
# ssh
root@192.168.56.102
The
authenticity of host '192.168.56.102 (192.168.56.102)' can't be established.
ECDSA
key fingerprint is d3:8b:10:b5:ef:a2:c1:30:de:e5:b1:69:4a:12:52:db.
Are you
sure you want to continue connecting (yes/no)? yes
Warning:
Permanently added '192.168.56.102' (ECDSA) to the list of known hosts.
root@192.168.56.102's
password:
We can see the file and entry inside it.
# cd /root/.ssh
# ls
known_hosts
# more known_hosts
192.168.56.102
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyN
TYAAABBBD8bNX2TllC8n1lYbjTPuIOHJtlOaic6+rZmvjNHMwEOXcPqElAJzWkw/79Gu7bnpGVPYV98T
Sk1Y//BUxwK338=
Now go back to /exercise and run the ping command again.
# cd exercise1/
# ansible
192.168.56.102 -i inventory -u root -m ping -k
SSH
password:
192.168.56.102
| SUCCESS => {
"changed": false,
"ping": "pong"
}
# ssh root@192.168.56.103
#ansible all -i
inventory -u root -m ping -k
For Debugging:
# ansible 192.168.56.102 -i inventory -u root -m ping -k
-vvv
Run command
# ansible
192.168.56.102 -i inventory -u root -m command -a "yum list
installed" -k
No need to mention module command, command is the
default module.
# ansible 192.168.56.102 -i inventory -u root -a
"yum list installed" -k
Difference between
Command Module and Shell Module both run shell commands.
Command Module: Run executable inside python.
Shell Module: Run executables inside shell. It allows to
use SHELL variables. E.g: $HOME, $PATH, etc
Chapter 4
Inventory and Configuration
Inventory Fundamentals
·
Can be present anywhere on the server, path need
to be specified properly.
Behavioral Parameters: Configuration can be applied to a system or
group of systems.
Groups: We can group our systems together. E.g: Test servers, prod
servers
Groups of Groups: E.g: East data centre, West data centre.
Assign Variables: E.g: Create variable called ntp server and attach to a group.
Scaling out using multiple files: Use multiple files to scale up
inventory file.
Static/Dynamic: Can create inventory file dynamically and ansible
can use this file.
Sample File:
Inventory Basics
# cat inventory
ansible2
ansible_ssh_host=192.168.56.102 ansible_ssh_user=root ansible_ssh_pass=creative
# ansible ansible2 -i inventory
-m ping
Now create group:
# cat inventory
ansible2
ansible_ssh_host=192.168.56.102 ansible_ssh_user=root ansible_ssh_pass=creative
ansible3
ansible_ssh_host=192.168.56.103 ansible_ssh_user=root ansible_ssh_pass=creative
[testservers]
ansible2
ansible3
# ansible
testservers -i inventory -m ping
Now create group
of groups
# cat inventory
ansible2
ansible_ssh_host=192.168.56.102 ansible_ssh_user=root ansible_ssh_pass=creative
ansible3
ansible_ssh_host=192.168.56.103 ansible_ssh_user=root ansible_ssh_pass=creative
[testservers]
ansible2
[devserver]
ansible3
[datacenter:children]
testservers
devserver
# ansible
datacenter -i inventory -m ping
Now create a parameter group
# cat inventory
ansible2
ansible_ssh_host=192.168.56.102
ansible3
ansible_ssh_host=192.168.56.103
[testservers]
ansible2
[devserver]
ansible3
[datacenter:children]
testservers
devserver
[datacenter:vars]
ansible_ssh_user=root
ansible_ssh_pass=creative
# ansible
datacenter -i inventory -m ping
Creating Prod
and Dev Env:
# pwd
/exercise1/production
# ls -ltr
drwxr-xr-x. 2 root root
6 Apr 24 08:27 host_vars
-rw-r--r--. 1 root root 241 Apr 24 08:35 inventory_prod
drwxr-xr-x. 2 root root
33 Apr 24 08:37 group_vars
# cat group_vars/all
---
# This is all file
username: all_username
# ansible
testservers -i inventory_prod -m user -a "name={{username}}
password=12345"
ansible2
| SUCCESS => {
"changed": true,
"comment": "",
"createhome": true,
"group": 1000,
"home": "/home/all_username",
"name": "all_username",
"password":
"NOT_LOGGING_PASSWORD",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1000
}
# cat
group_vars/testservers
---
# comments here
username: group_user
# ansible testservers -i inventory_prod -m user -a
"name={{username}} password=12345"
ansible2 | SUCCESS => {
"changed": true,
"comment": "",
"createhome": true,
"group": 1001,
"home": "/home/group_user",
"name": "group_user",
"password":
"NOT_LOGGING_PASSWORD",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1001
}
Note:
Group variable take precedence on all user.
# cat
host_vars/ansible2
---
#comments
here
username:
ansible3
# ansible
testservers -i inventory_prod -m user -a "name={{username}}
password=12345"
ansible2
| SUCCESS => {
"changed": true,
"comment": "",
"createhome": true,
"group": 1002,
"home":
"/home/ansible3",
"name": "ansible3",
"password":
"NOT_LOGGING_PASSWORD",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1002
}
Ansible Config
·
Defines how ansible works.
·
Can change how many parallel connection Ansible
can make
·
Can handle unknown ssh keys
Configuration Settings:
Order-of-Operations
As multiple teams use Ansible in same Env, so there is
order of operations rule to load configuration.
1. $ANSIBLE_CONFIG: First thing - Env
Variable, if variable exists Ansible load the files it points to first.
2. ./ansible.cfg : Second place, in the current directory. This is
commonly used when you're sharing plays and playbooks between multiple members
or your team using, let's say, a version repository like Git. If they're
running Ansible on their local machines and using Git to synchronize all their
data, you can add the configuration file with that playbook, and the
configuration will move with it.
3. ~/.ansible.cfg : Home directory of
currently logged in account. This place is best used when you're using a shared
system and you want to run your Ansible plays, but you want to configure it for
each user specification.
4. /etc/ansible/ansible.cfg: Global
configuration file.This file can be created only if we use “pip” or package
manager to install ansible. If you installed Ansible and building by source,
this file won't exist, but you can still put it in there.
Environment Variables Overrides:
$ANSIBLE_<configsetting>
Overrides specific settings by
prefixing ANSIBLE_ to the name
#export ANSIBLE_FORKS=10
Great way to override specific
settings on-the fly.
Now we try to disable the host
key checking. For that first delete the ssh key footprint from known_hosts
file.
# cat ansible.cfg
[defaults]
host_key_checking=True
# ansible ansible2 -i inventory_prod -m ping
ansible2 | FAILED! => {
"failed": true,
"msg":
"Using a SSH password instead of a key is not possible because Host Key
checking is enabled and sshpass does not support this. Please add this host's fingerprint to your
known_hosts file to manage this host."
}
Now make the
host_key_checking=False
# ansible ansible2 -i inventory_prod -m ping
ansible2 | SUCCESS => {
"changed": false,
"ping":
"pong"
}
As we know that environment
variable is having highest precedence, we try to override the variable
host_key_checking.
#export ANSIBLE_HOST_KEY_CHECKING=True
#echo $ANSIBLE_HOST_KEY_CHECKING
Delete the ssh footprint
#vi /root/.ssh/known_hosts
# ansible ansible2 -i inventory_prod -m ping
ansible2 | FAILED! => {
"failed": true,
"msg":
"Using a SSH password instead of a key is not possible because Host Key
checking is enabled and sshpass does not support this. Please add this host's fingerprint to your
known_hosts file to manage this host."
}
Working with Python3 based system
#which python
/usr/bin/python
# whereis python
python:
/usr/bin/python /usr/bin/python2.7 /usr/lib/python2.7 /usr/lib64/python2.7
/etc/python /usr/include/python2.7 /usr/share/man/man1/python.1.gz
Since, here we are having python 2.7 so our commands will not
fail, but if we use python3 then ansible commands will fail.
In case if python3 is installed, no need to uninstall it and
then install 2.7. Just run the python2.7 executable or use the below env
parameter.
ansible_python_interpreter=/usr/bin/python2.7
Chapter 5
Ansible Module
Fundamentals
·
Are used inside your plays, playbooks, or adhoc
commands
·
Provide the necessary steps for Ansible to
follow in order to accomplish something
·
Its like a command center, it holds all the
possibilities in a single repository for you to pick and use whenever you need
it
Types:
1>
Core
2>
Extra
3>
Deprecated
To list and check
module present
#ansible-doc -l
#ansible-doc <name>
#ansible-doc cloudtrail
#ansible-doc -s cloudtrail
Copy Module
·
Copies a file from local box to remote system
·
Has “backup” capability
·
Can do validation remotely
Fetch Module
·
Pulls a file from remote host to local system
·
Can use md5 checksums to validate
Yum Module
·
Manages installed applications on Redhat-based
systems
·
Can install, update or delete packages
·
Can update entire system
Service Module
·
Can stop, start or restart services
·
Can enable services to start on boot
Chapter 6
Hands-on Modules
Yum Module
#cat
/exercise/inventory
ansible2
ansible_ssh_host=192.168.56.102
ansible3
ansible_ssh_host=192.168.56.103
[testservers]
ansible2
[devserver]
ansible3
[datacenter:children]
testservers
devserver
[datacenter:vars]
ansible_ssh_user=root
ansible_ssh_pass=creative
#ansible-doc yum
=name
-state
Below Command will take around 5 mins to complete.
# ansible testservers
-i inventory -m yum -a "name=httpd state=present"
ansible2 |
SUCCESS => {
"changed": true,
"msg": "",
"rc": 0,
"results": [ Output
Truncated.
Run the command again, changed value will be “false”.
# ansible testservers
-i inventory -m yum -a "name=httpd state=present"
ansible2
| SUCCESS => {
"changed": false,
"msg": "",
"rc": 0,
"results": [
"httpd-2.4.6-45.el7.centos.4.x86_64 providing httpd is already
installed"
]
}
Service Module
First we check the man page
#ansible-doc service
-
enabled
Whether the service should start on
boot. *At least one of
state and enabled are required.*
(Choices: yes, no)[Default: (null)]
= name
Name of the service.
- state
`started'/`stopped' are idempotent
actions that will not run
commands unless necessary.
Now run the command on ansible server to start the
service on client.
# ansible
testservers -i inventory -m service -a "name=httpd state=started"
ansible2
| SUCCESS => {
"changed": true,
"name": "httpd",
"state": "started",
"status": {
My-Sql Server
# ansible devserver
-i inventory -m yum -a "name=mariadb-server state=present"
ansible3 |
SUCCESS => {
"changed": true,
"msg": "",
"rc": 0,
"results": [ Output
Truncated
Now start the service:
# ansible
devserver -i inventory -m service -a "name=mariadb state=started"
ansible3
| SUCCESS => {
"changed": true,
"name": "mariadb",
"state": "started",
"status": {
Firewalld Service
If you try to open 192.168.56.102 to open in browser, it
will not open. As firewalld is blocking it.
Stop this service on both clients
# ansible testservers:devserver
-i inventory -m service -a "name=firewalld state=stopped"
ansible2
| SUCCESS => {
"changed": true,
"name": "firewalld",
"state": "stopped",
"status": {
ansible3
| SUCCESS => {
"changed": true,
"name": "firewalld",
"state": "stopped",
"status": {
Now open again in browser ( http://192.168.56.102)
We used here testservers:devserver, will see in next session
what is it.
Host/Group Target Patterns
Setup Module
·
Gather facts on remote systems
·
Used in playbooks
# ansible testservers
-i inventory -m setup
ansible2
| SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses":
[
"10.0.2.15",
"192.168.56.102"
"ansible_architecture":
"x86_64",
"ansible_bios_date":
"12/01/2006",
"ansible_bios_version":
"VirtualBox",
Use Filter for refined output
# ansible
testservers -i inventory -m setup -a
"filter=ansible_enp*"
ansible2
| SUCCESS => {
"ansible_facts": {
"ansible_enp0s3": {
"active": true,
"device":
"enp0s3",
"features": {
"busy_poll":
"off [fixed]",
"fcoe_mtu": "off
[fixed]",
"generic_receive_offload": "on",
"generic_segmentation_offload": "on"
"ipv4":
{
"address":
"10.0.2.15",
"broadcast":
"10.0.2.255",
"netmask":
"255.255.255.0",
"network":
"10.0.2.0"
Another example:
# ansible
testservers -i inventory -m setup -a
"filter=ansible_mounts"
ansible2
| SUCCESS => {
"ansible_facts": {
"ansible_mounts": [
{
"device":
"/dev/mapper/cl-root",
"fstype":
"xfs",
"mount":
"/",
"options":
"rw,seclabel,relatime,attr2,inode64,noquota",
"size_available":
7227125760,
"size_total":
8466202624,
"uuid":
"0fd71a9e-2428-4083-b883-763de03e754b"
},
{
"device":
"/dev/sda1",
"fstype":
"xfs",
"mount":
"/boot",
"options":
"rw,seclabel,relatime,attr2,inode64,noquota",
"size_available":
872513536,
"size_total":
1063256064,
"uuid":
"eae9c880-0bc0-4713-bb1d-d8e71ac6dfd9"
}
]
},
"changed": false
}
Collect All data from the servers:
Below command will create a directory setup and inside it
create file for each server having full system data.
# ansible all -i
inventory -m setup --tree ./setup
#ls -ltr setup
-rw-r--r--.
1 root root 14505 Apr 26 11:14 ansible2
-rw-r--r--.
1 root root 14401 Apr 26 11:14 ansible3
#cd setup
#cat ansible2
{"ansible_facts":
{"ansible_all_ipv4_addresses": ["10.0.2.15",
"192.168.56.102"], "ansib
le_all_ipv6_addresses":
["fe80::a00:27ff:fe5a:6ca7", "fe80::23b2:78dc:3be8:9a10",
"fe80:
:1baa:9868:f581:9efa",
"fe80::4304:30b4:68df:8672"], "ansible_architectur
Output Truncated
No comments:
Post a Comment