Need for Ansible Ad-hoc commands

Before getting into Ansible playbooks, we’ll explore Ansible Ad-hoc commands and how it helps to quickly perform common tasks and gather data from one or many servers. For configuration management and deployments, though, you’ll want to pick up on using playbooks – the concepts you will learn here will port over directly to the playbook language.

Since the emergence of cloud and virtualization, the number of servers managed by an individual Administrator has risen dramatically in the past decade. This had made admins to find a way to manage servers in streamlined fashion. On any given day, a systems administrator might do the below tasks.

Check log files

Check resource usage

Manage system users and groups

Check for patches and apply updates using package managers

Deploy applications

Manage cron jobs

Reboot servers.

Nearly all of these tasks might have already been partially automated but some often needs manual intervention especially when it comes to diagnosing issues in real time. When working with complex multi server environment, logging into each server manually to diagnose is not a workable approach. Ansible allows sys admins to run ad-hoc commands on one or hundreds of machines at the same time using the ‘ansible’ command. You will be able to manage your servers very efficiently even if you decide to ignore the rest of Ansible’s powerful features after reading this article.

Exploring Ad-hoc commands with local infrastructure

We will be exploring the Ansible ad-hoc commands wit the local infrastructure we created in the chapter “Ansible Local Testing: Vagrant and Virtualbox“. To cut through quickly, we created 3 virtual machines using vagrant and virtualbox. We have assigned two servers to act as app and the other server as db( Just by giving names ).

Important Note: This tutorial‘s examples works fine with Ansible version > 2.0 . Versions prior to 2.0 might require small changes in variable names which will be indicated using comments.

The content of the hosts file are quite self explanatory. We have created an ‘app’ group containing ip’s of the application servers, a ‘db’ group containing ip address of the DB server and an ‘all’ group which has ip’s of all the servers. Further we have created a variable ‘ansible_user’ for the ‘all’ group which makes it easy for us to pass the commands without having the need to pass the user name every time.

Note: The variable name should be ‘ansible_ssh_user’ for versions prior to Ansible 2.0

Ansible Modules

Before jumping into Ansible Ad-hoc commands, it is important to understand about ansible modules. Ansible ships with a number of modules (called the ‘module library’) that can be executed directly on remote hosts. Users can also write their own modules. These modules can control system resources, like services, packages, or files (anything really), or handle executing system commands. They are the backbone of Ansible.

There are three types of Ansible modules

Core modules – These are modules that are supported by Ansible itself.

Extra modules – These are modules that are created by communities or companies but are included in the distribution that may not be supported by Ansible.

Deprecated modules – These are identified when a new module is going to replace it or a new module is actually more preferred.

Ansible has module documentation installed locally that you can browse. Browse all the available modules in the library by running the below command.

ansible-doc -l

To know more details about a specific module such as parameter names and how to use the module, you can use the below command

ansible-doc <module_name>

You can even get playbook example on how to use a module using the below command.

ansible-doc -s <module_name>

Ansible modules are passed with the flag ‘-m’ to indicate which module to use. For eg,

It is assumed that the connection between servers are based on ssh keys and not password. In case if you are using password based authentication, then you’ll need to use ‘-k’ flag to prompt for password.

The user id that is used to connect to the clients is expected to have passwordless sudo access. In case if you have not enabled passwordless access, you need to pass ‘-K’ flag to prompt for sudo password to execute commands requiring sudo access.

The hosts file path is assumed to be the default location ( /etc/ansible/hosts). If you are using a hosts file located in different location, then you can use ‘ANSIBLE_HOSTS’ environment variable to set the location explicitly. You can even use ‘-i’ flag in the command line to point the location of the host file to be used.

Ping test

Lets start with a ping test and make sure we can connect to our servers.

We can see the host names of the servers in random order. By default ansible runs commands in parallel using multiple process forks. The default value is 5. You can change this based upon server capacity and requirement as described in this chapter

‘-f’ denotes the number of forks (simultaneous process) to be used. Setting the value to 1 makes it to run in the sequence. It’s fairly rare that you will ever need to do this, but it’s much more frequent that you’ll want to increase the value (like -f 10, or -f 25… depending on how much your system and network connection can handle)

Note: For the above example, we did not specify the command module as “-m command” since that is the default module.

Check Disk space

Now that we have made sure our host names are correct, lets check the disk space of each server.

Here we are explicitly mentioning the module name as ‘yum’ since we use CentOS. You can use ‘apt’ for ubuntu servers. Both yum and apt module takes several attributes. In this example we are using the required ones. We are specifying the package name as ‘ntp’ with the name attribute. The state attribute specifies whether the package should be installed or removed ( ‘present’ will install and ‘absent’ will uninstall the package ). The ‘-b’ (–become-user) flag indicates that the command should be run as sudo.

Database configuration

We configured the application servers using the app group defined in Ansible’s main inventory, and we can configure the database server (currently the only server in the db group) using the similarly- defined db group.

We have successfully configured the servers to host our hypothetical web application. We just did this without logging into the servers and just by executing few commands. By this time, you might have realized the simplicity and power of Ansible.

Make changes to just one server

Assume that the ntpd service in one of the Application server got crashed and stopped. You need to verify in which server the service got stopped and restart it on that specific server.

Step 1: Check the status of the service in the app group of the inventory file

Another common use for ad-hoc commands is remote file management. Ansible makes it easy to copy files from your host to remote servers, create directories, manage file and directory permissions and ownership, and delete files or directories.

Copy files to servers

You can use either copy or synchronize module to copy files and directories to remote servers.

The src can be a file or a directory. If you include a trailing slash, only the contents of the directory will be copied into the dest. If you omit the trailing slash, the contents and the directory itself will be copied into the dest.

The copy module is perfect for single-file copies, and works very well with small directories. When you want to copy hundreds of files, especially in very deeply-nested directory structures, you should consider either copying then expanding an archive of the files with Ansible’s unarchive module, or using Ansible’s synchronize module.

The fetch module can be used, the same way as copy module. The difference is that, the files will be copied down to the local dest in a directory structure that matches the host from which you copied them. For example, use the following command to grab the hosts file from the servers.

Fetch will, by default, put the /etc/hosts file from each server into a folder in the destination with the name of the host (in our case, the three IP addresses), then in the location defined by src. So, the db server’s hosts file will end up in /Users/devopsideas/Ansible-Tutorial/192.168.33.30/etc/hosts.

You can use the file module to create files and directories (like touch), manage permissions and ownership on files and directories, modify SELinux properties, and create symlinks.
Here’s how to create a directory

Some operations take quite a while (minutes or even hours). For example, when you run yum update or apt-get update && apt-get dist-upgrade, it could be a few minutes before all the packages on your servers are updated.
In these situations, you can tell Ansible to run the commands asynchronously, and poll the servers to see when the commands finish. When you’re only managing one server, this is not really helpful, but if you have many servers, Ansible starts the command very quickly on all your servers (especially if you set a higher –forks value), then polls the servers for status until they’re all up to date.
To run a command in the background, you set the following options:

-B <seconds>: the maximum amount of time (in seconds) to let the job run.

-P <seconds>: the amount of time (in seconds) to wait between polling the servers for an
updated job status.

$ ansible -b app -B 3600 -a "yum -y update"

Deploy version controlled application

For simple application deployments, where you may need to update a git checkout, or copy a new bit of code to a group of servers, then run a command to finish the deployment, Ansible’s ad-hoc mode can help. For more complicated deployment, we need to follow a different approach, which we will see in later section.

Ansible’s git module lets you specify a branch, tag, or even a specific commit with the version parameter . To force Ansible to update the checked-out copy, we passed in update=yes. The repo and dest options should be self-explanatory.

Then, run the application’s update.sh shell script if that’s part of your deployment.

$ ansible app -s -a "/opt/myapp/update.sh"

Conclusion

In this section, we have configured, monitored, and managed the infrastructure without ever logging in to an individual server. You also learned how Ansible connects to remote servers, and how to use the ansible command to perform tasks on many servers quickly in parallel, or one by one.

This should have given you a nice overview and by now, you should be getting familiar with the basics of Ansible, and you should be able to start managing your own infrastructure more efficiently.

In the next section, we will learn how to create Ansible Playbooks and deep dive and experience the real power of Ansible.