Cloud InitIn the previous post we’ve seen how to setup and configure Cloud Automation Services, how to use Cloud Assembly to create a fully Cloud agnostic blueprint, how to use input variables and how to integrate Cloud Automation Services with Puppet. In this post I will discuss how to use Cloud-Init to customize the deployment eg. how to install applications on top of that virtual machine component in the blueprint.

In vRealize Automation this process depends on a vRealize Automation guest- and a bootstrap agent. With Cloud Automation Services, VMware stepped away from this and adopted an industry standard method called Cloud-Init.


What is Cloud-Init?

When deploying virtual machines using Cloud Automation Services, every instance starts out as a clone of a template, ami, or image. To give the virtual machine its specific role and configuration you need a tool that does this customization. Cloud-init is the service that is installed inside the instance and applies a cloud-config automatically as soon as the instance is started. Cloud-config is the language of the scripts that cloud-init knows to execute.

While cloud-init started life in Ubuntu, it is now available for most major Linux and FreeBSD operating systems. It is currently installed in the Ubuntu Cloud Images and also in the official Ubuntu images available on EC2, Azure, GCE and many other clouds. For a list of Cloud-Init enabled virtual machines in Azure see this list.

For Microsoft Windows workloads, the equivalent is CloudBase-init but is this is currently not usable within Cloud Assembly.

Cloud-Init starts early at boot, retrieves metadata that has been provided from an external provider (metadata) or by direct user data supplied by the user.

You can use Cloud Init to perform a variety of actions:

  • Create users.
  • Setting a default locale.
  • Modifying configuration files.
  • Setting a hostname.
  • Creating files or folders.
  • Setting up mount points.
  • Configuring network devices.
  • Install applications.
  • …..


How do I prepare for Cloud-Init?

If you’re using images that are not Cloud-Init enabled, like on your vSphere environment, you can set it up in the following way.

Red Hat/CentOS

For Red Hat / CentOS run the following commands:

sudo yum install -y cloud-init gdisk
sudo yum check-update cloud-init -y
sudo yum install cloud-init -y


For Ubuntu 14.04 and 16.04, please use vanilla cloud-init. Use the stock Ubuntu images provided by Canonical, which come with cloud-init pre-installed.
If you’re using non-Canonical images, use the following command-line to install cloud-init on Debian-based systems.

apt-get -y update
apt-get -y install cloud-init


How do I use Cloud-Init?

Now that you’ve enabled Cloud-Init on your templates or images, it’s time to look at some examples/possibilities. Cloud-Init starts at the virtual machine’s first boot and retrieves the metadata that has been provided from an external provider. In the case of Cloud Automation Services, the metadata or instructions that are needed to perform are provided in the blueprint YAML code. See the image below:

inputs: {}
    type: Cloud.Machine
      image: ubuntu
      flavor: small
        - tag: "env:dev"
        - name: '${}'
      cloudConfig: |
    type: Cloud.Network
      name: WP-Network
      networkType: public


In the red square, below line 13 you can now insert your code. Make sure you have the right indentation.

Cloud-Init examples

For instance, create a directory using Cloud-init.

  - mkdir -p [directory_location]
  - mkdir -p /var/www/html/mywebsite

Restart a service.

  - service [servicename] reload
  - service apache2 reload

Set hostname.

  hostname: [host_name] #static hostname
  hostname: ${input.vmname} #using input variable
  hostname: 'srv-web01'

Run commands on first boot.

  sh [command or script]
  sh, -xc, "echo $(date) ': Hello World!'"

Create a new user with ssh-rsa key access and bash shell environment.

  - name: demo
      - ssh-rsa <public_key>
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    groups: [admin, root, sudo]  #add required groups
    shell: /bin/bash

Create a new user with password access and bash shell environment.

  ssh_pwauth: yes
    list: |
    expire: false
    - default
    - name: [user-name]
      passwd: [password]
      lock_passwd: false
      sudo: ['ALL=(ALL) NOPASSWD:ALL']
      groups: [wheel, sudo, admin] #add required groups
      shell: '/bin/bash'

Install application packages like ‘apache‘, ‘php‘, ‘mysql-client‘, etc.

  repo_update: true
  repo_upgrade: all

  - [package_name]
  - apache2
  - php
  - mysql-client  
  - php-mysql
  - libapache2-mod-php
  - php-mcrypt

Install and configure a Postgres Database.
(credits: Cody  De Arkland)

  - postgresql
  - |
    sudo -u postgres psql <<SQL
      CREATE DATABASE [database_name];
      CREATE USER dbuser with encrypted password '[password]';
      grant all privileges on database [database_name] to dbuser;
      \connect [database_name];
      CREATE TABLE textData (
      id        SERIAL PRIMARY KEY,
      title       TEXT,
      text        TEXT
      ALTER DATABASE posts OWNER TO dbuser;
      ALTER TABLE textData OWNER TO dbuser;
  - echo "Restarting Postgres Services"
  - [ systemctl, stop, postgresql.service ]
  - ufw allow 5432
  - echo "host    all    all   md5" >> /etc/postgresql/9.5/main/pg_hba.conf
  - echo "listen_addresses = '*'" >> /etc/postgresql/9.5/main/postgresql.conf
  - [ systemctl, start, postgresql.service ]

This is not the end of this series because there are a lot of topics still to be explained. Next up, how to define dependencies in your CAS blueprints. So check-in regular for new content!