34,79 €
This book provides you with the knowledge you need to understand how Ansible 2.1 works at a fundamental level and leverage its advanced capabilities. You'll learn how to encrypt Ansible content at rest and decrypt data at runtime. You will master the advanced features and capabilities required to tackle the complex automation challenges of today and beyond.
You will gain detailed knowledge of Ansible workflows, explore use cases for advanced features, craft well thought out orchestrations, troubleshoot unexpected behaviour, and extend Ansible through customizations. Finally, you will discover the methods used to examine and debug Ansible operations, helping you to understand and resolve issues.
By the end of the book, the readers will be able to unlock the true power of the Ansible automation engine and will tackle complex real world actions with ease.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 261
Veröffentlichungsjahr: 2017
Copyright © 2017 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 author, nor Packt Publishing, and its dealers and distributors will be held liable for any damages caused or alleged to be 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.
First published: November 2015
Second edition: March 2017
Production reference: 1270317
Published by Packt Publishing Ltd.
Livery Place
35 Livery Street
Birmingham
B3 2PB, UK.
ISBN 978-1-78712-568-1
www.packtpub.com
Author
Jesse Keating
Copy Editor
Safis Editing
Reviewer
Sreenivas Makam
Project Coordinator
Kinjal Bari
Acquisition Editor
Prachi Bisht
Proofreader
Safis Editing
Content Development Editor
Trusha Shriyan
Indexer
Pratik Shirodkar
Technical Editor
Varsha Shivhare
Production Coordinator
Nilesh Mohite
Graphics
Kirk D'Penha
Jesse Keating is an accomplished Ansible user, contributor, and presenter. He has been an active member of the Linux and open source community for over fifteen years. He has first-hand experience with a variety of IT activities, software development, and large-scale system administration. He has presented at numerous conferences and meet-ups, and has written many articles on a variety of topics.
Sreenivas Makam is a senior engineering manager at Cisco Systems, Bangalore. He has a master's in electrical engineering and has around 18 years’ experience in the networking industry. He has worked in both startups and big, established companies. His interests include Containers, SDN, network automation, devops, and cloud technologies, and he likes to try out and follow open source projects in these areas. His blog can be found at https://sreeninet.wordpress.com/, he has presentations at http://www.slideshare.net/SreenivasMakam, and his hacky code is at https://github.com/smakam. Sreenivas is a Docker Captain, (https://www.docker.com/community/docker-captains) and his blog articles have been published in Docker weekly newsletters. He can be reached on Twitter at @srmakam.
He has written Mastering CoreOS, also reviewed Mastering Ansible, CoreOS Cookbook, all by Packt Publishing.
It was extra special that my second daughter, Masha, was born while reviewing this book. Thanks to my daughters, Sasha and Masha, for keeping me energetic.
For support files and downloads related to your book, please visit www.PacktPub.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.PacktPub.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.PacktPub.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.
https://www.packtpub.com/mapt
Get the most in-demand software skills with Mapt. Mapt gives you full access to all Packt books and video courses, as well as industry-leading tools to help you plan your personal development and advance your career.
Thanks for purchasing this Packt book. At Packt, quality is at the heart of our editorial process. To help us improve, please leave us an honest review on this book's Amazon page at https://www.amazon.com/dp/1787282589.
If you'd like to join our team of regular reviewers, you can e-mail us at [email protected]. We award our regular reviewers with free eBooks and videos in exchange for their valuable feedback. Help us be relentless in improving our products!
Welcome to Mastering Ansible, your guide to a variety of advanced features and functionalities provided by Ansible, the automation and orchestration tool. This book will provide readers with the knowledge and skills to truly understand how Ansible functions at a fundamental level. This will allow readers to master the advanced capabilities needed to tackle complex automation challenges of today and the future. Readers will gain knowledge of Ansible workflows, explore use cases for advanced features, troubleshoot unexpected behavior, and extend Ansible through customization.
Chapter 1, 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, 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 4, Controlling Task Conditions, describes the changing of the default behavior of Ansible to customize task error and change conditions.
Chapter 5, Composing Reusable Ansible Content with Roles, covers the approach to move beyond executing loosely-organized tasks on hosts to encapsulating clean and reusable abstractions to apply a specific functionality of a target set of hosts.
Chapter 6, Minimizing Downtime with Rolling Deployments, explains the common deployment and upgrade strategies to showcase relevant Ansible features.
Chapter 7, Troubleshooting Ansible, takes you through the various methods that can be employed to examine, introspect, modify, and debug the operations of Ansible.
Chapter 8, Extending Ansible, discovers the various ways in which new capabilities can be added to Ansible via modules, plugins, and inventory sources.
Chapter 9, Infrastructure Provisioning, will be working with cloud infrastructure providers and container systems to create an infrastructure to manage.
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.6 or 2.7 installed (Windows isn't supported for the control machine). This includes Red Hat, Debian, CentOS, OS X, any of the BSDs, and so on.
This book uses the Ansible 2.2.x.x series release.
Ansible installation instructions can be found at http://docs.ansible.com/ansible/intro_installation.html.
Some examples use Docker, version 1.12.6. Docker installation instructions can be found at: http://www.docker.com/community-edition.
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.
In this book, you will find a number of text styles that distinguish between different kinds of information. Here are some examples of these styles and an explanation of their meaning.
Code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles are shown as follows: "We'll make use of this in a failed_when statement."
A block of code is set as follows:
- name: query sessions command: /sbin/iscsiadm –m session register: sessions failed_when: sessions.rc not in (0, 21)Any command-line input or output is written as follows:
$ source ./hacking/env-setupWarnings or important notes appear in a box like this.
Tips and tricks appear like this.
Feedback from our readers is always welcome. Let us know what you think about this book-what you liked or disliked. Reader feedback is important for us as it helps us develop titles that you will really get the most out of. To send us general feedback, simply e-mail [email protected], and mention the book's title in the subject of your message. If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide at www.packtpub.com/authors.
Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase.
You can download the example code files for this book from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
You can download the code files by following these steps:
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Mastering-Ansible-Second-Edition. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
We also provide you with a PDF file that has color images of the screenshots/diagrams used in this book. The color images will help you better understand the changes in the output. You can download this file from https://www.packtpub.com/sites/default/files/downloads/MasteringAnsibleSecondEdition_ColorImages.pdf.
Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you find a mistake in one of our books-maybe a mistake in the text or the code-we would be grateful if you could report this to us. By doing so, you can save other readers from frustration and help us improve subsequent versions of this book. If you find any errata, please report them by visiting http://www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details of your errata. Once your errata are verified, your submission will be accepted and the errata will be uploaded to our website or added to any list of existing errata under the Errata section of that title.
To view the previously submitted errata, go to https://www.packtpub.com/books/content/support and enter the name of the book in the search field. The required information will appear under the Errata section.
Piracy of copyrighted material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works in any form on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy.
Please contact us at [email protected] with a link to the suspected pirated material.
We appreciate your help in protecting our authors and our ability to bring you valuable content.
If you have a problem with any aspect of this book, you can contact us at [email protected], and we will do our best to address the problem.
This chapter provides a detailed exploration of the architecture and design of how Ansible goes about performing tasks on your behalf. We will cover the basic concepts of inventory parsing and how the data is discovered, and then dive into playbook parsing. We will take a walk through module preparation, transportation, and execution. Lastly, we will detail variable types and find out where variables can be located, the scope they can be used in, 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:
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 for the operating system and version that you might be using. This book will assume the use of the Ansible 2.2.x.x version. To discover the version in use on a system with Ansible already installed, make use of the version argument, that is, either ansible or ansible-playbook:
Note that ansible is the executable for doing adhoc 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 order changed slightly in version 1.5, with the new order being:
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 no settings in the ansible.cfg file that would affect the default operation of Ansible.
In Ansible, nothing happens without an inventory. Even ad hoc actions performed on localhost require an inventory, even if that inventory consists just 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 as well, and we'll explore the options available to you.
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.nameThat 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 hostname, or the special all group. This can be quite tedious when developing a playbook that operates across different sets of 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 some groupings:
[web] mastery.example.name [dns] backend.example.name [database] backend.example.name [frontend:children] web [backend:children] dns databaseWhat 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 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.
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 preproduction 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 staging or production environment because it refers to the generic group names that exist in both inventories. Simply refer to the right inventory to execute it in the desired environment.
Inventories provide more than just system names and groupings. Data about the systems can be passed along as well. This can include:
Variables are a powerful construct within Ansible and can be used in a variety of ways, not just the ways 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 is how to expand the dataset. Note that variable data can come from many different sources, and one source may override another source. 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=ottoIn 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 provided IP address rather than performing a DNS lookup on the name mastery.example.name. There are a number of other behavioral inventory variables, which are listed at the end of this section along with their intended use.
As of version 2.0, the longer form of some behavioral inventory parameters has been deprecated. The ssh part of ansible_ssh_host, ansible_ssh_user, and ansible_ssh_port is no longer required. A future release may ignore the longer form of these variables.
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 behavior they intend to modify:
Inventory parameters
Behaviour
ansible_host
This is the DNS name or IP address used to connect to the host, if different from the inventory name, or the name of the Docker container to connect to.
ansible_port
This is the SSH port number, if not 22.
ansible_user
This is the default SSH username or user inside a Docker container to use.
ansible_ssh_pass
This is the SSH password to use (this is insecure; we strongly recommend using --ask-pass or the SSH keys).
ansible_ssh_private_key_file
This is the private key file used by SSH. This is useful if you use multiple keys and you don't want to use 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
This setting is always appended to the default sftp command-line arguments.
ansible_scp_extra_args
This setting is always appended to the default scp command-line arguments.
ansible_ssh_extra_args
This setting is always appended to the default ssh command-line arguments.
ansible_ssh_pipelining
This setting uses a Boolean to define whether or not 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
The method to use for privilege escalation. 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, or docker. The default is paramiko before Ansible 1.2, and smart afterwards, which detects whether the usage of ssh will be feasible based on whether the SSH feature ControlPersist is supported.
ansible_docker_extra_args
This is a string of any extra arguments that can be passed to Docker. This is mainly used to define a remote Docker daemon to use.
ansible_shell_type
This is the shell type of the target system. By default, commands are formatted using the sh-style syntax. Setting this to csh or fish will cause commands to be executed on target systems to follow the syntax of csh or fish instead.
ansible_shell_executable
This sets the shell tool that will be used on the target system. This should only be used if the default of /bin/sh is not possible to use.
ansible_python_interpreter
This is the target host Python path. This is useful for systems with more than one Python, systems that are not located at /usr/bin/python (such as *BSD), or for systems where /usr/bin/python is not a 2.X series Python. We do not use the /usr/bin/env mechanism as it requires the remote user's path to be set right and also assumes that the Python executable is named Python, where the executable might be named something like python26.
ansible_*_interpreter
This works for anything such as Ruby or Perl and works just like ansible_python_interpreter. This replaces the shebang of modules which run on that host.
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 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 script that Ansible will call at runtime to discover real-time inventory data. This script 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 this in a later chapter, Ansible provides a number of example inventory plugins, including but not limited to:
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 iniconfig file read from a known location or environment variables read from the shell environment used to execute ansible or ansible-playbook.
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.
In Chapter 8, Extending Ansible, we will develop our own custom inventory plugin to demonstrate how they operate.
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 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, we will create a task same as this:
- name: add new node into runtime inventory add_host: name: newmastery.example.name groups: web ansible_host: 192.168.10.30This 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
