Ansible Tutorial: A Helpful Guide, No Experience Required

Eric GoebelbeckerMon, 08/19/2019 - 08:49
Subject

Ansible is an automation tool for cloud provisioning, configuration management, application deployment, and other IT operations. You can use it for simple tasks, like deploying and configuring software releases, or for managing complicated multi-tier environments. Ansible doesn’t need agents and works with existing security infrastructure, so it’s easy to integrate into an existing network.

Rather than defining your systems one-at-time like other orchestration tools, Ansible models your IT infrastructure by describing how your systems interrelate. It also uses a simple YAML grammar to describe your automation jobs.

In this tutorial, you’re going to install Ansible on a single node and use it to deploy a software package to another. Don’t worry if you only have access to one computer — I’ll show you how to fake it and manage the same node you’re running on.

Let’s get started!

Installing Ansible

Control Nodes and Managed Nodes

Installing Ansible means adding it to the control node, the system you’ll use to issue commands, and configuring your managed nodes so that Ansible can communicate with them. We’ll start with the control node.

Install Ansible Control Nodes With OS Packages

Ansible is written in Python, so you have a few choices for how to install it. If your control node is running Red Hat Enterprise Linux (TM), CentOS, Fedora, Debian, or Ubuntu, you can install the latest release version using the system’s OS package manager.

So for Ubuntu, you would add the PPA, update apt, and install the package.

$ sudo apt update

$ sudo apt install software-properties-common

$ sudo apt-add-repository --yes --update ppa:ansible/ansible

$ sudo apt install ansible

On Red-hot and CentOS, you can use yum.

$ sudo yum install ansible

The Ansible documentation has detailed instructions here.

Install Ansible Control Nodes With Python

You can also install Ansible’s Python package via pip. Ansible works with Python 2.7 or 3.x, so it works with the Python version that comes installed on Linux and MacOs. Support for Python 2.7 is deprecated though, so if you’re setting up Ansible on a production system, you should use Python 3.

If you don’t already have pip installed, download and run the install script.

$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py

$ python get-pip.py --user

I recommend using a virtual environment for Ansible. So install virtualenv if you haven’t already.

$ sudo pip install virtualenv

Next, create a virtual environment for Ansible.

python -m virtualenv ansible   

Then source it and install Ansible.

$ source ansible/bin/activate

$ pip install ansible

Now you have Ansible installed in a virtual environment in your home directory. To use it, run it from inside the environment.

 $ ansible/bin/ansible

 Usage: ansible <host-pattern> [options]

 

 Define and run a single task 'playbook' against a set of hosts

 

Options:

(trimmed for space)

You can add the Ansible virtual environment’s bin directory to your path to save on some typing.

$ PATH=$PATH:~/ansible/bin

If you’re feeling adventurous, you can run the latest version of Ansible from source too. The directions are here.

Configure Ansible Managed Nodes

Now that you’ve set up your control node, it’s time to add a managed node. Ansible uses ssh (and sftp, which runs over ssh) to communicate with managed nodes. So adding one means setting up ssh keys so the control node can connect to the managed node, run commands, and transfer software.

Digital Ocean has an excellent tutorial for adding keys here. I’ll include a brief version of the process below.

If you want to use your control node as your managed node, you’ll still want to generate a key and install it on your control node.

First, check for keys on your managed node. List the .ssh directory in your Ansible user’s home directory.

$ ls -al .ssh

drwx------.  2 ericg ericg 4096 Jul 12 13:36 .

drwx------. 24 ericg ericg 4096 Jul 13 10:13 ..

-rw-------.  1 ericg ericg 1831 Jul 12 13:15 id_rsa

-rw-r--r--.  1 ericg ericg  408 Jul 12 13:15 id_rsa.pub

-rw-r--r--.  1 ericg ericg  404 Jul 12 13:33 known_hosts

If you have an id_rsa.pub file, you have a key. A key looks similar to this:

$ cat .ssh/id_rsa.pub

ssh-rsa ABSAB3NzaC1yc2EAAAADAQABAAABAQDDDswdvVgIiCbQEYLu66peXQ9AxFQFetIaz0DrK1V2QuXSyikdlpv8vik3Wt5RYQC3i6NXcGRQpojsL7vgxQMtceoELMVqLMqbVZ8xsiMe4D590zCbto6IhFetyK/AhHIy0l/qNGusEpTrUoZRWZfEOYAakecX14Bncv1XFSi5FZ8Vhn7SJI+qHCqp38AG412T268CoPvvhw8DNqsVKzYjiGpJXOVWi6cQzeazRfh7+iJHomp1QBJ++dE13jqxEZgf9ZJFOy7VZRpoGau2iLn2PLOkXp+kdYGrEQ03WJpUx9fKmMAotzFHfGHCKV291kto0bNthJtQyqzL ericg@ix

If you don’t have a key, use ssh-keygen to create one.

$ ssh-keygen -t rsa

Keygen will offer a few prompts. Accept the default location for the new key and don’t add a passphrase for this tutorial. This command creates id_rsa and id_rsa.pub files in your .ssh directory.

Here’s what the output will look like:

Generating public/private rsa key pair.

Enter file in which to save the key (/home/ericg/.ssh/id_rsa):

Enter passphrase (empty for no passphrase):

Enter same passphrase again:

Your identification has been saved in /home/ericg/.ssh/id_rsa.

Your public key has been saved in /home/ericg/.ssh/id_rsa.pub.

The key fingerprint is:

4a:dd:0a:c6:25:4c:3f:ed:24:32:8c:77:44:4d:93:67 ericg@a

The key's randomart image is:

+--[ RSA 2048]----+

|          .oo.   |

|         .  o.E  |

|        + . EE   |

|     . = =       |

|      = S = .    |

|     o +===+     |

|      . o + o .  |

|           . o   |

|                 |

+-----------------+

Now, copy the new key to the managed node with ssh.

$ cat ~/.ssh/id_rsa.pub | ssh ericg@192.9.100.12 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >>  ~/.ssh/authorized_keys"

Note the chmod 700 portion of this command. Ssh won’t recognize a directory that doesn’t have the correct file permissions.

If you’re going to use the same node as both a control and managed node, you can copy the key to authorized_keys without the ssh command.

$ cat ~/.ssh/id_rsa.pub >>  ~/.ssh/authorized_keys

$ chmod 700 ~/.ssh/authorized_keys

Test the key by shelling to the managed host. You should be able to connect without a password.

$ ssh ericg@192.9.100.12 (or ssh localhost)

Last login: Sat Jul 13 15:32:55 2019 from 108.5.246.140

$

Ansible Configuration and Inventory

Now that you’ve set up a managed node, it’s time to add it to your inventory. We’re going to use a local configuration so that you can quickly move your scripts and system information to a different control node.

First, create an ansible_config directory.

$ mkdir ~/ansible_config

Next, create a hosts file in the new folder to hold your inventory.

$ touch ~/ansible_config/hosts

Then add your managed node to the file with your text editor of choice. Mine looks like this:

$ cat ~/ansible_config/hosts

192.9.100.12

Your inventory is the list of hosts you wish to control with Ansible. You can list hosts by IP address or hostname. So if you’re managing your control node, you can list localhost or 127.0.0.1. You can use a hostname for your remote managed node if you have one, too.

Now, create a configuration file in your home directory.

$ touch ~/.ansible.cfg

Edit the file and add a line for your inventory.

[defaults]

inventory  = /home/ericg/ansible_config/hosts

You’re ready to test your installation.

Ansible Ping

So, start with an Ansible ping.

$ ansible all -m ping

 

127.0.0.1 | SUCCESS => {

    "ansible_facts": {

        "discovered_interpreter_python": "/usr/bin/python"

    },

    "changed": false,

    "ping": "pong"

}

Ping verifies that we can connect to a host and execute a remote command. It also gives us basic information. In this case, localhost has a Python interpreter installed in /usr/bin.

Targeting Ansible Hosts

Let’s modify the ping command. You used all to indicate that you wanted to ping all hosts. Pass in the hostname or address of your managed node instead.

$ ansible 127.0.0.1 -m ping

127.0.0.1 | SUCCESS => {

    "ansible_facts": {

        "discovered_interpreter_python": "/usr/bin/python"

    },

    "changed": false,

    "ping": "pong"

}

You’ll see the same response.

Run Arbitrary Commands With Ansible

Ping is a module, so you used the -m command line option to invoke it. You’re not limited to modules, though. You can run an arbitrary or ad-hoc command with *-a.

$ ansible 127.0.0.1 -a "ls -a"

35.174.111.167 | CHANGED | rc=0 >>

total 16

drwx------. 4 ericg ericg 111 Jul 12 17:51 .

drwxr-xr-x. 4 root      root       39 Jul 12 17:35 ..

drwx------. 3 ericg ericg  17 Jul 12 17:51 .ansible

-rw-------. 1 ericg ericg 472 Jul 13 16:21 .bash_history

-rw-r--r--. 1 ericg ericg  18 Jan 14 06:10 .bash_logout

-rw-r--r--. 1 ericg ericg 141 Jan 14 06:10 .bash_profile

-rw-r--r--. 1 ericg ericg 312 Jan 14 06:10 .bashrc

drwx------. 2 ericg ericg  48 Jul 13 16:19 .ssh

Install Software With Playbooks

Let’s finish up by demonstrating an Ansible Playbook. Playbooks use Ansible’s YAML language to describe configuration, policies, and deployments. Here’s a playbook that installs and starts the Apache web server on Fedora Linux. Save this file in ~/ansible_config/httpd.yml

---

- name: This sets up an httpd webserver

  hosts: 127.0.0.1

  become: yes

  become_method: sudo

  tasks:

  - name: Install apache packages

    dnf:

      name: httpd

      state: present

  - name: ensure httpd is running

    service:

      name: httpd

      state: started

Let’s break the playbook down.

- name: This sets up an httpd webserver

This is a note that describes what the playbook performs. When you’re managing an extensive set of nodes, having a name for each playbook is invaluable.

  hosts: 127.0.0.1

  become: yes

  become_method: sudo

This section designates which hosts the playbook will be run on. It’s also used to specify the credentials the tasks will use. Become indicates that Ansible will become another user. Become_method specifies how. Since we need to run Fedora’s package manager, this playbook will use sudo.

Finally, we have two tasks.

  tasks:

  - name: Install apache packages

    dnf:

      name: httpd

      state: present

  - name: ensure httpd is running

    service:

      name: httpd

      state: started

The first uses dnf, the Fedora package manager, to install the current version of Apache. The second uses Fedora’s service command to ensure that Apache is started.

So, let’s run this playbook. For this, we need the ansible-playbook command. You’ll pass it two command line options. The first argument is the location of the playbook file. The second is –extra-vars with the sudo password.

$ ansible-playbook ansible_config/httpd.yml --extra-vars "ansible_become_pass=YourPassword"

Using /home/ericg/.ansible.cfg as config file

 

PLAY [This sets up an httpd webserver] *******************************************************************************************************************

 

TASK [Gathering Facts] ***********************************************************************************************************************************

ok: [127.0.0.1]

 

TASK [Install apache packages] ***************************************************************************************************************************

changed: [127.0.0.1] => {"changed": true, "msg": "", "rc": 0, "results": ["Installed: httpd", "Installed: apr-util-openssl-1.6.1-8.fc29.x86_64", "Installed: mod_http2-1.15.1-1.fc29.x86_64", "Installed: fedora-logos-httpd-28.0.3-2.fc29.noarch", "Installed: httpd-2.4.39-3.fc29.x86_64", "Installed: httpd-filesystem-2.4.39-3.fc29.noarch", "Installed: httpd-tools-2.4.39-3.fc29.x86_64", "Installed: apr-1.6.5-1.fc29.x86_64", "Installed: apr-util-1.6.1-8.fc29.x86_64", "Installed: apr-util-bdb-1.6.1-8.fc29.x86_64"]}

 

TASK [ensure httpd is running] ***************************************************************************************************************************

changed: [127.0.0.1] => {"changed": true, "name": "httpd", "state": "started", "status": (trimmed for space) "0"}}

 

PLAY RECAP ***********************************************************************************************************************************************

127.0.0.1                  : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

Ansible prints information, in the form of JSON records about the changes made to the host. Dnf installed httpd, along with several packages that it relies on. Then it started the web server.

You installed a web server and started it with a single Ansible command.

System Management With Ansible

In this tutorial, you configured both control and managed nodes for Ansible. Then you used the tools to run remote commands, including a software deployment. This is only the beginning of what you can do with this powerful systems management utility. Learn more about how to use the world’s simplest IT automation platform with an online boot camp from ASPE.