Reader small image

You're reading from  Practical Ansible - Second Edition

Product typeBook
Published inSep 2023
PublisherPackt
ISBN-139781805129974
Edition2nd Edition
Right arrow
Authors (3):
James Freeman
James Freeman
author image
James Freeman

James Freeman is an accomplished IT professional with over 25 years' experience in the technology industry. He has more than a decade of first-hand experience in solving real-world enterprise problems in production environments using Ansible, open source, and AWS. As part of this work, he frequently introduces Ansible as a new technology to businesses and CTOs for the first time. In addition, he has co-authored five books and one video training course on Ansible, facilitated bespoke Ansible workshops and training sessions, and presented at both international conferences and meetups on Ansible.
Read more about James Freeman

Fabio Alessandro Locati
Fabio Alessandro Locati
author image
Fabio Alessandro Locati

Fabio Alessandro Locati – commonly known as Fale – is an EMEA associate principal solutions architect at Red Hat, a public speaker, an author, and an open source contributor. His primary areas of expertise are Linux, automation, security, and cloud technologies. Fale has more than 15 years of working experience in IT, with many of them spent consulting for various organizations, including dozens of Fortune 500 companies. Fale has written Learning Ansible 2.7, Learning Ansible 2, and OpenStack Cloud Security, and has been part of the review process of multiple books.
Read more about Fabio Alessandro Locati

Daniel Oh
Daniel Oh
author image
Daniel Oh

Daniel Oh is a principal technical marketing manager at Red Hat. He provides runtimes, frameworks, fast data access, and high-performance messaging in flexible, easy-to-use, cost-effective, open, and collaborative ways. He's also a CNCF ambassador and DevOps Institute ambassador who evangelizes how to design and develop cloud-native serverless microservices and deploy them to multi/hybrid cloud-native platforms based on CNCF projects. Daniel loves to share his developer experiences with DevOps folks in terms of how to evolve traditional microservices to cloud-native, event-driven, and serverless applications via technical workshops, brown bag sessions, hackathons, and hands-on labs across regions at many international conferences.
Read more about Daniel Oh

View More author details
Right arrow

Advanced Ansible Topics

Up to this point, we have worked hard to give you a solid foundation in Ansible so that, whatever your desired automation task, you can implement it with ease and confidence. However, when you really start to ramp up your automation, how do you ensure that you can handle any condition that arises in a graceful manner? For example, how can you ensure that when you have to initiate long-running actions, you can run them asynchronously and come back to them to check on the results reliably later? Or, if you are updating a large group of servers, how can you ensure that the play fails early if a handful of servers suffer failures? The last thing you want to do is to roll out a broken update (let’s face it, problems do occur with everyone’s code from time to time) across 100 servers—far better to detect that a small percentage have failed and abort the entire play on this basis than attempt to continue and break an entire load-balanced cluster...

Technical requirements

This chapter assumes that you have set up your control host with Ansible, as detailed in Chapter 1, Getting Started with Ansible, and are using the most recent version available. The examples in this chapter are tested with Ansible 2.15. This chapter also assumes that you have at least one additional host to test against and, ideally, this should be Linux-based. Although we will give specific examples of hostnames in this chapter, you are free to substitute them with your own hostname and/or IP addresses; details of how to do this are provided at the appropriate places.

The code bundle for this chapter is available at https://github.com/PacktPublishing/Practical-Ansible-Second-Edition/tree/main/Chapter%209.

Asynchronous versus synchronous actions

As we have seen in this book so far, Ansible plays are executed in sequence, with each task running to completion before the next task is started. Although this is often advantageous for flow control and logical sequencing, there are times when you may not want this. In particular, it might be the case that a particular task runs for longer than the configured SSH connection timeout, and as Ansible uses SSH to perform its automation tasks on most platforms, this would be an issue.

Fortunately, Ansible tasks can be run asynchronously—that is to say, tasks can be run in the background on the target host and polled on a regular basis. This is in contrast to synchronous tasks, where the connection to the target host is kept open until the task completes (which runs the risk of a timeout occurring).

As ever, let’s explore this through a practical example. Suppose we have two servers in a simple INI-formatted inventory:

[frontends...

Controlling play execution for rolling updates

By default, Ansible parallelizes tasks on multiple hosts at the same time to speed up automation tasks in large inventories. The setting for this is defined by the forks parameter in the Ansible configuration file, which defaults to 5 (so, by default, Ansible attempts to run its automation job on five hosts at the same time).

In a load-balanced environment, this is not ideal, especially if you want to avoid downtime. Suppose we have five frontend servers in an inventory (or perhaps even fewer). If we allow Ansible to update all of these at the same time, the end users may experience a loss of service. So, it is important to consider updating all of the servers at different times. Let’s reuse our inventory from the previous section with just two servers in it. Obviously, if these were in a load-balanced environment, it would be vital that we only update one of these at a time; if both were taken out of service simultaneously,...

Configuring the maximum failure percentage

In its default mode of operation, Ansible continues to execute a play on a batch of servers (the batch size is determined by the serial directive we discussed in the preceding section) as long as there are hosts in the inventory and a failure isn’t recorded. Obviously, in a highly available or load-balanced environment (such as the one we discussed previously), this is not ideal. If there is a bug in your play, or perhaps a problem with the code being rolled out, the last thing that you want is for Ansible to faithfully roll it out to all servers in the cluster, causing a service outage because all the nodes suffered a failed upgrade. It would be far better, in this kind of environment, to fail early on and leave at least some hosts in the cluster untouched until someone can intervene and resolve the issue.

For our practical example, let’s consider an expanded inventory with 10 hosts in it. We’ll define this as follows...

Setting task execution delegation

In every play we have run so far, we have assumed that all the tasks are executed on each host in the inventory in turn. However, what if you need to run one or two tasks on a different host? For example, we have talked about the concept of automating upgrades on clusters. Logically, however, we would want to automate the entire process, including the removal of each host in turn from the load balancer and their return after the task is completed.

Although we still want to run our play across our entire inventory, we certainly don’t want to run the load balancer commands from those hosts. Let’s once again explain this in more detail with a practical example. We’ll reuse the two simple host inventories that we used earlier in this chapter:

[frontends]
frt01.example.com
frt02.example.com

Now, to work on this, let’s create two simple shell scripts in the same directory as our playbook. These are only examples, as setting...

Using the run_once option

When working with clusters, you will sometimes encounter a task that should only be executed once for the entire cluster. For example, you might want to upgrade the schema of a clustered database or issue a command to reconfigure a Pacemaker cluster, which would typically be issued on one node and then automatically propagated to all other nodes by the cluster management software. You could, of course, address this with a special inventory with only one host in it, or even by writing a special play that references one host from the inventory, but this is inefficient and starts to make your code fragmented.

Instead, you can write your code as you normally would but make use of the special run_once directive for any tasks you want to run only once on your inventory. For example, let’s reuse the 10-host inventory that we defined earlier in this chapter. Now, let’s proceed to demonstrate this option, as follows:

  1. Create the simple playbook...

Running playbooks locally

It is important to note that when we talk about running a playbook locally with Ansible, it is not the same as talking about running it on localhost. If we run a playbook on localhost, Ansible actually sets up an SSH connection to localhost (it doesn’t differentiate its behavior or attempt to detect whether a host in the inventory is local or remote—it simply tries faithfully to connect).

Indeed, we can try creating a local inventory file with the following contents:

[local]
localhost

Now, if we attempt to run the ping module in an ad hoc command against this inventory, we see the following:

$ ansible -i localhosts -m ping all --ask-pass
The authenticity of host 'localhost (::1)' can't be established.
ECDSA key fingerprint is SHA256:DUwVxH+45432pSr9qsN8Av4l0KJJ+r5jTo123n3XGvZs.
ECDSA key fingerprint is MD5:78:d1:dc:23:cc:28:51:42:eb:fb:58:49:ab:92:b6:96.
Are you sure you want to continue connecting (yes/no)? yes
SSH...

Working with proxies and jump hosts

Often, when it comes to configuring core network devices, these are isolated from the main network via a proxy or jump host. Ansible lends itself well to automating network device configuration as most of it is performed over SSH; however, this is only helpful in a scenario where Ansible can either be installed and operated from the jump host or, better yet, can operate via a host such as this.

Fortunately, Ansible can do exactly that. Let’s assume that you have two Cumulus Networks switches in your network (these are based on a special distribution of Linux for switching hardware, which is very similar to Debian). These two switches have the cmls01.example.com and cmls02.example.com hostnames, but both can only be accessed from a host called bastion.example.com.

The configuration to support our bastion host is performed in the inventory, rather than in the playbook. We begin by defining an inventory group with the switches in, in the...

Configuring playbook prompts

So far, all of our playbooks have had their data specified for them at runtime in variables we defined within the playbook. However, what if you actually want to obtain information from someone during a playbook run? Perhaps you want a user to select a version of a package to install? Or, perhaps you want to obtain a password from a user for an authentication task without storing it anywhere. (Although Ansible Vault can encrypt the data at rest, some companies may forbid the storing of passwords and other such credentials in tools that they have not evaluated.) Fortunately, for these instances (and many more), Ansible can prompt you for user input and store the input in a variable for future processing.

Let’s reuse the two host frontend inventories we defined at the beginning of this chapter. Now, let’s demonstrate how to capture data from users during a playbook run with a practical example:

  1. Create a simple play definition in the...

Placing tags in the plays and tasks

We have discussed, at many points in this book, that as your confidence and experience with Ansible grows, it is likely that your playbooks will grow, both in scale and complexity. While this is undoubtedly a good thing, there may be times when you only want to run a subset of a playbook, rather than running it from beginning to end. We discussed how to conditionally run tasks based on the value of a variable or fact, but is there a way we can run them based on a selection made when the playbook is run?

Tags in Ansible plays are the solution to this, and in this section, we will build a simple playbook with two tasks—each bearing a different tag—to show you how tags work. We will work with the two simple host inventories that we worked with previously:

  1. Create the following simple playbook to perform two tasks—one to install the nginx package and the other to deploy a configuration file from a template:
    ---
    - name: Simple...

Securing data with Ansible Vault

Ansible Vault is a tool included with Ansible that allows you to encrypt your sensitive data at rest, while also using it in a playbook. Often, it is necessary to store login credentials or other sensitive data in a variable to allow a playbook to run unattended. However, this risks exposing your data to people who might use it with malicious intent. Fortunately, Ansible Vault secures your data at rest using AES-256 encryption, meaning your sensitive data is safe from prying eyes.

Let’s proceed with a simple example that shows you how you can use Ansible Vault:

  1. Start by creating a new vault to store sensitive data in; we will call this file secret.yml. You can create this using the following command:
    $ ansible-vault create secret.yml
    New Vault password:
    Confirm New Vault password:

Enter the password you have chosen for the vault when prompted and confirm it by entering it a second time (the vault that accompanies this book on...

Summary

Ansible has many advanced features that allow you to run your playbooks in a variety of scenarios, whether that is upgrading a cluster of servers in a controlled manner; working with devices on a secure, isolated network; or controlling your playbook flow with prompts and tags. Ansible has been adopted by a large and ever-growing user base and, as such, is designed and evolved around solving real-world problems. Most of the advanced features of Ansible we discussed are centered around exactly this—solving real-world problems.

In this chapter, you learned about running tasks asynchronously in Ansible, before looking at the various features available for running playbooks to upgrade a cluster, such as running tasks on small batches of inventory hosts, failing a play early if a certain percentage of hosts fail, delegating tasks to a specific host, and even running tasks once, regardless of your inventory (or batch) size. You also learned about the difference between...

Questions

  1. Which parameter allows you to configure the maximum number of hosts in a batch that will fail before a play is aborted?
    1. percentage
    2. max_fail
    3. max_fail_percentage
    4. max_percentage
    5. fail_percentage
  2. True or false? You can use the --ask-vault-pass parameter to use the vault to keep sensitive data at rest:
    1. True
    2. False
  3. True or false? To run a playbook asynchronously, you need to use the async keyword:
    1. True
    2. False

Further reading

If you install Passlib, which is a password-hashing library for Python 3, vars_prompt is encrypted with any crypt scheme (such as descrypt, md5crypt, sha56_crypt, and more). You can learn more about this here:

https://passlib.readthedocs.io/en/stable/

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Practical Ansible - Second Edition
Published in: Sep 2023Publisher: PacktISBN-13: 9781805129974
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime

Authors (3)

author image
James Freeman

James Freeman is an accomplished IT professional with over 25 years' experience in the technology industry. He has more than a decade of first-hand experience in solving real-world enterprise problems in production environments using Ansible, open source, and AWS. As part of this work, he frequently introduces Ansible as a new technology to businesses and CTOs for the first time. In addition, he has co-authored five books and one video training course on Ansible, facilitated bespoke Ansible workshops and training sessions, and presented at both international conferences and meetups on Ansible.
Read more about James Freeman

author image
Fabio Alessandro Locati

Fabio Alessandro Locati – commonly known as Fale – is an EMEA associate principal solutions architect at Red Hat, a public speaker, an author, and an open source contributor. His primary areas of expertise are Linux, automation, security, and cloud technologies. Fale has more than 15 years of working experience in IT, with many of them spent consulting for various organizations, including dozens of Fortune 500 companies. Fale has written Learning Ansible 2.7, Learning Ansible 2, and OpenStack Cloud Security, and has been part of the review process of multiple books.
Read more about Fabio Alessandro Locati

author image
Daniel Oh

Daniel Oh is a principal technical marketing manager at Red Hat. He provides runtimes, frameworks, fast data access, and high-performance messaging in flexible, easy-to-use, cost-effective, open, and collaborative ways. He's also a CNCF ambassador and DevOps Institute ambassador who evangelizes how to design and develop cloud-native serverless microservices and deploy them to multi/hybrid cloud-native platforms based on CNCF projects. Daniel loves to share his developer experiences with DevOps folks in terms of how to evolve traditional microservices to cloud-native, event-driven, and serverless applications via technical workshops, brown bag sessions, hackathons, and hands-on labs across regions at many international conferences.
Read more about Daniel Oh