Ansible tutorial - part 1

Ansible tutorial – part 1

What you will learn in part 1 of this tutorial? What is Ansible? How to install Ansible on Windows/Linux/MacOS? How to prepare test environment for Ansible? Intro to Inventory files. First connection to the server.

A short word about Ansible tutorial

This is multipart series about Ansible, great tool for provisioning and configuration management. You will learn how to create useful roles and use Ansible in efficient way. You will also pick up some good practices:)

If you like tl;dr take a look at shorter veresion of this tutorial on GitHub: https://github.com/blacksaildivision/ansible-tutorial
There are also some examples!

Part 1: Intro to Ansible and Inventory files
Part 2: Playbooks and tasks
Part 3: Templates and handlers 
Part 4: Variables

 

First thing first - what is Ansible?

Ansible is a simple yet powerful tool for configuration management and orchestration of your infrastructure. It speeds up installing software, configuring servers and most important - it reduces manual steps you need to make, to setup your server(s). It is also great alternative to Puppet and Chef. Both are similar tools to Ansible, but in my opinion Ansible is much easier to learn and master.

How do WE use Ansible (possible use cases)?

We have lot of servers that we need to take care of. At the beginning we were just logging into our servers via SSH and fire all commands in terminal. It was painful job, so we decided that we need to automate things. We checked Puppet, Chef and Ansible and we decided to stick with the last one. It was really good choice. Now we use Ansible for:

  • Installing our entire LAMP stack on new server
  • Configuration of most of the software on our servers
  • Testing if servers are configured properly
  • Deploying our applications
  • Keeping Infrastructure As Code (IAC) - all infrastructure is in single Git repository

Most of these tasks are done with single command. For instance we can update nginx on all servers with bumping the version in our variable file and execute one command in terminal. It will be updated on all servers at once.  No more logging it via SSH and executing commands one by one:)

 

What do I need to know about Ansible?

Ansible is using files for configuration and provisioning. By using Ansible you can go with IAC - Infrastructure As Code. It means that you can keep you entire infrastructure in GIT repository. You can track changes and use all goodies that comes with source version control.

Ansible is based on YAML files. If you don't know it, you will learn it in minutes. Really easy and simple.

For templates it uses Jinja2 engine. Powerful and easy to learn.

It does not require additional software to be installed on the server. It uses old-school ssh protocol for connecting and configuring the server. One requirements is to have Python installed on the server, but these days, all common Linux distributions have it out of the box.

Let's get started - how to install Ansible?

No matter what is you operating system, when you will be installing Ansible, make sure that you will install version 2.0  or higher. It has lot more features than 1.x versions. It is stable and commonly used these days.

If you are using OS X or Linux, it is not a big deal for you. Here are some tutorials from Ansible documentation - how to install Ansible on OS X or Linux? The easiest way is to use APT, Yum for Linux and Pip or Homebrew.  Please make sure that you are installing Ansible in version 2.0 or higher:)

If you are using Windows, it's a bit more hassle, unless you already have the Windows with Bash terminal! If you do, simply use APT for installing Ansible. However if you don't have it yet, you need to install more things. On our Windows machines we use Babun (much better version of Cygwin, if you didn't hear about it, check it out right now!). To install Ansible with Babun, please use this tutorial.

 

Prepare test environment

You will need a server or virtual machine where you can test Ansible. If you are just starting with I highly recommend to use empty and fresh server. You don't want to mess up production server while learning it!

If you have some clean server on DigitalOcean for example, you can use it. However easier (and free) way is to install Vagrant and use dummy box. If something will go wrong, you can always remove everything and start fresh. For the purpose of this tutorial, we will use Vagrant.

Start with a new directory for example: vagrant_ansible_tutorial . In this directory create file named Vagrantfile and paste following content into that file:

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
  config.vm.box = "geerlingguy/centos7"
  config.vm.network "forwarded_port", guest: 80, host: 8080
  config.vm.network "private_network", ip: "192.168.60.70"
  config.vm.provider "virtualbox" do |vb|
     vb.memory = "2048"
  end
end

You can adjust some parameters if you like. Save the changes in file and execute vagrant up in your terminal. You must be in vagrant_ansible_tutorial directory. Wait until your box will be up and running.

Inventory file

First thing that we need to do before we can actually start using Ansible is to create an Inventory file. Inventory files are the way to specify connection to the servers for Ansible. You can treat is as an alternative to SSH command. So instead of executing:

ssh -i my_private_key_file_path username@server_ip_or_domain.com

you need to add following line to inventory file:

server_ip_or_domain.com ansible_user=username ansible_private_key_file=my_private_key_file_path

Let's create a file in our directory project and name it hosts .  Paste following code into that file:

[ansible_tutorial]
192.168.60.70 ansible_user=vagrant ansible_private_key_file="./.vagrant/machines/default/virtualbox/private_key"

Let's start from 2nd line. We specified IP address to our server. This is the same IP as in Vagrantfile . Instead of using the IP you can use domain address like blacksaildivision.com.

Next is the user that we will use to connect to the server. Vagrant default user is vagrant . Last thing is private key that we are using for accessing the server. After starting the box, Vagrant will create new key in the .vagrant directory.

Alternatively you can specify the password instead of SSH key. But if you are using passwords instead of keys for accessing your server, you should change it ASAP, because you are doing it wrong. Passwords are easy to hack. Trust me, at the beginning our server was hacked twice, even though we had pretty strong password. We didn't know about such thing as SSH back then:) If you will use password, Ansible will also give you a warning.

If you need to alter the port or add additional arguments for your connection, check Ansible documentation here.

Groups in Inventory files

In first line we have [ansible_tutorial]  and it's name of the group of the servers.  You can omit it, but the good practice is to specify the group for server(s). Take a look on following file:

[web]
147.120.24.3 ansible_user=developer ansible_private_key_file="~/.ssh/web"
147.120.24.4 ansible_user=developer ansible_private_key_file="~/.ssh/web"
147.120.24.5 ansible_user=developer ansible_private_key_file="~/.ssh/web"
 	 	
[database]
11.60.215.157 ansible_user=db ansible_private_key_file="~/.ssh/db"
11.60.215.158 ansible_user=db ansible_private_key_file="~/.ssh/db"

There are two groups of the servers - web and database. Now we can execute different commands on each group. For instance on database group we can install MongoDB related software and on servers that belongs to web group we can install nginx+php.

It's good practice to specify a group, even if you have single server. It's more descriptive way than using IP or host name.

Testing connection to server

Last thing in this part is to test connection between Ansible and the server. Execute following command:

ansible ansible_tutorial -m ping -i hosts

If you didn't connect to this server via ssh before, you will get message about authentication for new host. Just type yes.

You should get following input:

192.168.60.70 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

What we just did is we checked if Ansible is able to connect to the server. If you get SUCCESS message, you are ready to start provisioning with Ansible!

Explaining the command you just executed. There are 3 parameters. First one is the group from inventory file. You can also specify particular host or IP from inventory file or you can use all  to test all servers within given inventory file:

ansible all -m ping -i hosts

Second thing is module name. We need to use ping module to check the connection. Last thing is inventory file, which in our case is created hosts  file.

If you have the problems with getting SUCCESS message, you need to debug the connection. Use -vvvv to get debug output. Usually you are able to figure out what is wrong with the connection from debug output:

ansible all -m ping -i hosts -vvvv

In most cases it is wrong private key path or some typos.

  • Sachidananda Sahu

    Hello,
    I tried this by setting vagrantfile and hosts file in the same directory and while doing vagrant up, i am getting following errors.

    I am not sure about it is problem with private/public key file or something else.What i can guess is is there any problem with the box image provided ?

    ==> default: Checking if box ‘geerlingguy/centos7’ is up to date…
    ==> default: Clearing any previously set forwarded ports…
    ==> default: Clearing any previously set network interfaces…
    ==> default: Preparing network interfaces based on configuration…
    default: Adapter 1: nat
    default: Adapter 2: hostonly
    ==> default: Forwarding ports…
    default: 80 (guest) => 8080 (host) (adapter 1)
    default: 22 (guest) => 2222 (host) (adapter 1)
    ==> default: Running ‘pre-boot’ VM customizations…
    ==> default: Booting VM…
    ==> default: Waiting for machine to boot. This may take a few minutes…
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key

    After this it should apply privatekey/public key and proceed but it is trying for more time and after that it is giving this log as

    Timed out while waiting for the machine to boot. This means that
    Vagrant was unable to communicate with the guest machine within
    the configured (“config.vm.boot_timeout” value) time period.

    If you look above, you should be able to see the error(s) that
    Vagrant had when attempting to connect to the machine. These errors
    are usually good hints as to what may be wrong.

    If you’re using a custom box, make sure that networking is properly
    working and you’re able to connect to the machine. It is a common
    problem that networking isn’t setup properly in these boxes.
    Verify that authentication configurations are also setup properly,
    as well.

    If the box appears to be booting properly, you may want to increase
    the timeout (“config.vm.boot_timeout”) value.