What is Ansible? 
 
 
Ansible is simple, fast, complete, effecient and secure
    
Ansible is... 
 
  
Application Deployment
Multi-Tier Orchestration
Configuration Management
1. Ansible is a powerful automation engine.
2. It's several tools in one: Application deployment, multi-Tier orchestration, configuration management and even provisioning.
 
 
     
 
 
    Simple   
Easy  to write, read, maintain and evolve- without writing scripts or custom code
Ansibles automation language is easy to write, read, maintain and evolve because you to have to write scripots or use custom code. 
This allows sysadmins, developers, and IT managers to complete automation projects in hours, not weeks. 
 
 
    FAST   to learn and setup 
1. Ansible is fast to learn.If you are a system admin or a developer, you can be automating in under 30 minutes.You can forget how it works and focus on what you want to do.
2. Setup is also fast because you don't have to install agents to manage machines. It relies on SSH. As long as SSH is installed, you are ready to automate.
   
Efficient 
Doesn't require a custom agent or software to install.
Ansible runs on OpenSSH.
1. With no additional software infrastructure, you don't have to
worry about managing the management tool.
2. That means anywhere SSH goes, Ansible goes.
3. It doesn't suck memory or CPU resources when it is not in use.
4. Designed from day one to automate no-downtime rolling updates
and multi-tier orchestration.
 
  
    
Secure 
 
No agent
SSH transport
Ansible plays can be read by anyone
1. It doesn't need additional ports or root level daemons.
2. It uses built-in OS authentication for better security - login
as who you are, sudo if you want to sudo.
3. You can work with tools like Kerberos, LDAP, and sssd.
4. OpenSSH is the most peer-reviewed security component around.
5. This makes it auditable. You know what you're automating,
and bugs have nowhere to hide.
 
  
    
        Inventory 
     
    
Ansible works against multiple systems in your infrastructure at the same time. It does this by selecting portions of systems listed in Ansible’s inventory file, which defaults to being saved in the location /etc/ansible/hosts. 
 
  
    
        Hosts 
     
    
A host is simply a remote machine that Ansible manages. They can have individual variables assigned to them, and can also be organized in groups. All hosts have a name they can be reached at (which is either an IP address or a domain name) and optionally a port number if they are not to be accessed on the default SSH port. 
  
    
        Groups 
     
    
A group consists of several hosts assigned to a pool that can be conveniently targeted together, and also given variables that they share in common. 
  
    
        Playbook 
     
    
Playbooks are the language by which Ansible orchestrates, configures, administers, or deploys systems.  Playbooks contain 
Plays 
 . 
  
    
        Play 
 
A play is a mapping between a set of hosts selected by a host specifier and the 
tasks 
  which run on those hosts to define the role that those systems will perform. There can be one or many plays in a playbook. 
  
    
        Tasks 
 
Tasks combine an action with a name and optionally some other keywords (like looping directives). Tasks call 
modules 
 .  
  
    
        Modules 
     
    
Modules are the units of work that Ansible ships out to remote machines. Modules can be implemented in any language. Modules just have to return JSON or simple key=value pairs. Once modules are executed on remote machines, they are removed, so no long running daemons are used. Ansible refers to the collection of available modules as a ‘
library 
 ’.
 
  
    
        Library 
 
A collection of modules made available to /usr/bin/ansible or an Ansible playbook.
 
 Example 
Ansible Architecture 
 
     
 
    
Remote Execution 
 
Replacement for traditional systems administration tasks  
 
Checking system responsiveness and uptime 
 
Gathering information about a collection of systems 
 
Replace one off rsync scripts, fabric, or terminal multiplexing 
 
 
Ansible provides a command-line tool and framework capable of 
executing over a large number of hosts, eliminating the need for 
systems administrators to multiplex terminal sessions via SSH to 
execute concurrent tasks across multiple hosts.  What may have 
been done in bash scripts, rsync scripts, etc. can be done via 
ad-hoc one-liners in the shell.
 
     
 
Remote Execution  
ansible -m user -a "name=bob state=present" webservers
 
ansible -m apt -a "pkg=apache2 state=present" webservers
 
Example 1 is adding a user to all the systems defined in the 
webservers group. Example 2 is installing the apache2 package 
on all systems defined in the webservers group.
 
    
Config Management 
 
     
Lengthy system configuration, to include adding users, ssh keys, installing and configuring services, and bootstrapping systems to a given state. 
 
 
"Configuration remediation" Consistent server configuration. Removes manual configuration errors. 
 
 
Servers need to be configured; Ansible configures servers.  
Using a combination of imperative and declarative syntax 
[described in detail--maybe using the GPS analogy], using 
concepts such as tasks, roles, plays, and playbooks, complex 
machine configurations are being assembled and converged by 
the Ansible toolchain rather than manually by administrators.  
Configuration is either set manually by the author or dynamically at runtime by Ansible, resulting in consistent configuration across large server sets.
 
    
Application Deployment and Orchestration 
 
Ansible can be used to replace various deployment and orchestration tools.
 
Deploy your custom application. 
 
 
 
 
Replacement for Capistrano and Fabric (i.e., git deployments) 
 
 
 
 
Good for large, complex environments 
 
 
 
    Application Development:  Two Schools of Thought 
Rolling Release 
Remove node from production, update components, and put back into rotation. 
Fresh Start 
Deploy entirely new infrastructure and replace current environment wholesale. 
 
    
Provisioning Infrastructure Dynamically 
 
Infrastructure is Data. 
 
You can provision to various clouds. 
 
Dynamic Inventory plugins for various providers (Rackspace, Amazon, Digital Ocean, OpenStack, Eucalyptus, etc.) 
 
 
Cover the various ways that infrastructure can be provisioned 
using Ansible. Mention that there are modules that provide 
he ability to deploy to various clouds. Include a high level 
overview of the dynamic inventory plugin system. (Creating 
Infrastructure is the same as Configuring Infrastructure.)
 
 What is your team currently using for: 
Application Deployment 
Multi-Tier Orchestration 
Configuration Management 
Have the class search the ansible documention and come up 
with something that Ansible does. Be that a specific module, 
or a high level concept.
  System Requirements 
Control machine: 
Linux, BSD, OS X (Not Windows!)
Python 2.6 or 2.7 
Target machines: 
Linux, BSD, OS X, Windows
Python 2.4 or greater (2.5 or greater recommended)  
 Installation 
CentOS 7:
Must configure EPEL (if not already setup)
$ sudo yum install ansible 
Ubuntu:
$ sudo apt-get install software-properties-common
$ sudo apt-add-repository ppa:ansible/ansible
$ sudo apt-get update
$ sudo apt-get install ansible  Mac:Use pip 
 $ sudo pip install ansible 
 
Ansible Key Components  
What makes Ansible tick!
Let's delve into the concepts that drive Ansible.
  
Key components of Ansible 
Inventory 
Modules/Tasks 
Plays 
Playbooks 
 
These are some very key components you'll need to understand for using Ansible.
 
 
  
Inventory 
 
 
Ansible works against multiple systems in your infrastructure
at the same time. It does this by selecting portions of systems
listed in Ansible's inventory.
  
Inventory   concepts 
Hosts 
Groupings 
Inventory-specific data 
Static or Dynamic sources 
 
Breaking down by topic, we'll cover four parts (Note the listed)
 
Inventory:  Hosts 
 
Hosts can have Ansible specific attributes such as: 
Connection IP addresses and ports 
 
 
Remote user and sudo user 
 
 
Connection types (Paramiko, OpenSSH, local, etc.) 
 
 
Further limit targeted hosts using --limit 
 
 
You have a lot of flexibility when you specify hosts in Inventory. You can
set variables to determine connection types, host ip addresses and fully-qualified
domain names, remote users and sudo users as well as any other variable you may 
come up with to use when interacting with your hosts, such as "apache_port" or 
"mysql ports".
  
Inventory:  Hosts  
 
This is an example of a host entry in an inventory file: 
web1.example.com ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50
 
As you can see, we have a host name, a specified SSH port and IP Address.
  
Inventory:  
Host  Entries Using Ranges 
You can have ranges of machine names or letters like this:
www[01:50].example.com ansible_ssh_port=5555
db-[a-f].example.com ansible_ssh_port=5555
 
Here we see that we can bracket a range of alpha-numeric characters to shorten our entries in the file.
   
Inventory:  Groups 
 
Inventory Host Organization: Groups
Allow targeted operations against different types of hosts.  
Can have variables that apply to all hosts within them.  
Limit allows you to specify only certain groups to act against.  
Hosts can exist in more than one group at once.  
 
We can also act against groups of hosts in a similar manner to single hosts.
This allows you to also have standard settings for lots of similar hosts, such
as a standard set of ports for apache on all web servers. You can limit the execution of
Ansible jobs just as you can single hosts with the "--limit" option. Hosts can exist
in more than one group at once, letting you do interesting operations on the intersections
of groups. For example, target all of the east coast web servers.
  
Inventory:  Groups 
 
Groups are represented in brackets above host lists in the inventory file.
[webservers]
www[01:50].example.com ansible_ssh_port=5555 [databases]db-[a-f].example.com ansible_ssh_port=5555 
 
This is an example of a range of hosts specified via the bracket nomenclature.
 
    
         
 
    
Dynamic Inventory : Ansible and the Cloud 
 
Inventory can also be gathered on demand from other sources dynamically.  Those sources include:
 
 
Cloud API (Rackspace, Amazon, Digital Ocean, OpenStack,     Eucalyptus , etc.) 
 
Cobbler 
 
 
Create your own for fun and profit! 
 
 
So we can also take inventory from a wide variety of sources on the fly.  We can touch Rackspace, 
Openstack, Amazon EC2, Digital Ocean, and other provisioning systems like Cobbler.  You can also
create your own inventory module to interface with any custom CMDB systems you may have.
 
     
 
    
Inventory:  Ansible and the Cloud 
Dynamic inventories also respect groups and other details. 
Groups are auto-determined by instance tags, regions and other attributes. 
 
Dynamic Inventories can be used alongside Static Inventories for a hybrid cloud approach. 
 
 
Tagged instances automatically are put in a group based on that tag.  Other attributes also 
become groups, such as regions deployed to, or other custom attributes.
 
     
 
    
Tasks 
 
  A task is a discrete action that is a declaration about the state of a system.
 
Example Tasks: 
Directory should exist 
 
Package should be installed 
 
Service should be running 
 
Cloud Instance should exist 
 
 
These are examples of declarative tasks where the beginning state is disregarded in favor of ensuring end-state.
  
Tasks:  Examples 
Ansible can execute single tasks on sets of hosts to full-fill an  ad-hoc declarations
$ ansible web-hosts -m file -a "path=/opt/cache state=directory"
$ ansible web-hosts -m yum -a "name=nginx state=present"
$ ansible web-hosts -m service -a "name=nginx enabled=yes state=started"
 
in the first we make sure opt/cache exists, the second we install nginx, third we make 
sure nginx is installed, chkconfig'ed on and the service is started.
  
               Tasks:  Sources  
 
    
Code for tasks can come from:  
Existing modules   
Custom modules  
Raw ssh commands  
 
Tasks use modules or commands to create their actions to apply to remote systems. 
You can create your own modules, use any of the over 200 included modules, or use the output from commands.
  
 LAB   
Add a User using an Ansible ad-hoc command 
 
    
         
 
    
Modules 
 
Modules are the bits of code copied to the target system to be executed to satisfy the task declaration. 
Code need not exist on remote host -- ansible copies it over  
 
Many modules come with Ansible -- "batteries included"  
 
Custom modules can be developed easily 
 
Command/shell modules exists for simple commands 
 
Script module exists for using existing code 
 
Raw module exists for executing raw commands over ssh 
 
 
Modules essentially create python code out of the descriptions given via the tasks that are then sent to the 
remote machine and interpreted/executed by that host. Once executed, Ansible then cleans up after itself and 
removes the module and output from the remote system.
  
Module  Interactions 
Module listing and documentation via ansible-doc
$ ansible-doc -l
acl                  Sets and retrieves file ACL information.
apt                  Manages apt-packages
 
$ ansible-doc acl
> ACL
  Sets and retrieves file ACL information.
  Options (= is mandatory):
  - entry
          The acl to set or remove.  This must always be quoted in the [...]
 
Modules and tasks represent the core function of ansible. Modules are capable of idempotence -- 
can be ran successively and understand change vs no change. In these examples we see how to use
the command "ansible-doc" to review informtaion about specific modules that are included.
  
Module  Interactions in Tasks 
A series of tasks
- name: add cache dir
  file: path=/opt/cache state=directory
- name: install nginx
  yum: name=nginx state=present
- name: start nginx
  service: name=nginx enabled=yes state=started
 
An ordered series of tasks can be described to form plays.  Tasks utilize modules to act upon remote hosts.
 
     
 
    
Plays 
 
Plays are ordered sets of tasks to execute against host  selections from your inventory. 
 
Play  Naming 
- name: This is a Play
 
General best practices are to name tasks in a way that shows what they do.
  
Plays:  Hosts Selection 
- name: This is a Play
  hosts: web-servers
 
This is how we specify in a play/plabook what hosts we will act upon based on group.
  
Play  Arguments 
- name: This is a Play
  hosts: web-servers
  remote_user: fred
  sudo: yes
  connection: ssh
 
Furthermore, we can specify other variables as arguments.  
Such as what remote user to connect as, or whether we sudo to root to complete our task.
  
Play:  Variables 
- name: This is a Play
  hosts: web-servers
  remote_user: fred
  sudo: yes
  connection: ssh
  vars:
    http_port: 80
    cache_dir: /opt/cache
 
We gather facts before every run from hosts we are acting on.  Facts become variables that
contain information such as kernel level, host name, ip addresses and other standard information.
  
Play:  Tasks 
- name: This is a Play
  hosts: web-servers
  remote_user: fred
  sudo: yes
  connection: ssh
  gather_facts: no
  vars:
    http_port: 80
    cache_dir: /opt/cache
  tasks:
    - name: create cache dir
      file: path={{ cache_dir }} state=directory
    - name: install nginx
      yum: name=nginx state=installed
 
This is a compelte example of a play within a playbook.  It contains arguments, variables,
host groups to act on, two tasks and wheteher we use sudo on those tasks.  It also uses the variables
specified for the cache directory.  Variables are represented in the Jinja2 format with double curly braces.
 
     
 
    
        Plays:  Concurrency and Order of Operations 
     
- name: This is a Play
  hosts: web-servers
  remote_user: fred
  sudo: yes
  connection: ssh
  vars:
    http_port: 80
    cache_dir: /opt/cache
  tasks:
    - name: create cache dir
      file: path={{ cache_dir }} state=directory
    - name: install nginx
      yum: name=nginx state=installed
 
You can specify number of concurrent machines to act upon via setting a number of forks.  That will act upon 
that number of hosts at once, however the tasks within the play complete from top to botton, in order, one at a time.
  
Plays:  Conditionals  
 
- name: This is a Play
  hosts: web-servers
  remote_user: fred
  sudo: yes
  connection: ssh
  vars:
    http_port: 80
    cache_dir: /opt/cache
  tasks:
    - name: create cache dir
      file: path={{ cache_dir }} state=directory
    - name: install apache
      yum: name=httpd state=installed
      when: ansible_os_family == "RedHat"
    - name: install apache
      apt: pkg=apache2 state=installed
      when: ansible_os_family == "Debian"
 
This is an example of a conditional. Conditionals allow for actions to be dependant on some fact or variable set.
In this case, we see that we install nginx via Linux-Distro specific package managers. The variable "ansible_os_family"
is a discovered fact gathered when we first run the play or playbook against hosts.
  
Plays:  Error Handling 
- name: This is a Play
  hosts: web-servers
  remote_user: fred
  sudo: yes
  connection: ssh
  vars:
    http_port: 80
    cache_dir: /opt/cache
  tasks:
    - name: create cache dir
      file: path={{ cache_dir }} state=directory
    - name: install nginx
      yum: name=httpd state=installed
      when: ansible_os_family == "RedHat"
    - name: install nginx
      apt: pkg=apache2 state=installed
      when: ansible_os_family == "Debian"
    - name: failing command
      command: /bin/fail
      ignore_errors: yes
 
In this example we see the use of the "ignore_errors" setting, allowing users to dictate to ansible
to ignore when the return codes of ansible-initiated tasks indicate failures or errors.  Another way
to do this is by using the "failed_when" options.
  
Plays:  Inclusions 
- name: This is a Play
  hosts: web-servers
  remote_user: fred
  sudo: yes
  connection: ssh
  vars_files:
    - vars/nginx.yaml
  tasks:
    - name: create cache dir
      file: path={{ cache_dir }} state=directory
    - include: tasks/install-apache.yaml
    - name: failing command
      command: /bin/fail
      ignore_errors: yes
 
Take note of the "include" task: This allows us to include other playbooks at specific points in our
run allowing for complicated aspects of orchestration to be seamless based on function or type of 
playbook.  While this is useful, most often now you will use Roles for this functionality.  We'll talk
more about those in a bit.
  
 LAB   
Write and run a play that creates the directory /opt/cache on a 
    targeted host machine 
 
     
 
    
Playbooks 
 
Playbooks are ordered sets of plays to execute against inventory selections. 
 
Playbooks:  Inventory Selection 
$ ansible-playbook -i production play.yaml
$ ansible-playbook -i pre-prod play.yaml
$ ansible-playbook -i hosts/dfw/ play.yaml
 
As you can see, we can specify different inventories to run the playbook "play.yaml" against.
  
Playbooks:  Global Variables 
$ ansible-playbook -i pre-prod -e "cache_dir=/srv/cache/" play.yaml
 
Variables declared in this manner from the command line override other values.
  
Playbooks:  Forks 
$ ansible-playbook -f 30 -i pre-prod -e "cache_dir=/srv/cache/" play.yaml
 
This shows us declaring this playbook to be run against 30 hosts at a time by delcaring 
"-f 30" which is the flag for "forks equals 30 at a time."
  
Playbooks:  Inventory-Limits 
$ ansible-playbook --limit dfw -f 30 -i pre-prod -e "cache_dir=/srv/cache/" play.yaml
 
This shows us running a playbook while declaring a limit to run only against "DFW" 
which could mean a single host named DFW, or a host group DFW.
  
Playbooks:  Inclusions 
- name: This is a Play
  hosts: web-servers
  remote_user: fred
  sudo: yes
  connection: ssh
  gather_facts: no
  vars:
    http_port: 80
    cache_dir: /opt/cache
  tasks:
    - name: create cache dir
      file: path={{ cache_dir }} state=directory
- include: playbook2.yaml
 
In this example we see that at the end of the playbook, we include another playbook.  This allows
us to continue against other playbooks using the already discovered facts and variables declared.
  
Playbooks:  Roles 
Roles are portable units of task organization in playbooks.
Roles are units of organization in Ansible. Assigning a role to a group of hosts 
(or a set of groups, or host patterns, etc.) implies that they should implement a 
specific behavior. A role may include applying certain variable values, certain tasks, 
and certain handlers - or just one or more of these things. Because of the file structure 
associated with a role, roles become redistributable units that allow you to share 
behavior among playbooks - or even with other users.
 
Basic Playbook Structure 
In this chapter we'll cover the basic playbook structure, and write a simple playbook from scratch.
 
     
 
Play Header 
---
- name: this is the name of a play
  hosts: all
  user: root
  tasks: []
 
As we covered earlier, a playbook is a series of plays. Each play needs a "hosts" keyword, which tells Ansible to which hosts hosts this play applies. You can define a lot of other parameters at the play level, including which user to log in as, whether these tasks should be run through sudo, which connection mechanism to use, etc.
 
     
 
Write the tasks 
---
- name: this is the name of a play
  hosts: all
  user: root
  tasks:
  - name: install nginx
    yum: package=nginx state=present
 
Now that we have the "front matter" of the play defined, we can add the tasks, as shown. Each task can have a name that is human-readable. This isn't required, but it's recommended. Then you call the module, in this case "yum", and any arguments.
 
Run the playbook 
Run the playbook. If you've written everything correctly, it should install nginx on the target systems, and return the results. Notice the "Gathering Facts" step that occurs at the top of the run. This is implicit, but you can turn it off with "gather_facts: no" in the play. At the end, a "host recap" will be printed out. This gives you a summary of tasks that completed successfully, tasks that changed something on the target system, any failures, or unreachable systems.
  
 LAB   
Write playbook to install nginx, start the service and enable it at 
    time of boot