How to create a Cloud Agnostic service in Cloud Assembly

Cloud Agnostic

As discussed earlier, VMware released three new Cloud Automation Services at VMworld 2018. Cloud Assembly, Service Broker and Code Stream are the three new golden nuggets. I already discussed the role and functions of these three services and Dimitri already showed you how you can quickly get up-and-running with Cloud Assembly. He has described how to connect your on-premises environment using the Data Collector, how to do the initial configuration, how to build your first blueprint and even how to leverage your existing Puppet assets. Needless to say that I’m over the moon with the power of these new Cloud Automation Services. But for me, one of the coolest new features is the Cloud Agnostic blueprint.

In this article I will discuss the prerequisites, the limitations, show you how to create a cloud agnostic blueprint and show you how to ‘steer’ the deployment to a specific cloud provider.

What is a cloud agnostic blueprint?

A cloud agnostic blueprint is a blueprint that allows you to deploy exactly the same construct to different clouds. Cloud Assembly has the intelligence to take this cloud agnostic blueprint and know when to place it where using which specific cloud components. At the time of GA vSphere, AWS and Azure are supported.

This bring us directly to the limitations of cloud agnostic blueprints. Because Cloud Assembly ’translates’ the used blueprint components to the cloud specific building blocks, you can only use components that are known to all cloud providers. I can use an Ubuntu template because I pointed to the cloud specific Ubuntu templates using image mappings. I can use t-shirt size deployments like small/medium/large because I defined what I mean with these t-shirts sizes in the different cloud providers using flavour mapping.


That brings us to the prerequisites. For cloud agnostic blueprints to work, you must have the following in place:

Cloud Agnostic

  • Flavor mappings - maps t-shirt sizes like small/medium/large to the required size configurations in each used cloud environment. For example: mapping ‘Small’ to a ‘t2.micro instance’ on AWS and ‘1 vCPU, 1GB RAM’ on vSphere.
  • Image mappings - maps the required image to an image/template on each used cloud environment. Usually based on operating system selection. For example: mapping ‘Ubuntu’ to a vSphere template named ‘Template ubuntu-denial-16.04’ and an AWS ami named ‘ami-a1b2c3’.
  • Network profiles - defines a networks and network settings that are available for that cloud account in that region. The network and security settings that are defined in the matched network profile are also applied when the blueprint is deployed.


  • Storage profiles - definition of a cloud-specific set of storage policies that let the cloud administrator define storage for a cloud account region.
  • Tags - are used to ‘steer’ your deployment. For example: assign a ‘env:prod’ tag to your vSphere cloud zone, assign a ‘env:dev’ tag to AWS and a ‘env:test’ tag to Azure. By using these tags in your blueprint you can direct the deployment to your test, development or production environment. The same can be done with storage (gold/silver/bronze) or networks (private/public) within the cloud environments.

If you have followed Dimitri’s previous articles on in which he shows you how you can quickly get Cloud Assembly up-and-running, you should have all this in place.

Cloud agnostic blueprint

Below is a start of a very simple cloud agnostic blueprint. You see that there’s no specific vSphere or AWS functionality in the blueprint and that the marked (purple) properties are all static defined. As you may notice, I did not use a static network assignment. This prevents me from locking myself into a specific cloud environment. Instead, I only defined that I want to use an existing network with the tag ‘networktype:public’. By doing this, Cloud Assembly will select the network with the ‘networktype:public’ tag which I defined in my network profiles.

You could use the same method to assign gold/silver/bronze storage to your blueprint without statically assigning storage and keeping your blueprint fully agnostic.

We can now take this a step further by defining inputs which act as variables to ‘steer’ the deployment or make the deployment dynamic in the sense of choice of operating system and virtual machine size.

[The use of inputs is a very interesting topic and deserves its own article. Next week, Dimitri will show you how to use inputs, how to use different types of input and how to limit the inputs by using filters.]

To create a more dynamic deployment, I added two inputs which determine the size (${input.size}, marked in purple) and the operating system (${input.operating_system}, marked in red]). These prompt the user at deployment to choose a size and an operating system.

To direct the deployment to a cloud environment, I added a third input, ${input.environment}, marked in green. This determines if this is a test, development or production deployment and ‘steers’ the deployment accordingly.

So, the environment input determines the cloud environment I deploy to and the actual size and VM template which are used is defined by the flavor and image mappings we discussed earlier.

To show this works I will deploy the blueprint to different environments, steering the deployment by selecting the environment at request. In the background this uses the capability tags you see in the image below and this is something we call tag based placement.

As you can see I have three cloud zones in my project. Azure with a priority of 1 (highest), AWS with a priority of 2 (mid) and vSphere with a priority of 3 (lowest). If I would not use tags, this would be the order in which the different cloud environments are used. But I assigned tags to these cloud zones. Azure is my test environment (env:test), AWS is my development environment (env:dev) and vSphere is my production environment (env:prod). You will probably recognise these values from the environment input I used above.

Test deployment

On the left you see how the inputs show on the request form. On the right you can see what the effect is on an actual deployment? Cloud Assembly offers a great visual way of providing you with this information. In the request details you can display a Provisioning diagram. This provisioning diagram is a flow chart in which Cloud assembly shows why it made the choice it did and why did my virtual machine end up on Azure.

In the provisioning diagram you can see that this virtual machine is deployed on Azure because this cloud zone has a matching env:test tag. You can also see that AWS was not used because ‘Hard constraints could not be met’, in other words it did not have a matching tag.

Development deployment

Now we request a virtual machine in the development environment.

Again, in the provisioning diagram you can see that this virtual machine is deployed on AWS because this cloud zone has a matching env:dev tag. You can also see that although Azure has a higher priority, it was not used because it did not have a matching tag.

Production deployment

The last deployment is a virtual machine in the production environment.​

Here we see something strange. In the provisioning diagram you can see that this virtual machine is deployed on vSphere because this cloud zone has a matching env:prod tag. You can also see that although AWS has a higher priority, it was not used because it did not have a matching tag.

The strange thing is that the vSphere cloud zone has two clusters, Core Infra and Home Lab. Core Infra is tagged with env:prod, so this is where the requested virtual machine is created. But Home Lab is tagged with env:dev, so why did our previous deployment not end up on vSphere? This is because the AWS cloud zone also has the env:dev tag but a higher priority.

This makes that tags offers you a very powerful way to determine which cloud environment, storage, network, etc. to use while maintaining the power of a cloud agnostic service definition.