Ansible 101 Tutorial for CentOS

I am currently working with a customer who is interested in using ansible as their common tool for server and storage automation. They would like to use Ansible to automate Linux, Windows, traditional controller-based storage, and software-defined storage. Given this, I figured it was about time I got my hands on Ansible to understand, first hand, the difficulty this standardization might pose.

My three tries at getting the community version of Ansible working on my laptop remind me of the "curtains" sketch in Monty Python and the Holy Grail: 

"Everyone said I was daft to build a castle on a swamp, but I built it all the same, just to show them. It sank into the swamp. So I built a second one. And that one sank into the swamp. So I built a third. That burned down, fell over, and then sank into the swamp. But the fourth one stayed up."

Needless to say, I learned a bit along the way until I finally had an error-free process to getting an Ansible playbook to run. I thought I could save others some frustration by laying out the steps that I found to work.



A Few Items Learned Through Trial and Error

  • If you like the vi editor, as I do, use vim instead. YAML does not seem to like vi. Create a YAML file in vi and you will get syntax errors. Create the same YAML file in vim and you will have no syntax errors. This really should not be the case, but seems to be.
  • I have had more success with CentOS than Ubuntu. ssh PKI worked with Ansible in CentOS without a hitch. In Ubuntu, I had to prompt the user for the password on every Ansible run. Could be operator error, but since most of my customers use CentOS/Red Hat and not Ubuntu, I am OK with this.
  • I was not successful in trying to control Windows through Ansible. Ansible uses Powershell rather than ssh for Windows hosts and remote execution for Powershell needs to be set up. Setting up Powershell remote execution is not a simple task. I may try again another time.
Now, on to the Ansible setup.

Step 1: Install a Few Copies of CentOS

  • Since everything I was going to do was going to be from the command line, I installed the CentOS Minimal ISO from the CentOS download page.
  • I installed two copies of CentOS in VMware Parallels on my Mac as that was convenient for me. Feel free to use whatever works for you. Bare metal, VMware Workstation, Parallels, VirtualBox, ESXi, Hyper-V, AWS, Azure.
  • Once my two copies of CentOS were installed, I opened up side by side root ssh CentOS sessions on my Mac. This gave me taller windows to work with than the Minimal ISO console.
  • If you want to use vim, like I did, you will need to install vim on each machine using "yum install vim". The vim package is not included in the CentOS Minimal ISO.

Step 2: Set Up Password-less ssh Login

  • I used this guide. Kudos to the author.
  • Before jumping into the ssh tutorial, I added the two CentOS machines to /etc/hosts on each machine so that I could refer to them by alias. ifconfig has been deprecated, so you now use the "ip address" command to find your ip address in CentOS.
  • I also added these lines to the .bash_profile on each machine so that I could keep track of which machine I was logged into. This example is from my first machine:
    • PS1="CentOS1:\w "
    • export PS1
  • To set up password-less ssh login, run each of these commands from the home directory of root on your Ansible control machine (centos1 in my case):
    • ssh-keygen -t rsa (I hit enter when asked for a passphrase)
    • ssh root@centos2 mkdir -p .ssh (set up the .ssh directory on remote machine)
    • cat .ssh/id_rsa.pub | ssh root@centos2 'cat >> .ssh/authorized_keys' (copy public key to remote machine)
    • ssh root@centos2 "chmod 700 .ssh; chmod 640 .ssh/authorized_keys" (fix permissions on remote machine)
    • ssh root@centos2 (This will test password-less ssh login)

Step 3: Set Up Ansible


  • I used this guide. Again, my thanks to the author.
  • Run each of these commands from the home directory of root on your Ansible control machine (centos1 in my case): 
    • yum install epel-release (repository that houses Ansible)
    • yum install ansible (Ansible)
    • vim /etc/ansible/hosts (Substitute your IP addresses)
      • [servers]
      • centos1 ansible_ssh_host=192.168.1.243 ansible_connection=local
      • centos2 ansible_ssh_host=192.168.1.201
    • mkdir /etc/ansible/group_vars
    • vim /etc/ansible/group_vars/servers (sets ansible variable for the "servers" group of hosts)
      • ---
      • ansible_ssh_user: root (change to the user Ansible should connect as)

Step 3: Run a Simple Ansible Ping Test


  • Ping is a built-in Ansible module and can be used to test connectivity and Ansible setup. Run this command from the home directory of root on your Ansible control machine:
    • ansible -m ping all (All runs the command against all sections in /etc/ansible/hosts)
      • centos1 | SUCCESS => {
      •     "changed": false, 
      •     "ping": "pong"
      • }
      • centos2 | SUCCESS => {
      •     "changed": false, 
      •     "ping": "pong"
      • }

Step 4: Run an Ansible Playbook


  • An Ansible playbook is a group of tasks. These tasks can query, create, change destinations based on findings. This post was written right around the time of the Intel Meltdown & Spectre speculative execution vulnerabilities. Fixes for these vulnerabilities are delivered as firmware and OS updates including kernel updates. I thought an Ansible playbook that checked for CentOS kernel version would be a useful learning exercise. I came up with two similar playbooks using different Ansible modules - ansible_kernel and yum.
  • ansible_kernel Module Example 
    • Use vim, not vi, to create kernel_version.yml with these lines:
      • ---
      • - hosts: servers
      •   tasks:
      •   - debug: msg={{ ansible_kernel }}
    • Then test the playbook with the "ansible-playbook kernel_version.yml" command. Your output should look something like this:
      • PLAY [servers] *****************************************************************

      • TASK [Gathering Facts] *********************************************************
      • ok: [centos1]
      • ok: [centos2]

      • TASK [debug] *******************************************************************
      • ok: [centos1] => {
      •     "msg": "3.10.0-693.el7.x86_64"
      • }
      • ok: [centos2] => {
      •     "msg": "3.10.0-693.el7.x86_64"
      • }

      • PLAY RECAP *********************************************************************
      • centos1                    : ok=2    changed=0    unreachable=0    failed=0   
      • centos2                    : ok=2    changed=0    unreachable=0    failed=0   
  • Yum Module Example 
    • Use vim, not vi, to create package_version.yml with these lines:
        • ---
          • - hosts: servers
            •   tasks:
              •        - name: yum_command 
                •          yum:
                  •            list=installed
                    •          register: yum_packages
                      •        - debug: var=item
                        •          with_items: "{{yum_packages|json_query(jsonquery)}}"
                          •          vars:
                            •                 jsonquery: "results[?name=='kernel'].envra"
                          • Then test the playbook with the "ansible-playbook package_version.yml" command. Your output should look something like this:
                              • PLAY [servers] *****************************************************************

                                  • TASK [Gathering Facts] *********************************************************
                                    • ok: [centos1]
                                      • ok: [centos2]

                                          • TASK [yum_command] *************************************************************
                                            • ok: [centos1]
                                              • ok: [centos2]

                                                  • TASK [debug] *******************************************************************
                                                    • ok: [centos1] => (item=0:kernel-3.10.0-693.el7.x86_64) => {
                                                      •     "changed": false, 
                                                        •     "item": "0:kernel-3.10.0-693.el7.x86_64"
                                                          • }
                                                            • ok: [centos2] => (item=0:kernel-3.10.0-693.el7.x86_64) => {
                                                              •     "changed": false, 
                                                                •     "item": "0:kernel-3.10.0-693.el7.x86_64"
                                                                  • }

                                                                      • PLAY RECAP *********************************************************************
                                                                        • centos1                    : ok=3    changed=0    unreachable=0    failed=0   
                                                                          • centos2                    : ok=3    changed=0    unreachable=0    failed=0  

                                                                      Summary


                                                                      The purpose of this blog was to help others get a base Ansible system up and running including the required password-less ssh. There are many helpful web pages out there that explain the many Ansible modules available and how to use them in playbooks. This page on ansible.com is a good place to start.

                                                                      I hope you have found this blog helpful and I welcome your feedback.

                                                                      Comments