Ansible Tutorial: Automate and Configure Remote Linux Servers

Ansible Tutorial: Automate and Configure Remote Linux Servers

What if you have to remotely automate Linux servers, maybe about 200? What options do you have? You could decide to use the following;

  • Shell
  • Python

If you have sufficient experience in programming, you can write a Shell script or a Python script to do that for you; what if you don't know Shell or Python? You'd have to learn either one. In most cases, you may not want to go through such stress. In this tutorial, I will be explaining the process of automating using Ansible as you'd do to a beginner, but there are some requirements to follow;

  • Linux
  • Vagrant (The first article in this series)
  • YAML (You can learn at Ansible YAML)

That's just about all, let's dive right in 🎶

We have set up three Linux servers in Virtualbox using Vagrant; they all use the Ubuntu image.

  • Nodecontroller: This is the controller server where we'll Install Ansible.
  • target01: As its name implies, this is the target server, we'd be automating this server and target02.

Let's ssh into the nodecontroller and Install Ansible, we'd be following the guide at Ansible Installation Guide

CD into where you have your Vagrantfile, run vagrant status to verify the VMs we installed in the first article then;

vagrant up && vagrant ssh nodecontroller

It starts up the VMs AND ssh into the nodecontroller, now to install Ansible;

Run

sudo apt install ansible

If it can't find the package, go ahead and follow the instruction below, otherwise skip the adding the source list part;

echo deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main >> /etc/apt/sources.list

It adds the ansible source to the sources list for Ubuntu if you see a permission denied error even with using sudo;

Run

su

Then run the same command and exit when done, next;

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367 
sudo apt update
sudo apt install ansible

This should take a few minutes, after it's done, to verify it has been installed, run;

ansible --version

You should see something like this, and then you're good to go; Ansible

Getting started with Ansible

Ansible has three main components, namely;

  • Control node: This is our nodecontroller.
  • Managed node: This is target01 and target02
  • Inventory: This is the list of our nodes organized on the control node, as it sounds, it stores the list of nodes we want to automate.

Let's create an Inventory

Get the IP addresses of target01 and target02 by vagrant ssh target01 into them from your host(PC), then run ifconfig, note them down and exit, and now SSH into your nodecontroller.

cat > inventory.txt

Then paste;

target01 ansible_host=192.168.56.4 ansible_ssh_pass=vagrant
target02 ansible_host=192.168.56.5 ansible_ssh_pass=vagrant

Press Enter, then Ctrl C to exit, then run cat inventory.txt to verify the input.

We added the target01 and target02 to the inventory file, the target01 and target02 are the name of the server, ansible_host is a variable, and we stored each server's IP address in it, ansible_ssh_pass stores the SSH password for each server, this shouldn't be used in production apps as it exposes your password.

Let's ping target01

Run

ansible target01 -m ping -i inventory.txt

You should see this output if it was successful;

Ansible ping

If you can't, verify the IP address you used for target01, you can try pinging target02 too in the same way.

Now we've only tried connecting to a server only one at a time, using ansible target01 -m ping -i inventory.txt, we want to be able to run commands on multiple servers with a single command, let's edit our inventory file.

You can use nano or VIM to edit the inventory file, if you'd like to learn about the VIM editor, check out my article, VIM for beginners, or use nano, by running nano inventory.txt and edit the file to;

[targets]
target01 ansible_host=192.168.56.4 ansible_ssh_pass=vagrant
target02 ansible_host=192.168.56.5 ansible_ssh_pass=vagrant

Then Ctrl X to Save and Exit.

Now run;

ansible targets -m ping -i inventory.txt

You should see;

Ansible targets

We got two outputs, this is from each target (target01 and target02).

Quick explanation

In the inventory.txt, we created a group called targets and added the target01 and target02 configuration; that's why we can run ansible targets -m ping -i inventory.txt and it runs on all servers under the targets group.

But there's a better way to automate tasks on Servers!

Introduction to Ansible Playbooks

Based on docs.ansible.com. Ansible Playbooks offer a repeatable, reusable, simple configuration management and multi-machine deployment system that is well suited to deploying complex applications. If you need to execute a task with Ansible more than once, write a playbook and put it under source control. Then you can use the playbook to push out new configurations or confirm the configuration of remote systems.

Let's create an Ansible Playbook

nano Ansible-play.yml

Paste this;

- name: Play one
  hosts: targets
  tasks:
    - name: "Execute IP Check"
      command: ifconfig
      register: command_output
    - debug : var=command_output

Then run the playbook and attach the inventory file to it;

ansible-playbook exampleplaybook.yml -i inventory.txt

Explanation

The whole YAML file is the playbook, under it, we have each play (activities/tasks that run on the server); we named it Play one, also we used targets as the hosts - This is our group from the inventory file, so we targetted all servers under the targets group. Then we have each task that will run in the server under the tasks list.

The first task explanation

- name: "Execute IP Check"
  command: ifconfig
  register: command_output

We gave it a name and used the command module to run the ifconfig command, then registered the output in a variable named command_output.

The second task explanation

- debug : var=command_output

We then used the debug module to redirect the command_output to the stdout of the host (your PC).

So, in summary, we ran all the ifconfig commands on all the servers under the targets group and got their outputs.

BUT there's a better way to copy files from a source(your PC) to a destination(nodecontroller) through SSH. SCP is the solution.. 😉 I was hoping you wouldn't ask me the whole meaning; I forgot, lol.

How to use SCP

Secure Copy(SCP) is used to securely transfer files through the SSH protocol from one computer to another.

You want to be able to edit your Ansible playbook on your PC(host), so you can use a text editor like VSCode; when you're done editing it, you can transfer it to the nodecontroller VM with a single command instead of using that ugly nano or copying from your host to the VM, this is a better alternative and faster and we get to learn something more.

Install SCP Plugin in Vagrant

vagrant plugin install vagrant-scp

That's all; now we're ready to use SCP.

Format of the SCP command

vagrant scp <source> <destination>

In your host(PC), change the directory to where you have your ansible playbook, then run this command;

Using it;

vagrant scp absolute_uri_to_playbook/playbook.plays.yaml nodecontroller:/home/vagrant

This copies the playbook on your host to the nodecontroller using just a single command, so when you make new changes to the playbook on your host, rerun that same command; SCP is not only on Vagrant; you can also use it without Vagrant.

What are Ansible Modules?

Based on docs.ansible.com, Modules (also referred to as “task plugins” or “library plugins”) are discrete units of code that can be used from the command line or in a playbook task. Ansible executes each module, usually on the remote managed node, and collects return values.

We've used two modules so far; we used the command and the debug module, modules is the building block you build upon on playbooks, want to install apache on 250+ Ubuntu Linux server? Use the apt module for Ansible.

Install PHP/MYSQL and Apache on all VMs using Ansible Playbook

It's alright if you don't know PHP, follow along. Let's assume you have to configure the LAMP stack for about 200+ systems running Linux, you can do that using Ansible with a playbook; it takes just a single command.

Create a playbook in your nodecontroller and name it playbook.plays.yaml, you can name it anything you like.

In playbook.plays.yaml

- name: Play one
  hosts: targets
  tasks:
    - apt_repository:
        repo: ppa:ondrej/php
        state: present
      become: yes

    - name: Install Apache2
      apt:
        name: apache2
        state: present

      become: yes
    - name: Install MySQL Server
      apt:
        name: mysql-server
        state: present
      become: yes
    - name: Install PHP and others
      become: yes
      apt:
        pkg:
          - php5
          - libapache2-mod-php5
          - php5-mysql

NOTE: Don't use PHP5 on a production app; I only used it for illustration, I was having issues installing PHP7, so I had to go with the quick one.

Quick explanation

We used the targets group as the hosts, which contains target01 and target02. The first task we added adds the ppa:ondrej/php repository using the apt_repository module, we'd have used sudo add-apt-repository ppa:ondrej/php5 to do this on a terminal, we also used a field become: yes, this is used to elevate privileges, that is using sudo.

Then we used the apt module to install mysql-server, then used a field state: present, this means mysql-server should be present, if it was already installed, it does nothing, and if it wasn't installed, it installs it, so you can run this as many times as you want.

We did same for apache2, in the last module, we installed a list of packages, php5, libapache2-mod-php5, php5-mysql.

Now you can run it.

ansible-playbook playbook.plays.yaml -i inventory.txt

If it was successful, you should see something like;

Ansible vagrant

This means you have installed PHP and MySQL on target01 and target02 without actually interacting with either of them, now imagine it was about 100 virtual machines.

There are more to working with Ansible to this, also our PHP and MySQL setup isn't done yet, I just went through the basics in this article, maybe, just maybe in the future, I might create a complete tutorial to do that.

This brings us to the end of this long article, I hope you enjoyed it, if you did, consider sharing and/or adding a Reaction, if you had any issues, you can also add a comment here, I would try my best to help.

Thanks for reading.