Mastering Ansible - James Freeman - E-Book

Mastering Ansible E-Book

James Freeman

0,0
36,59 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.
Mehr erfahren.
Beschreibung

Design, develop, and solve real-world automation and orchestration problems by unlocking the automation capabilities of Ansible.




Key Features



  • Tackle complex automation challenges with the newly added features in Ansible 2.7



Book Description



Automation is essential for success in the modern world of DevOps. Ansible provides a simple, yet powerful, automation engine for tackling complex automation challenges.






This book will take you on a journey that will help you exploit the latest version's advanced features to help you increase efficiency and accomplish complex orchestrations. This book will help you understand how Ansible 2.7 works at a fundamental level and will also teach you to leverage its advanced capabilities. Throughout this book, you will learn how to encrypt Ansible content at rest and decrypt data at runtime. Next, this book will act as an ideal resource to help you master the advanced features and capabilities required to tackle complex automation challenges. Later, it will walk you through workflows, use cases, orchestrations, troubleshooting, and Ansible extensions. Lastly, you will examine and debug Ansible operations, helping you to understand and resolve issues.






By the end of the book, you will be able to unlock the true power of the Ansible automation engine and tackle complex, real- world actions with ease.




What you will learn



  • Gain an in-depth understanding of how Ansible works under the hood


  • Fully automate Ansible playbook executions with encrypted data


  • Access and manipulate variable data within playbooks


  • Use blocks to perform failure recovery or cleanup


  • Explore the Playbook debugger and the Ansible Console


  • Troubleshoot unexpected behavior effectively


  • Work with cloud infrastructure providers and container systems


  • Develop custom modules, plugins, and dynamic inventory sources



Who this book is for



This book is for Ansible developers and operators who have an understanding of its core elements and applications but are now looking to enhance their skills in applying automation using Ansible.

Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:

EPUB

Seitenzahl: 396

Veröffentlichungsjahr: 2019

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Mastering AnsibleThird Edition

 

 

 

 

Effectively automate configuration management and deployment challenges with Ansible 2.7

 

 

 

 

 

 

 

 

James Freeman
Jesse Keating

 

 

 

 

 

 

 

 

 

 

BIRMINGHAM - MUMBAI

Mastering Ansible Third Edition

Copyright © 2019 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.

Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the authors, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.

Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.

Commissioning Editor: Vijin BorichaAcquisition Editor: Meeta RajaniContent Development Editor: Shubham BhattacharyaTechnical Editor: Sayali ThanekarCopy Editor:Safis EditingProject Coordinator: Nusaiba AnsariProofreader: Safis EditingIndexer: Rekha NairGraphics: Jisha ChirayilProduction Coordinator: Tom Scaria

First published: November 2015 Second edition: March 2017 Third edition: March 2019 

Production reference: 1220319

Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.

ISBN 978-1-78995-154-7

www.packtpub.com

 
mapt.io

Mapt is an online digital library that gives you full access to over 5,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.

Why subscribe?

Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals

Improve your learning with Skill Plans built especially for you

Get a free eBook or video every month

Mapt is fully searchable

Copy and paste, print, and bookmark content

Packt.com

Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.packt.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.

At www.packt.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks. 

Contributors

About the authors

James Freeman is an accomplished IT consultant with over 20 years' experience in the technology industry. He has more than 5 years of first-hand experience of solving real-world enterprise problems in production environments using Ansible, frequently introducing Ansible as a new technology to businesses and CTOs for the first time. In addition, he has authored and facilitated bespoke Ansible workshops and training sessions, and has presented at both international conferences and meetups on Ansible.

I would like to thank my other half, Neeshia Jasmara, for her support, without which this book would probably never have happened; my sons, Sam and Jaedyn, for their continued patience while I have my head in a computer; and my employer, Quru, and especially our founder, Roland Whitehead, who have provided me with the opportunities that enabled me to write this book.

Jesse Keatingis an accomplished Ansible user, contributor, and presenter. He has been an active member of the Linux and open source community for over 15 years. He has first- hand experience involving a variety of IT activities, software development, and large-scale system administration. He has presented at numerous conferences and meetups, and has written many articles on a variety of topics.

About the reviewer

Timothy Rupp has been working in various fields of computing for the last 15 years. He has held positions in cybersecurity and software engineering, as well as in the fields of cloud computing and DevOps.

He was first introduced to Ansible while at Rackspace. As part of the cloud engineering team, he made extensive use of a tool for deploying new capacity to the Rackspace public cloud. Since that introduction, he has contributed patches, provided support for, and presented on Ansible topics at local meetups.

While at F5 Networks, he led the development of F5's Ansible modules and became a core contributor to the Ansible project. Most recently, he has become reinvolved with cybersecurity in the financial sector.

 

 

 

 

 

Packt is searching for authors like you

If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.

Table of Contents

Title Page

Copyright and Credits

Mastering Ansible Third Edition

About Packt

Why subscribe?

Packt.com

Contributors

About the authors

About the reviewer

Packt is searching for authors like you

Preface

Who this book is for

What this book covers

To get the most out of this book

Download the example code files

Download the color images

Code in Action

Conventions used

Get in touch

Reviews

Section 1: Ansible Overview and Fundamentals

The System Architecture and Design of Ansible

Technical requirements

Ansible version and configuration

Inventory parsing and data sources

Static inventory

Inventory ordering

Inventory variable data

Dynamic inventories

Runtime inventory additions

Inventory limiting

Playbook parsing

Order of operations

Relative path assumptions

Play behavior directives

Execution strategies

Host selection for plays and tasks

Play and task names

Module transport and execution

Module reference

Module arguments

Module blacklisting

Module transport and execution

Task performance

Variable types and location

Variable types

Magic variables

Accessing external data

Variable precedence

Precedence order

Variable group priority ordering

Merging hashes

Summary

Protecting Your Secrets with Ansible

Technical requirements

Encrypting data at rest

Vault IDs and passwords

Things Vault can encrypt

Creating new encrypted files

Password prompt

Password file

Password script

Encrypting existing files

Editing encrypted files

Password rotation on encrypted files

Decrypting encrypted files

Executing Ansible-playbook with encrypted files

Mixing encrypted data with plain YAML

Protecting secrets while operating

Secrets transmitted to remote hosts

Secrets logged to remote or local files

Summary

Ansible and Windows - Not Just for Linux

Technical requirements

Running Ansible from Windows

Checking your build

Enabling WSL

Installing Linux under WSL

Setting up Windows hosts for Ansible control

System requirements for automation with Ansible

Enabling the WinRM listener

Connecting Ansible to Windows

Handling Windows authentication and encryption

Authentication mechanisms

A note on accounts

Certificate validation

Automating Windows tasks with Ansible

Picking the right module

Installing software

Extending beyond modules

Summary

Infrastructure Management for Enterprises with AWX

Technical requirements

Getting AWX up and running

Integrating AWX with your first playbook

Defining a project

Defining an inventory

Defining credentials

Defining a template

Going beyond the basics

Role-based access control (RBAC)

Organizations

Scheduling

Auditing

Surveys

Workflow templates

Notifications

Summary

Section 2: Writing and Troubleshooting Ansible Playbooks

Unlocking the Power of Jinja2 Templates

Technical requirements

Control structures

Conditionals

Inline conditionals

Loops

Filtering loop items

Loop indexing

Macros

Macro variables

name

arguments

defaults

catch_kwargs

catch_varargs

caller

Data manipulation

Syntax

Useful built-in filters

default

count

random

round

Useful Ansible provided custom filters

Filters related to task status

shuffle

Filters dealing with path names

basename

dirname

expanduser

Base64 encoding

Searching for content

Omitting undefined arguments

Python object methods

String methods

List methods

int and float methods

Comparing values

Comparisons

Logic

Tests

Summary

Controlling Task Conditions

Technical requirements

Defining a failure

Ignoring errors

Defining an error condition

Defining a change

Special handling of the command family

Suppressing a change

Error recovery

Using the rescue section

Using the always section

Handling unreliable environments

Iterative tasks with loops

Summary

Composing Reusable Ansible Content with Roles

Technical requirements

Task, handler, variable, and playbook inclusion concepts

Including tasks

Passing variable values to included tasks

Passing complex data to included tasks

Conditional task includes

Tagging included tasks

Task includes with loops

Including handlers

Including variables

vars_files

Dynamic vars_files inclusion

include_vars

extra-vars

Including playbooks

Roles

Role structure

Tasks

Handlers

Variables

Modules and plugins

Dependencies

Files and templates

Putting it all together

Role dependencies

Role dependency variables

Tags

Role dependency conditionals

Role application

Mixing roles and tasks

Role includes and imports

Role sharing

Ansible Galaxy

Summary

Troubleshooting Ansible

Technical requirements

Playbook logging and verbosity

Verbosity

Logging

Variable introspection

Variable subelements

Subelements versus Python object method

Debugging code execution

Playbook debugging

Debugging local code

Debugging inventory code

Debugging playbook code

Debugging executor code

Debugging remote code

Debugging the action plugins

Summary

Extending Ansible

Technical requirements

Developing modules

The basic module construct

Custom modules

Example – Simple module

Documenting a module

Providing fact data

The check mode

Supporting check mode

Handling check mode

Developing plugins

Connection-type plugins

Shell plugins

Lookup plugins

Vars plugins

Fact-caching plugins

Filter plugins

Callback plugins

Action plugins

Distributing plugins

Developing dynamic inventory plugins

Listing hosts

Listing host variables

Simple inventory plugin

Optimizing script performance

Contributing to the Ansible project

Contribution submissions

The Ansible repository

Executing tests

Unit tests

Integration tests

Code-style tests

Making a pull request

Summary

Section 3: Orchestration with Ansible

Minimizing Downtime with Rolling Deployments

Technical requirements

In-place upgrades

Expanding and contracting

Failing fast

The any_errors_fatal option

The max_fail_percentage option

Forcing handlers

Minimizing disruptions

Delaying a disruption

Running destructive tasks only once

Serializing single tasks

Summary

Infrastructure Provisioning

Technical requirements

Managing cloud infrastructures

Creating servers

Booting virtual servers

Adding to runtime inventory

Using OpenStack inventory sources

Managing a public cloud infrastructure

Interacting with Docker containers

Building images

Building containers without a Dockerfile

Docker inventory

Ansible Container

Using ansible-container init

Using ansible-container build

Using ansible-container run

Summary

Network Automation

Technical requirements

Ansible for network manage ment

Cross-platform support

Configuration portability

Backup, restore, and version control

Automated change requests

Handling multiple device types

Researching your modules

Configuring your modules

Writing your playbooks

Configuring Cumulus Networks switches with Ansible

Defining our inventory

Practical examples

Best practices

Inventory

Gathering facts

Jump hosts

Summary

Other Books You May Enjoy

Leave a review - let other readers know what you think

Preface

Welcome to Mastering Ansible, your guide to a collection of the most valuable advanced features and functionalities provided by Ansible, the automation and orchestration tool. This book will provide readers with the knowledge and skills required to truly understand how Ansible functions at a fundamental level. In turn, this will allow readers to master the advanced capabilities needed to tackle the complex automation challenges of today, and the future. Readers will gain knowledge of Ansible workflows, explore use cases for advanced features, troubleshoot unexpected behavior, extend Ansible through customization, and learn about many of the new and important developments in Ansible, especially around infrastructure and network provisioning.

Who this book is for

This book is for Ansible developers and operators who have an understanding of the core elements and applications but are now looking to enhance their skills in applying automation using Ansible.

What this book covers

Chapter 1, The System Architecture and Design of Ansible, looks at the ins and outs of how Ansible goes about performing tasks on behalf of an engineer, how it is designed, and how to work with inventory and variables.

Chapter 2, Protecting Your Secrets with Ansible, explores the tools available to encrypt data at rest and prevent secrets from being revealed at runtime.

Chapter 3, Ansible and Windows - Not Just for Linux, explores the integration of Ansible with Windows hosts to enable automation in cross-platform environments.

Chapter 4, Infrastructure Management for Enterprises with AWX, provides an overview of the powerful open source graphical management framework for Ansible known as AWX, and how this might be employed in an enterprise environment.

Chapter 5, Unlocking the Power of Jinja2 Templates, states the varied uses of the Jinja2 templating engine within Ansible and discusses ways to make the most out of its capabilities.

Chapter 6, Controlling Task Conditions, explains how to change the default behavior of Ansible to customize task error and change conditions.

Chapter 7, Composing Reusable Ansible Content with Roles, explains how to move beyond executing loosely-organized tasks on hosts, and instead to build clean, reusable, and self-contained code structures known as roles to achieve the same end result.

Chapter 8, Troubleshooting Ansible, takes you through the various methods that can be employed to examine, introspect, modify, and debug the operations of Ansible.

Chapter 9, Extending Ansible, covers the various ways in which new capabilities can be added to Ansible via modules, plugins, and inventory sources.

Chapter 10, Minimizing Downtime with Rolling Deployments, explains the common deployment and upgrade strategies in order to showcase the relevant Ansible features.

Chapter 11, Infrastructure Provisioning, examines cloud infrastructure providers and container systems in order to create an infrastructure to manage.

Chapter 12, Network Automation, describes the advancements in the automation of network device configuration using Ansible.

To get the most out of this book

To follow the examples provided in this book, you will need access to a computer platform capable of running Ansible. Currently, Ansible can be run on any machine with Python 2.7 or Python 3 (versions 3.5 and higher) installed (Windows is supported for the control machine, but only through a Linux distribution running in the Windows Subsystem for Linux (WSL) layer available on newer versions—see Chapter 3, Ansible and Windows - Not Just for Linux, for details). Supported operating systems include (but are not limited to) Red Hat, Debian, Ubuntu, CentOS, macOS, and FreeBSD.

This book uses the Ansible 2.7.x.x series release. Ansible installation instructions can be found at https://docs.ansible.com/ansible/intro_installation.html.

Some examples use Docker version 1.13.1. Docker installation instructions can be found at https://docs.docker.com/install/.

A handful of examples in this book make use of accounts on both Amazon Web Services (AWS) and Microsoft Azure. More information about these services may be found at https://aws.amazon.com and https://azure.microsoft.com respectively. We also delve into management of OpenStack with Ansible, and the examples in this book were tested against a single "all-in-one" instance of Devstack, as per the instructions found here: https://docs.openstack.org/devstack/latest/. 

Finally, the chapter on network device management makes use of Cumulus VX, version 3.7.3, in the example code—please see here for more information: https://cumulusnetworks.com/products/cumulus-vx/.

Download the example code files

You can download the example code files for this book from your account at www.packt.com. If you purchased this book elsewhere, you can visit www.packt.com/support and register to have the files emailed directly to you.

You can download the code files by following these steps:

Log in or register at

www.packt.com

.

Select the

SUPPORT

tab.

Click on

Code Downloads & Errata

.

Enter the name of the book in the

Search

box and follow the onscreen instructions.

Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:

WinRAR/7-Zip for Windows

Zipeg/iZip/UnRarX for Mac

7-Zip/PeaZip for Linux

The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Mastering-Ansible-Third-Edition. In case there's an update to the code, it will be updated on the existing GitHub repository.

We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!

Download the color images

We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://www.packtpub.com/sites/default/files/downloads/9781789951547_ColorImages.pdf.

Code in Action

Visit the following link to check out videos of the code being run:http://bit.ly/2HCcfRE

Conventions used

There are a number of text conventions used throughout this book.

CodeInText: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "Also, note that Ansible requires the winrm Python module installed to connect successfully."

A block of code is set as follows:

---- name: Linux file example playbook hosts: all gather_facts: false

Any command-line input or output is written as follows:

sudo yum install python2-winrm

Bold: Indicates a new term, an important word, or words that you see onscreen. For example, words in menus or dialog boxes appear in the text like this. Here is an example: "Now, note the buttons along the top of theInventoriespane—DETAILS, PERMISSIONS, GROUPS, HOSTS, SOURCES, and COMPLETED JOBS."

Warnings or important notes appear like this.
Tips and tricks appear like this.

Get in touch

Feedback from our readers is always welcome.

General feedback: If you have questions about any aspect of this book, mention the book title in the subject of your message and email us at [email protected].

Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packt.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.

Piracy: If you come across any illegal copies of our works in any form on the Internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.

If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.

Reviews

Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!

For more information about Packt, please visit packt.com.

Section 1: Ansible Overview and Fundamentals

In this section, we will explore the fundamentals of how Ansible works and establish a sound basis on which to develop playbooks and workflows.

The following chapters are included in this section:

Chapter 1, The System Architecture and Design of Ansible

Chapter 2, Protecting Your Secrets with Ansible

Chapter 3, Ansible and Windows – Not Just for Linux

Chapter 4, Infrastructure Management for Enterprises with AWX

The System Architecture and Design of Ansible

This chapter provides a detailed exploration of the architecture and design of Ansible, and how it goes about performing tasks on your behalf. We will cover the basic concepts of inventory parsing and how data is discovered, and then proceed onto playbook parsing. We will take a walk through module preparation, transportation, and execution. Lastly, we will detail variable types and find out where the variables are located, their scope of use, and how precedence is determined when variables are defined in more than one location. All these things will be covered in order to lay the foundation for mastering Ansible!

In this chapter, we will cover the following topics:

Ansible version and configuration

Inventory parsing and data sources

Playbook parsing

Execution strategies

Module transport and execution

Variable types and locations

Magic variables

Variable precedence (

and interchanging this with variable priority ordering

)

Technical requirements

Check out the following video to see the Code in Action:

http://bit.ly/2ulbmEl

Ansible version and configuration

It is assumed that you have Ansible installed on your system. There are many documents out there that cover installing Ansible in a way that is appropriate to the operating system and version that you might be using. This book will assume use of Ansible version 2.7.x.x. To discover the version in use on a system where Ansible is already installed, make use of the version argument, that is, either ansible or ansible-playbook, as follows:

ansible-playbook --version

This command should give you an output that's similar to the following screenshot:

Note that ansible is the executable for doing ad hoc one-task executions, and ansible-playbook is the executable that will process playbooks for orchestrating many tasks.

The configuration for Ansible can exist in a few different locations, where the first file found will be used. The search involves the following:

ANSIBLE_CFG

: This environment variable is used, provided it is set

ansible.cfg

: This is located in the current directory

~/.ansible.cfg

: This is located in the user's home directory 

/etc/ansible/ansible.cfg

Some installation methods may include placing a config file in one of these locations. Look around to check whether such a file exists and see what settings are in the file to get an idea of how Ansible operation may be affected. This book will assume that there are no settings in the ansible.cfg file that would affect the default operation of Ansible.

Inventory parsing and data sources

In Ansible, nothing happens without an inventory. Even ad hoc actions performed on the localhost require an inventory, though that inventory may just consist of the localhost. The inventory is the most basic building block of Ansible architecture. When executing ansible or ansible-playbook, an inventory must be referenced. Inventories are either files or directories that exist on the same system that runs ansible or ansible-playbook. The location of the inventory can be referenced at runtime with the --inventory-file (-i) argument, or by defining the path in an Ansible config file.

Inventories can be static or dynamic, or even a combination of both, and Ansible is not limited to a single inventory. The standard practice is to split inventories across logical boundaries, such as staging and production, allowing an engineer to run a set of plays against their staging environment for validation, and then follow with the same exact plays run against the production inventory set.

Variable data, such as specific details on how to connect to a particular host in your inventory, can be included, along with an inventory in a variety of ways, and we'll explore the options available to you.

Static inventory

The static inventory is the most basic of all the inventory options. Typically, a static inventory will consist of a single file in the ini format. Here is an example of a static inventory file describing a single host, mastery.example.name:

mastery.example.name

That is all there is to it. Simply list the names of the systems in your inventory. Of course, this does not take full advantage of all that an inventory has to offer. If every name were listed like this, all plays would have to reference specific hostnames, or the special built-in all group (which, as it suggests, contains all hosts in the inventory). This can be quite tedious when developing a playbook that operates across different environments within your infrastructure. At the very least, hosts should be arranged into groups.

A design pattern that works well is to arrange your systems into groups based on expected functionality. At first, this may seem difficult if you have an environment where single systems can play many different roles, but that is perfectly fine. Systems in an inventory can exist in more than one group, and groups can even consist of other groups! Additionally, when listing groups and hosts, it's possible to list hosts without a group. These would have to be listed first before any other group is defined. Let's build on our previous example and expand our inventory with a few more hosts and groupings as follows:

[web] mastery.example.name [dns] backend.example.name [database] backend.example.name [frontend:children] web [backend:children] dns database

What we have created here is a set of three groups with one system in each, and then two more groups, which logically group all three together. Yes, that's right; you can have groups of groups. The syntax used here is [groupname:children], which indicates to Ansible's inventory parser that this group, going by the name of groupname, is nothing more than a grouping of other groups.

The children, in this case, are the names of the other groups. This inventory now allows writing plays against specific hosts, low-level, role-specific groups, or high-level logical groupings, or any combination thereof.

By utilizing generic group names, such as dns and database, Ansible plays can reference these generic groups rather than the explicit hosts within. An engineer can create one inventory file that fills in these groups with hosts from a pre-production staging environment, and another inventory file with the production versions of these groupings. The playbook content does not need to change when executing on either a staging or production environment because it refers to the generic group names that exist in both inventories. Simply refer to the correct inventory to execute it in the desired environment.

Inventory ordering

A new play-level keyword, order, was added to Ansible in version 2.4. Prior to this, Ansible processed the hosts in the order specified in the inventory file, and continues to do so by default, even in newer versions. However, the following values can be set for the order keyword for a given play, resulting in the processing order of hosts described as follows:

inventory

: This is the default option, and simply means Ansible proceeds as it always has, processing the hosts in the order specified in the

inventory

file

reverse_inventory

: This results in the hosts being processed in the reverse of the order specified in the inventory

sorted

: The hosts are processed in alphabetically sorted order by name

reverse_sorted

: The hosts are processed in reverse alphabetically sorted order

shuffle

: The hosts are processed in a random order, with the order being randomized on each run

In Ansible, the alphabetical sorting used is otherwise known as lexicographical. In short this means that values are sorted as strings, with the strings being processed from left to right. Thus, say we have three hosts—mastery1, mastery11, and mastery2. In this list, mastery1 comes first as the character as position 8 is a 1. Then comes mastery11, as the character at position 8 is still a 1, but now there is an additional character at position 9. Finally comes mastery2, as character 8 is a 2 and 2 comes after 1. This is important as numerically we know that 11 is greater than 2, but in this list mastery11 comes before mastery2.

Inventory variable data

Inventories provide more than just system names and groupings. Data pertaining to the systems can be passed along as well. This data may include the following:

Host-specific data to use in templates

Group-specific data to use in task arguments or conditionals

Behavioral parameters to tune how Ansible interacts with a system

Variables are a powerful construct within Ansible and can be used in a variety of ways, not just those described here. Nearly every single thing done in Ansible can include a variable reference. While Ansible can discover data about a system during the setup phase, not all data can be discovered. Defining data with the inventory expands this. Note that variable data can come from many different sources, and one source may override another. Variable precedence order is covered later in this chapter.

Let's improve upon our existing example inventory and add to it some variable data. We will add some host-specific data, as well as group-specific data:

[web] mastery.example.name ansible_host=192.168.10.25 [dns] backend.example.name [database] backend.example.name [frontend:children] web [backend:children] dns database [web:vars] http_port=88 proxy_timeout=5 [backend:vars] ansible_port=314 [all:vars] ansible_ssh_user=otto

In this example, we defined ansible_host for mastery.example.name to be the IP address of 192.168.10.25. The ansible_host variable is a behavioral inventory variable, which is intended to alter the way Ansible behaves when operating with this host. In this case, the variable instructs Ansible to connect to the system using the IP address provided, rather than performing a DNS lookup on the name using mastery.example.name. There are a number of other behavioral inventory variables that are listed at the end of this section, along with their intended use.

Our new inventory data also provides group-level variables for the web and backend groups. The web group defines http_port, which may be used in an NGINX configuration file, and proxy_timeout, which might be used to determine HAProxy behavior. The backend group makes use of another behavioral inventory parameter to instruct Ansible to connect to the hosts in this group using port 314 for SSH, rather than the default of 22.

Finally, a construct is introduced that provides variable data across all the hosts in the inventory by utilizing a built-in all group. Variables defined within this group will apply to every host in the inventory. In this particular example, we instruct Ansible to log in as the otto user when connecting to the systems. This is also a behavioral change, as the Ansible default behavior is to log in as a user with the same name as the user executing ansible or ansible-playbook on the control host.

Here is a table of behavior inventory variables and the behaviors they intend to modify:

Inventory parameters

Behavior

ansible_host

This is the DNS name or or the Docker container name which Ansible will initiate a connection to.

ansible_port

Specifies the port number that Ansible will use to connect to the inventory host, if not the default value of 22.

ansible_user

Specifies the username that Ansible will connect to the inventory host with, regardless of the connection type.

ansible_ssh_pass

Used to provide Ansible with the password for authentication to the inventory host in conjunction with ansible_user.

ansible_ssh_private_key_file

Used to specify which SSH private key file will be used to connect to the inventory host, if not using the default one or ssh-agent.

ansible_ssh_common_args

This defines SSH arguments to append to the default arguments for

ssh

,

sftp

, and

scp

.

ansible_sftp_extra_args

Used to specify additional arguments that will be passed to the sftp binary when called by Ansible.

ansible_scp_extra_args

Used to specify additional arguments that will be passed to the scp binary when called by Ansible.

ansible_ssh_extra_args

Used to specify additional arguments that will be passed to the ssh binary when called by Ansible.

ansible_ssh_pipelining

This setting uses a Boolean to define whether SSH pipelining should be used for this host.

ansible_ssh_executable

This setting overrides the path to the SSH executable for this host.

ansible_become

This defines whether privilege escalation (

sudo

or otherwise) should be used with this host.

ansible_become_method

This is the method to use for privilege escalation, and can be one of

sudo

,

su

,

pbrun

,

pfexec

,

doas

,

dzdo

, or

ksu

.

ansible_become_user

This is the user to become through privilege escalation.

ansible_become_pass

This is the password to use for privilege escalation.

ansible_sudo_pass

This is the sudo password to use (this is insecure; we strongly recommend using

--ask-sudo-pass

).

ansible_connection

This is the connection type of the host. Candidates are

local

,

smart

,

ssh

,

paramiko

docker

, or

winrm

(more on this later in the book). The default is 

smart

in any modern Ansible distribution (this detects whether the SSH feature

ControlPersist

is supported and, if so, uses

ssh

as the connection type, falling back to

paramiko

otherwise).

ansible_docker_extra_args

Used to specify the extra argument that will be passed to a remote Docker daemon on a given inventory host.

ansible_shell_type

Used to determine the shell type on the inventory host(s) in question. Defaults to sh-style syntax, but can be set to csh or fish to work with systems that use these shells.

ansible_shell_executable

Used to determine the shell type on the inventory host(s) in question. Defaults to sh-style syntax, but can be set to csh or fish to work with systems that use these shells.

ansible_python_interpreter

This is used to manually set the path to Python on a given host in the inventory. For example some distributions of Linux have more than one Python version installed, and it is important that the correct one is set. For example, a host might have both /usr/bin/python27 and /usr/bin/python3, and this is used to define which one will be used.

ansible_*_interpreter

Used for any other interpreted language that Ansible might depend upon (e.g. Perl or Ruby). Replaces the interpreter binary with the one specified.

Dynamic inventories

A static inventory is great, and enough for many situations. But there are times when a statically written set of hosts is just too unwieldy to manage. Consider situations where inventory data already exists in a different system, such as LDAP, a cloud computing provider, or an in-house configuration management database (CMDB) (inventory, asset tracking, and data warehousing) system. It would be a waste of time and energy to duplicate that data and, in the modern world of on-demand infrastructure, that data would quickly grow stale or disastrously incorrect.

Another example of when a dynamic inventory source might be desired is when your site grows beyond a single set of playbooks. Multiple playbook repositories can fall into the trap of holding multiple copies of the same inventory data, or complicated processes have to be created to reference a single copy of the data. An external inventory can easily be leveraged to access the common inventory data stored outside of the playbook repository to simplify the setup. Thankfully, Ansible is not limited to static inventory files.

A dynamic inventory source (or plugin) is an executable that Ansible will call at runtime to discover real-time inventory data. This executable may reach out into external data sources and return data, or it can just parse local data that already exists but may not be in the Ansible inventory ini format. While it is possible, and easy, to develop your own dynamic inventory source, which we will cover in a later chapter, Ansible provides a number of example inventory plugins, including, but not limited to, the following:

OpenStack Nova

Rackspace Public Cloud

DigitalOcean

Linode

Amazon EC2

Google Compute Engine

Microsoft Azure

Docker

Vagrant

Many of these plugins require some level of configuration, such as user credentials for EC2 or authentication endpoint for OpenStack Nova. Since it is not possible to configure additional arguments for Ansible to pass along to the inventory script, the configuration for the script must either be managed via an ini config file read from a known location, or environment variables read from the shell environment used to execute ansible or ansible-playbook. Note also that sometimes, external libraries are required for these inventory scripts to function.

When ansible or ansible-playbook is directed at an executable file for an inventory source, Ansible will execute that script with a single argument, --list. This is so that Ansible can get a listing of the entire inventory in order to build up its internal objects to represent the data. Once that data is built up, Ansible will then execute the script with a different argument for every host in the data to discover variable data. The argument used in this execution is --host <hostname>, which will return any variable data specific to that host.

The inventory scripts are too numerous to go through each in detail in this book. However, to demonstrate the process, we will work through the use of the EC2 dynamic inventory. The dynamic inventory scripts officially included with Ansible can be found on Github:

https://github.com/ansible/ansible/tree/devel/contrib/inventory

On browsing this directory system, we can see there is an ec2.py and associated example configuration file, ec2.ini. Download these onto your system and make the Python file executable:

If we take a look at the comments at the top of ec2.py, we can see it tells us that we need the Boto library installed. Installing this will depend on your operating system and Python environment, but on CentOS 7 (and other EL7 variants), it could be done with the following:

Now, take a look at the ec2.ini file, and edit it as appropriate. You can see that your AWS credentials could go into this file, but it is not recommended for security reasons. For this example, we will simply specify them using environment variables, and then run our dynamic inventory script with the --list parameter, as discussed in the previous screenshot. Doing so yields the following:

Voila! We have a listing of our current AWS inventory, along with a glimpse into the host variables for the discovered hosts. Note that, of course, the full output is far more complete than this.

With the AWS inventory in place, you could use this right away to run a single task or entire playbook against this dynamic inventory. For example, to use the ping module to check Ansible connectivity to all hosts in the inventory, you could run the following command:

ansible -i ec2.py all -m ping

This, of course, is just one example. However, if you follow this process for other dynamic inventory providers, you should get them working with ease.

In Chapter 9, Extending Ansible, we will develop our own custom inventory plugin to demonstrate how they operate.

Runtime inventory additions

Just like static inventory files, it is important to remember that Ansible will parse this data once, and only once, per ansible or ansible-playbook execution. This is a fairly common stumbling point for users of cloud dynamic sources, where frequently, a playbook will create a new cloud resource and then attempt to use it as if it were part of the inventory. This will fail, as the resource was not part of the inventory when the playbook launched. All is not lost though! A special module is provided that allows a playbook to temporarily add an inventory to the in-memory inventory object, the add_host module.

The add_host module takes two options, name and groups. The name should be obvious; it defines the hostname that Ansible will use when connecting to this particular system. The groups option is a comma-separated list of groups to add this new system to. Any other option passed to this module will become the host variable data for this host. For example, if we want to add a new system, name it newmastery.example.name, add it to the web group, and instruct Ansible to connect to it by way of IP address 192.168.10.30. This will create a task resembling the following:

- name: add new node into runtime inventory add_host: name: newmastery.example.name groups: web ansible_host: 192.168.10.30

This new host will be available to use, by way of the name provided, or by way of the web group, for the rest of the ansible-playbook execution. However, once the execution has completed, this host will not be available unless it has been added to the inventory source itself. Of course, if this were a new cloud resource created, the next ansible or ansible-playbook execution that sourced inventory from that cloud would pick up the new member.

Inventory limiting

As mentioned earlier, every execution of ansible or ansible-playbook will parse the entire inventory it has been directed at. This is even true when a limit has been applied. A limit is applied at runtime by making use of the --limit runtime argument to ansible or ansible-playbook. This argument accepts a pattern, which is basically a mask to apply to the inventory. The entire inventory is parsed, and at each play, the limit mask supplied further limits the host pattern listed for the play.

Let's take our previous inventory example and demonstrate the behavior of Ansible with and without a limit. If you recall, we have the special group, all, that we can use to reference all the hosts within an inventory. Let's assume that our inventory is written out in the current working directory in a file named mastery-hosts, and we will construct a playbook to demonstrate the host on which Ansible is operating. Let's write this playbook out as mastery.yaml:

--- - name: limit example play hosts: all gather_facts: false tasks: - name: tell us which host we are on debug: var: inventory_hostname

The debug module is used to print out text, or values of variables. We'll use this module a lot in this book to simulate actual work being done on a host.

Now, let's execute this simple playbook without supplying a limit. For simplicity's sake, we will instruct Ansible to utilize a local connection method, which will execute locally rather than attempting to SSH to these non-existent hosts.

Let's take a look at the following screenshot:

As we can see, both hosts, backend.example.name and mastery.example.name, were operated on. Let's see what happens if we supply a limit, specifically to limit our run to frontend systems only:

We can see that only mastery.example.name was operated on this time. While there are no visual clues that the entire inventory was parsed, if we dive into the Ansible code and examine the inventory object, we will indeed find all the hosts within, and see how the limit is applied every time the object is queried for items.

It is important to remember that regardless of the host's pattern used in a play, or the limit supplied at runtime, Ansible will still parse the entire inventory set during each run. In fact, we can prove this by attempting to access the host variable data for a system that would otherwise be masked by our limit. Let's expand our playbook slightly and attempt to access the ansible_port variable from backend.example.name:

--- - name: limit example play hosts: all gather_facts: false tasks: - name: tell us which host we are on debug: var: inventory_hostname - name: grab variable data from backend debug: var: hostvars['backend.example.name']['ansible_port']

We will still apply our limit, which will restrict our operations to just mastery.example.name:

We have successfully accessed the host variable data (by way of group variables) for a system that was otherwise limited out. This is a key skill to understand, as it allows for more advanced scenarios, such as directing a task at a host that is otherwise limited out. Delegation can be used to manipulate a load balancer to put a system into maintenance mode while being upgraded without having to include the load balancer system in your limit mask.

Playbook parsing

The whole purpose of an inventory source is to have systems to manipulate. The manipulation comes from playbooks (or, in the case of Ansible ad hoc execution, that is, simple single-task plays). You should already have a basic understanding of playbook construction, so we won't spend a lot of time covering that; however, we will delve into some specifics of how a playbook is parsed. Specifically, we will cover the following:

Order of operations

Relative path assumptions

Play behavior keys

Host selection for plays and tasks

Play and task names

Order of operations

Ansible is designed to be as easy as possible for a human to understand. The developers strive to strike the best balance of human comprehension and machine efficiency. To that end, nearly everything in Ansible can be assumed to be executed in a top-to-bottom order; that is, the operation listed at the top of a file will be accomplished before the operation listed at the bottom of a file. Having said that, there are a few caveats, and even a few ways to influence the order of operations.

A playbook has only two main operations it can accomplish. It can either run a play, or it can include another playbook from somewhere on the filesystem. The order in which these are accomplished is simply the order in which they appear in the playbook file, from top to bottom. It is important to note that while the operations are executed in order, the entire playbook and any included playbooks are completely parsed before any executions. This means that any included playbook file has to exist at the time of the playbook parsing. They cannot be generated in an earlier operation. This is specific to playbook inclusions, and not necessarily to task inclusions that may appear within a play, which will be covered in a later chapter.

Within a play, there are a few more operations. While a playbook is strictly ordered from top to bottom, a play has a more nuanced order of operations. Here is a list of the possible operations and the order in which they will happen:

Variable loading

Fact gathering

The

pre_tasks

execution

Handlers notified from the

pre_tasks

execution

Roles execution

Tasks execution

Handlers notified from roles or tasks execution

The

post_tasks

execution

Handlers notified from the 

post_tasks

execution

Here is an example play with most of these operations shown:

--- - hosts: localhost gather_facts: false vars: - a_var: derp pre_tasks: - name: pretask debug: msg: "a pre task" changed_when: true notify: say hi roles: - role: simple derp: newval tasks: - name: task debug: msg: "a task" changed_when: true notify: say hi