Photo by Pawel Nolbert on Unsplash

Photo by Pawel Nolbert on Unsplash

Multicloud management with Ansible

Independence

Article from ADMIN 65/2021
By
Remain independent of your cloud provider by automatically rolling out virtual machines and applications with Ansible neutral inventory files.

Many cloud providers vie for the user's favor. Besides the top dogs, Amazon Web Services (AWS), Azure, and Google Cloud Platform (GCP), smaller regional or specialized providers are increasingly offering cloud computing resources, which is good for the user because competition is known to stimulate business and prompt price drops. Precisely because companies have a choice when it comes to cloud services, they will not want to bind themselves to a single vendor.

However, very few professional cloud users click through the providers' pretty web GUIs to roll out dynamic resources. The whole thing has to work quickly and automatically. All cloud providers, therefore, offer powerful tools for the command line, which can also be used to generate scripts that automate the rollout.

Of course, this is exactly what could shoot down your desired independence from the provider. After all, anyone who has invested a large amount of time developing fancy scripts for AWS cannot easily switch to GCP or Azure without first switching their automation to a different toolset. Two things can help in such a case: Ansible as an independent automation tool and a modular abstraction strategy.

Independence

Nobody rolls out empty virtual machines (VMs) for their own sake on platforms such as AWS or GCP: The decision is determined by the application. Providers are offering more and more convenient and preconfigured services for this purpose. Want MariaDB? No problem: Here's a pre-built image to roll out directly to AWS. The user saves themselves the trouble of separate operating system (OS) and database installations. This scenario sounds tempting, especially for the cloud provider, because it ties the user firmly to the platform and precisely to this one template, which is not available for another platform in this form.

To remain independent, administrators need to separate the VM rollout from the distribution of the applications. Minimal OS templates that are more or less identical on all cloud platforms can help. Alternatively, you can use a tool (e.g., lorax-composer [1]) to build your own OS templates, which can then be uploaded to the respective cloud environment.

With a modular rollout like this, admins write their installation and configuration playbooks independently of the cloud they use. The rollout process simply needs to communicate a set of parameters to the application automation component in a vendor-independent format. Whatever that component may be, the parameters include:

  • The external IP address through which the VM is accessible to Ansible and later the application.
  • The internal IP address that the application uses to communicate with other VMs in the same rollout.
  • The purpose or type of machine.

For Ansible to address the target systems for the application rollout, it needs a vendor-independent inventory. The Ansible modules for GCP, AWS, and Azure, of course, provide scripts for dynamic inventories, but there is a catch: For example, if you want to query the inventory of a GCP project dynamically and thus discover the internal IP address of a VM, you have to use the gce_private_ip variable. On AWS this would be ec2_private_ip.

Even in Ansible, the cloud modules come from the respective providers, and the designation of Ansible "facts" and variables is based on provider standards across the board. It is up to you as the administrator to ensure a neutral inventory.

Dynamic Static Inventory

A simple trick to stay as neutral as possible in cloud usage works like this: The vendor-specific playbook that rolls out the required VMs on the target platform also creates a static inventory file and there enters the variables required by the application rollout in an independent form. The application rollout playbook, in turn, takes all the necessary variables from the inventory file and can then work with any target platform, whether AWS, GCP, or even on-premises environments such as vSphere.

Here, I look at a vendor-neutral cloud rollout with two playbooks: one for AWS and the other for GCP. At the end, you will have a set of VMs and a matching neutral inventory. The examples shown here assume that the clouds you are using have been prepared, and that you have created the required users and SSH keys, as well as the appropriate subnets, security groups, and firewall rules.

By the way, if you work with variable data in an Ansible playbook, you should always keep the data separate from the playbook logic (i.e., never hard code the data directly into the playbook). Moreover, you always need to think first about the kind of data you need to capture and the kind of data you need to register before moving on to the logic. To begin, I'll start with the variable declaration.

Providing Basic Data: AWS

To talk to a cloud, you need to authenticate and specify the region or project in which you are working. The variable declaration ec2_vars.yml for AWS therefore starts:

---
ec2_access_key: (key)
ec2_secret_key: (secret)
ec2_region: us-east-1
ec2_key_name: (keyname)
ec2_security_group_id: sg-<ID>
ec2_vpc_subnet_id: subnet-<ID>
ec2_hostfile: ec2_hosts

The parameters are largely self-explanatory, with the exception of ec2_hostfile, which refers to the inventory file (yet to be created).

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus
Subscribe to our ADMIN Newsletters
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs



Support Our Work

ADMIN content is made possible with support from readers like you. Please consider contributing when you've found an article to be beneficial.

Learn More”>
	</a>

<hr>		    
			</div>
		    		</div>

		<div class=