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;
Getting started with Ansible
Ansible has three main components, namely;
- Control node: This is our
nodecontroller.
- Managed node: This is
target01
andtarget02
- 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;
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;
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;
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.