A beginner's guide to auto-configure a Linux machine with Ansible
Do you want to configure a Linux machine automatically in a couple of minutes?
In this third part of this post series, we cover application deployment with Ansible, to automate installing and configuring the software required to make our environment available for use.
The overall goal is to get several cloud resources automatically provisioned and configured to deliver a reproducible Linux environment that supports a use case, which in this case is creating virtual network topologies for lab testing. This is a four-part blog post series that covers:
- Use-case description
- Automating Infrastructure Provisioning
- Delivering an Application Deployment Environment
- Releasing Cloud resources
Target Environment
We typically think of platform as a service (PaaS) for application deployment, where a third-party vendor provides an environment that bundles together network resources, databases, and software dependencies to run an application. However, you can alternatively take care of these yourself, which is what we aim to automate and present in this blog post.
While we are automating the installation and configuration of a software mix that might be specific for this scenario, the automation patterns are the same for other software combinations.
The goal is not to cover every aspect of Linux System roles, for example, but to provide a succinct list of Ansible tasks that can deliver a Linux environment to fulfill a particular purpose.
If you just want to see the code, you can go to the repository. Otherwise, here is the description of the Ansible tasks executed for this example.
Customize the Linux environment
We start with a couple of cosmetic examples. All tasks included in here support two different Linux distributions: Ubuntu and Fedora.
Configure the hostname
We use the hostname
Ansible module to configure the name of the system. We take the hostname value in the Ansible inventory via the magic variable hostvars
that has all the variables assigned to hosts.
Change the Bash prompt
Some people prefer to customize their setups using dotfiles to get a consistent look and feel across their systems. You can copy these files over using the Ansible copy
module, and source them in either .bashrc
or .bash_profile
for example.
We only show a simple example to change the Bash prompt by copying over a file with the prompt variable (PS1
) details to /etc/profile.d
. This is enough for Fedora, however for Ubuntu, we need to source this file explicitly, hence we include an extra task with a conditional clause (when
) to only execute it for hosts running that Linux distribution.
Installing Packages and Libraries
Install packages
The variable common_software
provides a list of packages that are common across the Linux distributions options. You can overwrite its value — using Ansible Variable Precedence — with any list of packages of your preference.
Then the package
Ansible module installs these.
The variable base_software
provides a complimentary list of distribution-based packages. The facts variable ansible_distribution_file_variety
determines which packages to install: For either Debian
(Ubuntu) or RedHat
(Fedora).
Install libraries
Following the same pattern, we can install Python libraries, for example, by listing them on a variable which you can overwrite (python_libraries
).
The pip
Ansible module takes care of installing these Python libraries.
Install special software
We can’t install every software application with a package manager, or maybe you prefer a customized installation. In this opportunity, we install a programming language (Go), Docker to run containers, and Containerlab to create virtual network topologies.
Go
The following tasks automate the instructions to install Go, making it a consistent installation across Linux distributions.
It installs Go Version (go_version
) 1.16.5
by default. It gets the archive file from the download URL (go_download_url
) https://golang.org/dl/go{{ go_version }}…
. After downloading the archive file with the Ansible module get_url
, it unarchives to /usr/local
with the unarchive
Ansible module.
Docker
Docker provides installation guides for Fedora and Ubuntu. They have different dependencies and package repositories that need to be added to the target system. In the code snippet below, we see the instructions that are specific to Fedora. The rpm_key
Ansible module installs the GPG key of the repository, and then the Ansible module get_url
adds the Docker repository for the same Linux distribution.
With the distribution-specific tasks out of the way, we can proceed with the installation tasks that are common for Fedora and Ubuntu.
Last, but not least, a trick to manage Docker as a non-root user.
Containerlab
The installation steps are very similar to what we did for Go and are Linux distribution agnostic. We additionally create a symlink with the file
Ansible module to get a shorter executable name (clab
).
Advanced Linux tasks
Some tasks might make changes that require a reboot. Following an example of how to handle these.
Check cgroups version
We want to make sure we run cgroups v1, as some containers we need to run only support this version. However, Fedora31+ comes with cgroups v2 as the default, so we revert Systemd configuration to use cgroups v1 with the next task using the command
Ansible module.
After making the change, it notifies the handler Reboot machine
to reboot the machine with the reboot
Ansible module, and it resumes the Playbook execution when the managed node comes back online.
Execution
As stated in the first part of this series, to run this example you need to have Ansible installed on your computer and follow these steps to provision the testbed:
1. Clone the repository with git clone https://github.com/nleiva/aws-testbed.git
2. Make your AWS account credentials (AWS_ACCESS_KEY
and AWS_SECRET_KEY
) available as environment variables (export
).
3. Run the Playbook: ansible-playbook create-EC2-testbed.yml
.
Logging into the VM
The execution logs provide instructions to connect to the VM at the end. Something along the lines ssh -i testbed-private.pem fedora@ec2–54–175–179-XXX.compute-1.amazonaws.com
.
⇨ ansible-playbook create-EC2-testbed.yml -v
<snip>
TASK [Print out SSH access details] ***********************************************************************************************************************************************************
ok: [testbed-fedora34] => {
"msg": "ssh -i testbed-private.pem fedora@ec2-54-175-179-XXX.compute-1.amazonaws.com"
}
RUNNING HANDLER [configure_instance : Reboot machine] *****************************************************************************************************************************************
changed: [testbed-fedora34] => {"changed": true, "elapsed": 22, "rebooted": true}
PLAY RECAP ************************************************************************************************************************************************************************************
localhost : ok=25 changed=7 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
testbed-fedora34 : ok=33 changed=22 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Running virtual networks
Once in the VM, you can run any of the topology examples in the lab
folder. Change directory and run the clab
command, pointing to the topology file.
⇨ cd lab/frr
⇨ sudo clab deploy --topo topology.yml
To access router1
for example: docker exec -it clab-mylab-router1 vtysh
.
More details in the lab readme file.
Conclusions
Ansible is a flexible and powerful platform that can perform a myriad of tasks on Linux systems that enable us to automate the delivery of environments that are ready to serve a purpose.
In the next post, we go through the details of how we can automatically release all the resources we just created. Stay tuned!