Chapter 1 - Getting Started with Ansible
Ansible and Infrastructure Management
On snowflakes and shell scripts
Many developers and system administrators manage servers by logging into them via SSH, making changes, and logging off. Some of these changes would be documented, some would not. If an admin needed to make the same change to many servers (for example, changing one value in a config file), the admin would manually log into each server and repeatedly make this change.
If there were only one or two changes in the course of a server’s lifetime, and if the server were extremely simple (running only one process, with one configuration, and a very simple firewall), and if every change were thoroughly documented, this process wouldn’t be a problem.
But for almost every company in existence, servers are more complex—most run tens, sometimes hundreds of different applications or application containers. Most servers have complicated firewalls and dozens of tweaked configuration files. And even with change documentation, the manual process usually results in some servers or some steps being forgotten.
If the admins at these companies wanted to set up a new server exactly like one that is currently running, they would need to spend a good deal of time going through all of the installed packages, documenting configurations, versions, and settings; and they would spend a lot of unnecessary time manually reinstalling, updating, and tweaking everything to get the new server to run close to how the old server did.
Some admins may use shell scripts to try to reach some level of sanity, but I’ve yet to see a complex shell script that handles all edge cases correctly while synchronizing multiple servers’ configuration and deploying new code.
Configuration management
Lucky for you, there are tools to help you avoid having these snowflake servers—servers that are uniquely configured and impossible to recreate from scratch because they were hand-configured without documentation. Tools like CFEngine, Puppet and Chef became very popular in the mid-to-late 2000s.
But there’s a reason why many developers and sysadmins stick to shell scripting and command-line configuration: it’s simple and easy-to-use, and they’ve had years of experience using bash and command-line tools. Why throw all that out the window and learn a new configuration language and methodology?
Enter Ansible. Ansible was built (and continues to be improved) by developers and sysadmins who know the command line—and want to make a tool that helps them manage their servers exactly the same as they have in the past, but in a repeatable and centrally managed way. Ansible also has other tricks up its sleeve, making it a true Swiss Army knife for people involved in DevOps (not just the operations side).
One of Ansible’s greatest strengths is its ability to run regular shell commands verbatim, so you can take existing scripts and commands and work on converting them into idempotent playbooks as time allows. For someone (like me) who was comfortable with the command line, but never became proficient in more complicated tools like Puppet or Chef (which both required at least a slight understanding of Ruby and/or a custom language just to get started), Ansible was a breath of fresh air.
Ansible works by pushing changes out to all your servers (by default), and requires no extra software to be installed on your servers (thus no extra memory footprint, and no extra daemon to manage), unlike most other configuration management tools.
Installing Ansible
Ansible’s only real dependency is Python. Once Python is installed, the simplest way to get Ansible running is to use pip, a simple package manager for Python.
If you’re on a Mac, installing Ansible is a piece of cake:
- Check if
pipis installed (which pip). If not, install it:sudo easy_install pip - Install Ansible:
pip install ansible
You could also install Ansible via Homebrew with brew install ansible. Either way (pip or brew) is fine, but make sure you update Ansible using the same system with which it was installed!
If you’re running Windows, it will take a little extra work to set everything up. Typically, people run Ansible inside the Windows Subsystem for Linux. For detailed instructions setting up Ansible under the WSL, see Appendix A - Using Ansible on Windows workstations.
If you’re running Linux, chances are you already have Ansible’s dependencies installed, but we’ll cover the most common installation methods.
If you have python-pip and python-devel (python-dev on Debian/Ubuntu) installed, use pip to install Ansible (this assumes you also have the ‘Development Tools’ package installed, so you have gcc, make, etc. available):
$ pip install ansible
Using pip allows you to upgrade Ansible with pip install --upgrade ansible.
Fedora/Red Hat Enterprise Linux
The easiest way to install Ansible on an RPM-based OS is to use the official dnf package. If you’re running Red Hat Enterprise Linux (RHEL) or CentOS/Rocky/Alma Linux, you need to install EPEL’s RPM before you install Ansible (see the info section below for instructions):
$ dnf -y install ansible
Debian/Ubuntu
The easiest way to install Ansible on a Debian or Ubuntu system is to use the official apt package.
$ sudo apt-add-repository -y ppa:ansible/ansible
$ sudo apt-get update
$ sudo apt-get install -y ansible
Once Ansible is installed, make sure it’s working properly by entering ansible --version on the command line. You should see the currently-installed version information:
$ ansible --version
ansible [core 2.14.6]
...
python version = 3.10.11
jinja version = 3.1.2
libyaml = True
Creating a basic inventory file
Ansible uses an inventory file (basically, a list of servers) to communicate with your servers. Like a hosts file (at /etc/hosts) that matches IP addresses to domain names, an Ansible inventory file matches servers (IP addresses or domain names) to groups. Inventory files can do a lot more, but for now, we’ll just create a simple file with one server. Create a file named hosts.ini in a test project folder:
$ mkdir test-project
$ cd test-project
$ touch hosts.ini
Edit this hosts file with nano, vim, or whatever editor you’d like. Put the following into the file:
1 [example]
2 www.example.com
…where example is the group of servers you’re managing and www.example.com is the domain name (or IP address) of a server in that group. If you’re not using port 22 for SSH on this server, you will need to add it to the address, like www.example.com:2222, since Ansible defaults to port 22 and won’t get this value from your ssh config file.
Running your first Ad-Hoc Ansible command
Now that you’ve installed Ansible and created an inventory file, it’s time to run a command to see if everything works! Enter the following in the terminal (we’ll do something safe so it doesn’t make any changes on the server):
$ ansible -i hosts.ini example -m ping -u [username]
…where [username] is the user you use to log into the server. If everything worked, you should see a message that shows www.example.com | SUCCESS >>, then the result of your ping. If it didn’t work, run the command again with -vvvv on the end to see verbose output. Chances are you don’t have SSH keys configured properly—if you login with ssh username@www.example.com and that works, the above Ansible command should work, too.
Let’s run a more useful command:
$ ansible -i hosts.ini example -a "free -h" -u [username]
In this example, we quickly see memory usage (in a human-readable format) on all the servers (for now, just one) in the example group. Commands like this are helpful for quickly finding a server that has a value out of a normal range. I often use commands like free -h (to see memory statistics), df -h (to see disk usage statistics), and the like to make sure none of my servers is behaving erratically. While it’s good to track these details in an external tool like Nagios, Munin, or Cacti, it’s also nice to check these stats on all your servers with one simple command and one terminal window!
Summary
That’s it! You’ve just learned about configuration management and Ansible, installed it, told it about your server, and ran a couple commands on that server through Ansible. If you’re not impressed yet, that’s okay—you’ve only seen the tip of the iceberg.
_______________________________________
/ A doctor can bury his mistakes but an \
| architect can only advise his clients |
\ to plant vines. (Frank Lloyd Wright) /
---------------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||