Chapter 1. Introduction
It’s an interesting time to be working in the IT industry. We no longer deliver software to our customers by installing a program on a single machine and calling it a day. Instead, we are all gradually turning into cloud engineers.
We now deploy software applications by stringing together services that run on a distributed set of computing resources and communicate over different networking protocols. A typical application can include web servers, application servers, memory-based caching systems, task queues, message queues, SQL databases, NoSQL datastores, and load balancers.
IT professionals also need to make sure to have the proper redundancies in place, so that when failures happen (and they will), our software systems will handle them gracefully. Then there are the secondary services that we also need to deploy and maintain, such as logging, monitoring, and analytics, as well as third-party services we need to interact with, such as infrastructure-as-a-service (IaaS) endpoints for managing virtual machine instances.1
You can wire up these services by hand: spinning up the servers you need, logging into each one, installing packages, editing config files, and so forth, but it’s a pain. It’s time-consuming, error-prone, and just plain dull to do this kind of work manually, especially around the third or fourth time. And for more complex tasks, like standing up an OpenStack cloud, doing it by hand is madness. There must a better way.
If you’re reading this, you’re probably already sold on the idea of configuration management and considering adopting Ansible as your configuration management tool. Whether you’re a developer deploying your code to production, or you’re a systems administrator looking for a better way to automate, I think you’ll find Ansible to be an excellent solution to your problem.
A Note About Versions
The example code in this book was tested against several versions of Ansible. Ansible 5.9.0 is the latest version as of this writing; Ansible Tower includes version 2.9.27 in the most recent release. Ansible 2.8 went End of Life with the release of 2.8.20 on April 13, 2021. Expect Ansible to evolve further.
For years the Ansible community has been highly active in creating roles and modules—so active that there are thousands of modules and more than 20,000 roles. The difficulties of managing a project of this scale led creators to reorganize the Ansible content into three parts:
-
Core components, created by the Ansible team
-
Certified content, created by Red Hat’s business partners
-
Community content, created by thousands of enthusiasts worldwide
Ansible 2.9 has lots of built-in features, and later versions are more composable. This new setup makes it more easily maintainable as a whole.
The examples provided in this book should work in various versions of Ansible, but version changes in general call for testing, which we will address in Chapter 14.
What’s with the Name Ansible?
It’s a science-fiction reference. An ansible is a fictional communication device that can transfer information faster than the speed of light. Ursula K. Le Guin invented the concept in her book Rocannon’s World (Ace Books, 1966), and other sci-fi authors have since borrowed the idea, including Orson Scott Card. Ansible cofounder Michael DeHaan took the name Ansible from Card’s book Ender’s Game (Tor, 1985). In that book, the ansible was used to control many remote ships at once, over vast distances. Think of it as a metaphor for controlling remote servers.
Ansible: What Is It Good For?
Ansible is often described as a configuration management tool and is typically mentioned in the same breath as Puppet, Chef, and Salt. When IT professionals talk about configuration management, we typically mean writing some kind of state description for our servers, then using a tool to enforce that the servers are, indeed, in that state: the right packages are installed, configuration files have the expected values and have the expected permissions, the right services are running, and so on. Like other configuration management tools, Ansible exposes a domain-specific language (DSL) that you use to describe the state of your servers.
You can use these tools for software deployment as well. When people talk about deployment, they are usually referring to the process of generating binaries or static assets (if necessary) from software written by in-house developers, copying the required files to servers, adding configuration properties and environment variables, and starting services in a particular order. Capistrano and Fabric are two examples of open source deployment tools. Ansible is a great tool for deployment as well as configuration management. Using a single tool for both makes life simpler for the folks responsible for system integration.
Some people talk about the need to orchestrate deployments. Orchestration is the process of coordinating deployment when multiple remote servers are involved and things must happen in a specific order. For example, you might need to bring up the database before bringing up the web servers, or take web servers out of the load balancer one at a time to upgrade them without downtime. DeHaan designed Ansible from the ground up to be good at this, and to perform actions on multiple servers. It has a refreshingly simple model for controlling the order in which actions happen.
Finally, you’ll hear people talk about provisioning new servers. In the context of public clouds such as Amazon EC2, provisioning refers to spinning up new virtual machine instances or cloud-native software as a service (SaaS). Ansible has got you covered here, with modules for talking to clouds including EC2, Azure,2 Digital Ocean, Google Compute Engine, Linode, and Rackspace,3 as well as any clouds that support the OpenStack APIs.
Note
Confusingly, the Vagrant tool, covered later in this chapter, uses the term provisioner to refer to a tool that does configuration management. It thus refers to Ansible as a kind of provisioner. Vagrant calls tools that create machines, such as VirtualBox and VMWare, providers. Vagrant uses the term machine to refer to a virtual machine and box to refer to a virtual machine image.
How Ansible Works
Figure 1-1 shows a sample use case of Ansible in action. A user we’ll call Alice is using Ansible to configure three Ubuntu-based web servers to run NGINX. She has written a script called webservers.yml. In Ansible, the equivalent of a script is called a playbook. A playbook describes which hosts (what Ansible calls remote servers) to configure, and an ordered list of tasks to perform on those hosts. In this example, the hosts are web1, web2, and web3, and the tasks are things such as these:
-
Install NGINX
-
Generate a NGINX configuration file
-
Copy over the security certificate
-
Start the NGINX service
In the next chapter, we’ll elaborate what’s in this playbook; for now, we’ll focus on its role in the overall process. Alice executes the playbook by using the ansible-playbook
command. Alice starts her Ansible playbook by typing first the command and then the name of the playbook on a terminal line:
$ ansible-playbook webservers.yml
Ansible will make SSH connections in parallel to web1, web2, and web3. It will then execute the first task on the list on all three hosts simultaneously. In this example, the first task is installing the NGINX package, so the task in the playbook would look something like this:
- name: Install nginx package: name: nginx
Ansible will do the following:
-
Generate a Python script that installs the NGINX package
-
Copy the script to web1, web2, and web3
-
Execute the script on web1, web2, and web3
-
Wait for the script to complete execution on all hosts
Ansible will then move to the next task in the list and go through these same four steps.
It’s important to note the following:
-
Ansible runs each task in parallel across all hosts.
-
Ansible waits until all hosts have completed a task before moving to the next task.
-
Ansible runs the tasks in the order that you specify them.
What’s So Great About Ansible?
There are several open source configuration management tools out there to choose from, so why choose Ansible? Here are 21 reasons that drew us to it. In short: Ansible is simple, powerful, and secure.
Simple
Ansible was designed to have a dead simple setup process and a minimal learning curve.
Easy-to-read syntax
Ansible uses the YAML file format and Jinja2 templating, both of which are easy to pick up. Recall that Ansible configuration management scripts are called playbooks. Ansible actually builds the playbook syntax on top of YAML, which is a data format language that was designed to be easy for humans to read and write. In a way, YAML is to JSON what Markdown is to HTML.
Little to nothing to install on the remote hosts
To manage servers with Ansible, Linux servers need to have SSH and Python installed, while Windows servers need WinRM enabled. On Windows, Ansible uses PowerShell instead of Python, so there is no need to preinstall an agent or any other software on the host.
On the control machine (that is, the machine that you use to control remote machines), it is best to install Python 3.8 or later. Depending on the resources you manage with Ansible, you might have external library prerequisites. Check the documentation to see whether a module has specific requirements.
Ansible scales down
The authors of this book use Ansible to manage hundreds of nodes. But what got us hooked is how it scales down. You can use Ansible on very modest hardware, like a Raspberry Pi or an old PC. Using it to configure a single node is easy: simply write a single playbook. Ansible obeys Alan Kay’s maxim: “Simple things should be simple; complex things should be possible.”
System abstraction
Ansible works with simple abstractions of system resources like files, directories, users, groups, services, packages, and web services.
By way of comparison, let’s look at how to configure a directory in the shell. You would use these three commands:
mkdir -p /etc/skel/.ssh chown root:root /etc/skel/.ssh chmod go-wrx /etc/skel/.ssh
By contrast, Ansible offers the file
module as an abstraction, where you define the parameters of the desired state. This one action has the same effect as the three shell commands combined:
- name: Ensure .ssh directory in user skeleton file: path: /etc/skel/.ssh mode: '0700' owner: root group: root state: directory
With this layer of abstraction, you can use the same configuration management scripts to manage servers running Linux distributions. For example, instead of having to deal with a specific package manager like dnf, yum, or apt, Ansible has a “package” abstraction that you can use instead (just be aware that package names might differ). But you can also use the system-specific abstractions if you prefer.
If you really want to, you can write your Ansible playbooks to take different actions, depending on the variety of operating systems of the remote servers. But Bas, one of the authors of this book, tries to avoid that where he can; he instead focuses on writing playbooks for the systems that are in actual use.
Top to bottom tasks
Books on configuration management often mention the concept of convergence, or eventual consistent state. Convergence in configuration management is strongly associated with the configuration management system CFEngine by Mark Burgess. If a configuration management system is convergent, the system may run multiple times to put a server into its desired state, with each run bringing the server closer to that state.
Eventual consistent state does not really apply to Ansible, since it does not run multiple times to configure servers. Instead, Ansible modules work in such a way that running a playbook a single time should put each server into the desired state.
Powerful
Having Ansible at your disposal can bring huge productivity gains in several areas of systems management. The high-level abstractions Ansible provides (like roles) make it so that you can set up and configure things faster and potentially more securely.
Batteries included
You can use Ansible to execute arbitrary shell commands on your remote servers, but its real power comes from the wide variety of modules available. You use modules to perform tasks such as installing a package, restarting a service, or copying a configuration file.
As you will see later, Ansible modules are declarative; you use them to describe the state you want the server to be in. For example, you would invoke the user
module like this to ensure there is an account named “deploy” in the web group:
- name: Ensure deploy user exists user: name: deploy group: web
Push-based
Chef and Puppet are configuration management systems that use agents. They are pull-based by default. Agents installed on the servers periodically check in with a central service and download configuration information from the service. Making configuration management changes to servers goes something like this:
-
You: make a change to a configuration management script.
-
You: push the change up to a configuration management central service.
-
Agent on server: wakes up after periodic timer fires.
-
Agent on server: connects to configuration management central service.
-
Agent on server: downloads new configuration management scripts.
-
Agent on server: executes configuration management scripts locally that change server state.
In contrast, Ansible is push-based by default. Making a change looks like this:
-
You: make a change to a playbook.
-
You: run the new playbook.
-
Ansible: connects to servers and executes modules that change the state of the servers.
As soon as you run the ansible-playbook
command, Ansible connects to the remote servers and does its thing; this lowers the risk of random servers potentially breaking whenever their scheduled tasks fail to change things successfully. The push-based approach has a significant advantage: you control when the changes happen to the servers. You do not need to wait around for a timer to expire. Each step in a playbook can target one or a group of servers. You get more work done instead of logging into the servers by hand.
Multitier orchestration
Push mode also allows you to use Ansible for multitier orchestration, managing distinct groups of machines for an operation like an update. You can orchestrate the monitoring system, the load balancers, the databases, and the web servers with specific instructions so they work in concert. That’s very hard to do with a pull-based system.
Masterless
Advocates of the pull-based approach claim that it is superior for scaling to large numbers of servers and for dealing with new servers that can come online anytime. A central configuration management system, however, slowly stops working when thousands of agents pull their configuration at the same time, especially when they need multiple runs to converge. In comparison, Ansible comes with the ansible-pull
command, which can pull playbooks from a VCS repository like GitHub. Ansible does not need a master, but you can use a central system to run playbooks if you want to.
Pluggable and embeddable
A sizable part of Ansible’s functionality comes from the Ansible Plugin System, of which the Lookup and Filter plug-ins are most used. Plug-ins augment Ansible’s core functionality with logic and features that are accessible to all modules. Modules introduce new “verbs” to the Ansible language. You can write your own plug-ins (see Chapter 10) and modules (Chapter 12) in Python.
You can integrate Ansible into other products: Kubernetes and Ansible Tower are examples of successful integrations. Ansible Runner “is a tool and python library that helps when interfacing with Ansible directly or as part of another system whether that be through a container image interface, as a standalone tool, or as a Python module that can be imported.”4
Using the ansible-runner library, you can run an Ansible playbook from within a Python script:
#!/usr/bin/env python3 import ansible_runner r = ansible_runner.run(private_data_dir='./playbooks', playbook='playbook.yml') print("{}: {}".format(r.status, r.rc)) print("Final status:") print(r.stats)
Works with lots of stuff
Ansible modules cater to a wide range of system administration tasks. This list has the categories of the kinds of modules that you can use. These link to the module index in the documentation:
Really scalable
Large enterprises use Ansible successfully in production with tens of thousands of nodes and have excellent support for environments where servers are dynamically added and removed. Organizations with hundreds of software teams typically use AWX or a combination of Ansible Tower and Automation Hub for auditability, and for security with role-based access controls.
Worried about the scalability of SSH? Ansible uses SSH multiplexing to optimize performance, and there are folks out there who are managing thousands of nodes with Ansible (see Chapter 12 of this book).
Secure
Automation with Ansible helps us to improve system security to security baselines and compliance standards.
Codified knowledge
Your authors like to think of Ansible playbooks as executable documentation. Playbooks are like the README files that used to describe the commands you had to type out to deploy your software, except that these instructions will never go out of date because they are also the code that executes. Product experts can create playbooks that take best practices into account. When novices use such a playbook to install the product, they can be sure they’ll get a good result.
Reproducible systems
If you set up your entire system with Ansible, it will pass what Steve Traugott calls the “tenth-floor test”: “Can I grab a random machine that’s never been backed up and throw it out the tenth-floor window without losing sysadmin work?”
Equivalent environments
Ansible has a clever way to organize content that helps define configuration at the proper level. It is easy to create a setup for distinct development, testing, staging, and production environments. A staging environment is designed to be as similar as possible to the production environment so that developers can detect any problems before changes go live.
Encrypted variables
If you need to store sensitive data such as passwords or tokens, then ansible-vault
is an effective tool to use. We use it to store encrypted variables in Git. We’ll discuss it in detail in Chapter 8.
Secure transport
Ansible simply uses Secure Shell (SSH) for Linux and WinRM for Windows. We typically secure and harden these widely used systems-management protocols with strong configuration and firewall settings.
If you prefer using a pull-based model, Ansible has official support for pull mode, using a tool it ships with called ansible-pull
. This book won’t cover pull mode, but you can read more about it in the official Ansible documentation.
Idempotency
Modules are also idempotent. Idempotence is a nice property because it means that it is safe to run an Ansible playbook multiple times against a server. Let’s see what that means when we need a user named deploy
:
- name: Ensure deploy user exists user: name: deploy group: web
If the deploy
user does not exist, Ansible will create it. If it does exist, Ansible will not do anything. This is a vast improvement over the homegrown shell script approach, where running the shell script a second time might have a different (and unintended) effect.5
No daemons
There is no Ansible agent listening on a port. Therefore, when you use Ansible, there is no extra attack surface. (There is still an attack surface with software supply chain elements like Python libraries and other imported content.)
What Is Ansible, Inc.’s Relationship to Ansible?
The name Ansible refers to both the software and the company that runs the open source project. Michael DeHaan, the creator of Ansible the software, is the former CTO of Ansible the company. To avoid confusion, we refer to the software as Ansible and to the company as Ansible, Inc.
Ansible, Inc. sells training and consulting services for Ansible, as well as a web-based management tool called Ansible Tower, which we cover in Chapter 19. In October 2015, Red Hat bought Ansible, Inc.; IBM bought Red Hat in 2019.
Is Ansible Too Simple?
When Lorin was working on an earlier edition of this book, the editor mentioned that “some folks who use the XYZ configuration management tool call Ansible a for-loop over SSH scripts.” If you are considering switching over from another configuration management tool, you might be concerned at this point about whether Ansible is powerful enough to meet your needs.
As you will soon learn, Ansible supplies a lot more functionality than shell scripts. In addition to idempotence, Ansible has excellent support for templating, as well as defining variables at different scopes. Anybody who thinks Ansible is equivalent to working with shell scripts has never had to support a nontrivial program written in shell. We will always choose Ansible over shell scripts for configuration management tasks if given a choice.
What Do I Need to Know?
To be productive with Ansible, you need to be familiar with basic Unix/Linux system administration tasks. Ansible makes it easy to automate your tasks, but it is not the kind of tool that “automagically” does things that you otherwise would not know how to do.
For this book, we have assumed that you are familiar with at least one Linux distribution (such as Ubuntu, RHEL/CentOS, or SUSE), and that you know how to:
-
Connect to a remote machine using SSH
-
Interact with the Bash command-line shell (pipes and redirection)
-
Install packages
-
Use the sudo command
-
Check and set file permissions
-
Start and stop services
-
Set environment variables
-
Write scripts (any language)
If these concepts are all familiar to you, you are good to go with Ansible.
We will not assume you have knowledge of any particular programming language. For instance, you do not need to know Python to use Ansible unless you want to publish your own module.
What Isn’t Covered
This book is not an exhaustive treatment of Ansible. The first part is designed to get you working productively in Ansible as quickly as possible. Then it describes how to perform certain tasks that are not obvious from the official documentation.
We don’t cover all of Ansible’s modules in detail: there are more than 3,500 of them. You can use the ansible-doc
command-line tool with what you have installed to view the reference documentation and the module index mentioned previously.
Chapter 8 covers only the basic features of Jinja2, the template engine that Ansible uses, primarily because your authors memorize only basic features when we use Jinja2 with Ansible. If you need to use more advanced Jinja2 features in templates, check out the official Jinja2 documentation.
Nor do we go into detail about some features of Ansible that are mainly useful when you are running it on an older version of Linux.
Finally, there are features of Ansible we don’t cover simply to keep the book a manageable length. We encourage you to check out the official documentation to find out more about these features.
Moving Forward
This introductory chapter covered the basic concepts of Ansible at a general level, including how it communicates with remote servers and how it differs from other configuration management tools. The next chapters discuss how to practice using Ansible.
1 For more on building and maintaining these types of distributed systems, check out Thomas A. Limoncelli, Strata R. Chalup, and Christina J. Hogan’s The Practice of Cloud System Administration, volumes 1 and 2 (Addison-Wesley), and Designing Data-Intensive Applications by Martin Kleppman (O’Reilly).
2 Yes, Azure supports Linux servers.
3 For example, see “Using Ansible at Scale to Manage a Public Cloud”, a slide presentation by Jesse Keating, formerly of Rackspace.
4 Ansible Runner documentation, last accessed June 2, 2022.
5 If you are interested in what Ansible’s original author thinks of the idea of convergence, see Michael DeHaan’s Ansible Project newsgroup post “Idempotence, Convergence, and Other Silly Fancy Words We Use Too Often”.
Get Ansible: Up and Running, 3rd Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.