Wednesday, April 23, 2025

Ansible Journey 5: Running an Ansible Playbook

 

Note: As the number of files increases, you will want to manage them by creating a directory structure to store related files. I’ve updated my directory structure to the structure below. the playbooks will be created during this exercise, and the locations will be apparent in the commands shown in examples. The files in global_vars are used later.


opt/

     ansible/

         ansible.cfg

         files/

             sudoers/

                 sudoer_support

         global_vars/

             variables.yml

             vault_passwords

         host_vars/

         inventory/

             inventory

         playbooks/

             alsa_remove.yml

             nginx_web.yml

         README.md

Ansible playbooks are files that contain the details that in prior sections, we specified on the command line. This allows for more complicated actions without the tedium of typing everything in each tie we need to trigger automation by Ansible.


The files are YAML (.yml) files. This file format requires strict adherence to the YAML standard. This is beyond the scope of this tutorial and can be researched further here: https://yaml.org/ Be warned, the website is actually presented as a .yml file, so it looks rather odd.


The following is a basic .yml file that will install the latest version of Nginx from the host’s yum/dnf repository:


---


- hosts: all

  become: true

  tasks:


  - name: Install Nginx Web Service

  dnf:

    name: nginx

    state: latest


This is one play with one task, stored in one playbook (nginx_web.yml). It will execute actions against all hosts in the inventory file, and will request that the commands be executed using sudo. The name of the play (“Install Nginx Web Service”) is used in the output to show the results of that portion of the playbook. A playbook can contain more than one play. Finally, the “state: latest” line ensures that the latest version of the of Nginx will be installed.

NB: From professional experience, this is not really a good idea. Once an updated package is dropped into the repo, this playbook will end up updating Nginx on the server when the playbook is run again. It is very possible that the group maintaining the repository is a different group than those maintaining the playbooks, so unless these teams are in tight sync (which is most often, not the case) the software on the server could be updated before testing, and could cause breakage in a production service. The seasoned systems administrator will recognize this, and takes steps to prevent that from happening.

The playbook is run using the ansible-playbook command. The following shows the output of running this command on the command-line:


Figure 5.1: Running a playbook to install Nginx twice.

Starting out, Nginx is not installed on either server in our inventory. The first thing we notice is that the gather-facts module is executed. This is necessary for a playbook, and Ansible will add this for you behind the scenes. In the Install Nginx Web Service play, we see that there were changes to the targets. Finally, we get a Play Recap that shows a summary of what took place, and the results. The “ok=2” output indicates that two plays were executed (Gathering Facts and Install Nginx Web Service) and did not result in an error. “changed=1” indicates that one change was made (installation of Nginx).

In the second run, Nginx was still installed, so this shows the output when no changes are required.


<PREV - CONTENTS - NEXT>

Tuesday, April 22, 2025

Ansible Journey 4: Running Elevated Ansible Commands

For ansible to be useful, it will require the ability to execute commands as the root user (or equivalent). This page addresses how to given a dedicated ansible user (andadm) the ability to execute commands using the system’s sudo facility. (Other elevated privilege mechanisms are available, however sudo is the default and is perfectly capable of meeting our needs.)

Ansible requires two additional items to be added to the command-line. The first, --become, tells ansible to attempt to obtain elevated privileges. The second, --ask-become-pass instructs Ansible to ask you for the password before attempting the connection. Here is a command that will install Nginx to all systems in the inventory:


[ansadm@rocky-1 ansible]$ ansible all -m dnf -a 'name=nginx state=present' --become --ask-become-pass

BECOME password:                      <== ansadm's password here.

192.168.5.250 | CHANGED => {

   "ansible_facts": {

     "discovered_interpreter_python": "/usr/libexec/platform-python"

   },

   "changed": true,

   "msg": "",

   "rc": 0,

   "results": [

     "Installed: nginx-mod-http-perl-1:1.14.1-9.module+el8.4.0+542+81547229.x86_64",

[...]

     "Installed: nginx-mod-http-xslt-filter-1:1.14.1-9.module+el8.4.0+542+81547229.x86_64"

   ]

}

You can also use the single-character parameters, -b to replace ‘--become’ and -K to replace ‘--ask-become-pass.’


<PREV - CONTENTS - NEXT>

Ansible Journey 3: Running Ansible Commands Manually

Note: If you are also following the videos, you will notice that I skipped video #3. This covers the use of Git, which while useful is not required for the tutorial.

This covers executing an ansible command manually. While this is not a good way to leverage the core features of an Ansible-managed environment, it does provide useful output that can be used for testing, and to illustrate how Ansible functions.

The most basic command is the Ansible ping command. This is not an ICMP ping that we are used to in Unix environments. Rather this is a test performed using Ansible that checks to see if a node can receive and execute commands. Figure 3.1 shows the output (in green) of ansible ping. The first command explicitly states which files Ansible should use when executing the commands. The second demonstrates the same where the files are saved in Ansible’s configuration (discussed below). Of note is the “SUCCESS” string and the word “pong.” If the ping fails, the output will be in a different color, and will provide some details on why it failed.

Figure 3.1: The ansible ping command

 The following parameters can be used at the command line:


ParameterPurpose
allSpecifies that this action will take place on all hosts in the inventory file.
-i <file>Inventory file containing hosts upon which Ansible can operate
-mmodule component that contains the code to support execution of certain commands.
--key-file <file>Specifies the private key file to use.

The ansible.cfg file allows you to set up defaults when running ansible. Figure 3.2 shows this file.


Figure 3.2: A simple ansible.cfg file.

KeyValue
inventorySpecify the inventory file to use; searches local path first.
private_key_fileSpecify the private key to use in the connection

There is a default ansible.cfg and a hosts file that exist under /etc/ansible as defaults (created during installation). These can be overridden using the ansible.cfg file above.

If you want to perform a test and minimize output, you can run ansible against a single file using the limit parameter:

--limit <IP|hostname>


<PREV - CONTENTS - NEXT>

Ansible Journey 2: SSH Connectivity

SSH is the common tool for logging into one host from another. It is found on every version of Linux, and generally installed and set to start when the server starts. This is the default mechanism for Ansible to issue commands for other servers on the network. As such, it is both powerful, and incredibly dangerous. In most cases, we use a password or passphrase to connect from one host to another. If we use either with Ansible to connect to target hosts, we end up defeating the purpose of automation – to manage systems without human intervention.

In the prior post, I mentioned that Ansible works, whether we are in the office, or in bed. It wouldn’t do us much good to get an alert in the middle of the night because Ansible is attempting to execute some action, but is paused while waiting for a password. So, this requires setting up a passwordless authentication system, such that Ansible can make the connection, and issue the command(s) on the target without human intervention. Passwordless authentication removes one security block (the password) so you will need to secure access to the Ansible host and admin account in other ways. This is beyond the scope of this tutorial.

The following bash shell script, when executed on a host, will create that account, it's .ssh directory, and give it the permissions necessary to execute any command as if it were root:

#!/bin/bash

useradd ansadm
ssh_dir=/home/ansadm/.ssh
mkdir $ssh_dir && chmod 700 $ssh_dir

file=/etc/sudoers.d/ansadm
touch $file
chown root:root $file && chmod 440 $file && echo "ansadm ALL=(ALL) NOPASSWD: ALL" > $file

Account creation outside of Ansible is beyond the scope of this tutorial, but I'll cover at a high level what we are doing and why.

When saved as a shell script and given execute permissions, this can be run on any host (in fact, it will need to be run on every host except the ansible cont4ol host) where the ansible admin (ansadm) needs to exectute commands. First, we create the account, and ensure its .ssh directory is available. Next, we create a sudoers file for ansadm, and drop that in place so ansadm can obtain elevated permissions. This is all done in a secure way, such that permissions are not granted until the files are properly secured with permissions and ownership.

We need the .ssh directory to be in place before we use ansible to copy over the ansadm's public key.n This is because the authorized_key module will not create an .ssh directory as of this writing. Then, we drop in the file that gives ansadm permissions to execute any command. AS shown, that file has just one line:

ansadm ALL=(ALL) NOPASSWD: ALL


With that out of the way, we can begin using ansible to automate tasks.


<PREV - CONTENTS - NEXT>

 

Ansible Journey 1: Introduction

The author of the video series states that the purpose of Ansible is to provision hosts. I view Ansible as having that capability, but with a more general purpose. In my view, Ansible is an automation tool. Does it provision hosts? Yes, and that is a great use-case. More generally, Ansible provides a means of automating tasks that go far beyond simple provisioning.


Consider a situation in which one of your services go down. You have a secondary host that can provide the same service, but in a standby configuration. When the service goes down, you need a way to detect that, and bring the service up on the standby host, with no human involvement. This is where Ansible shines. By automating the process of bringing up the service on the standby host with Ansible, you have a fail-over solution that works whether you are in the office, or in bed.


There are two types of hosts I’ll be using: the Ansible host, and the client. Unlike other solutions (Chef, Puppet, etc.) there is no client utility required to receive inbound Ansible requests. Ansible relies completely on SSH for connectivity, and issuing commands.


I will use a single host (rocky_1) as the Ansible host. This server has the Ansible package installed. It will contain all of the files required to manage target hosts, including the configurations, inventories, and groups of commands (playbooks). I also have two target hosts (rocky_2 and rocky_3) that will be configured from the Ansible host.

 

<PREV - CONTENTS - NEXT>

 

An Ansible Journey

Welcome to my Ansible tutorial. This isn’t really meant for you, but rather is a tool for me to document my progress on learning Ansible. One of they keys of learning something quickly is to observe, internalize, practice, then write about what you are learning. I’ve set four days aside to do that before starting a new position. Now, if something along the way helps you out, great. Please feel free to read the posts; I'm happy to have you here, and I really hope you get something out of them.

I’ve based them off of the learnlinux.tv video series on YouTube, a 16-part series. I’ll write at least one post for each video with the exception of #3 which discusses Git. Git is a great tool, but unlike the SSH video, it's not strictly required for the tutorial. That said, in a revenue-generating environment, version control is an absolute must, and should be considered.

Here are the contents (which will be converted to links as I go):


1. Introduction

2. SSH Overview and Setup

3. Running Ad-Hoc Commands

4. Running Elevated Ad-Hoc Commands

5. Writing Our First Playbook

6. The When Conditional

7. Improving Your Playbook

8. Targeting Specific Nodes

9. Tags

10. Managing Files

11. Managing Services

12. Managing Users

13. Roles

14. Host Variablesand Handlers

15. Templates


With that, let’s dive right in by clicking the Introduction link above.

NEXT>

Monday, October 14, 2024

Solar Eclipse 2024 Expedition

Honestly, I can't say what the heck happened, but I never posted on my 2024 Solar Eclipse Expedition. But it happened, and here is that day.

I started out following state and U.S. highways past Indianapolis to a small town called Hartford City. Why Hartford City, IN? Well, as it happens, there is a cloud cover website you can visit that will tell you on a map what the percentage of cloud cover is for a given time of day and location. Hartford City showed up as an ideal spot, being both inside the inner band for the longest eclipse and as it had the lowest percentage of cloud cover in Indiana. I pulled into a public park in the middle of town.

 I set up next to a family who had just bought their telescope the day before at Costco. No bad vibes on Mom & Dad... They were out there serious about learning how to use the telescope to get a good view for the kids, and they did so, spectacularly. They were a really wonderful family, and I enjoyed meeting and talking with them. They were accompanied by friends, all from Valparaiso University.

As for me, I set up my gear over an hour or so, as I made good time hitting Hartford City in the morning. I got my focus where I thought it needed to be and started imaging. Slow through the partial, but at a great flurry during totality. I ended up with some nice images of totality. My goal of getting the diamond ring was accomplished as well. Here are some of the images from the day.

These were shot on a Canon T1i with a Tamron 70-300mm zoom. I used an ultraviolet filter matched with a 16.6n neutral density filter. All have been post-processed for brightness/contrast, and using the gimp plugin for the astrophotography noise filter.



Sol prior to the eclipse. ISO400, 1/2048th sec., f16.

As the eclipse begins, the air cools down and things seem a little off. ISO400, 1/2048th sec., f11.

Retreating from totality. ISO400 1/3200th sec., f14.

And totality! Prominences were nice, albeit a bit smaller. ISO400, 1/512th sec., f14.

This was the coveted prize of the trip: the diamond ring image. ISO400, 1/320th sec., f14. 

This is a composite image consisting of just the sun from one image, and the jet and sky from the second. It's a false image, but gives an interesting view. The jet is on display at American Legion Post 313 in Fairmount, IN. ISO400, 1/2580th sec, f11 (jet/sky).