Cloud-init: What is it and Why it’s Important to Your Cloud Environment

Cloud-init is a proven method of bootstrapping your instances in the cloud and creating a standard environment for your workloads to run on, providing standardization and manageability.

This page describes what it is and how it’s implemented.

Cloud-init and its capabilities

Cloud-init is an initialization service that is installed inside an instance, and cloud-config is a set of scripts that are executed as soon as the instance is started.

Zadara only provides a cloud-init metadata service. This service is available at the link-local address 169.254.169.254. It provides the VM with basic information about the instance. The service also provides cloud-init user-data, which users can add. This user-data allows for additional configurations when creating a new instance.

The Zadara Compute cloud provides the cloud-init metadata to the VM. The configuration in the OS image determines how this metadata is used during a VM’s first boot initialization.

Cloud-init runs on Linux workloads. The equivalent for Microsoft Windows is CloudBase-init, which supports the majority of cloud-config parameters. The service on the operating system 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 pass a regular script of almost any interpreter that you wish to use, providing that you have that interpreter already installed on your instance.

For example, passing a bash script to almost any instance should succeed, because most instances have bash installed by default. On the other hand, passing a Python or Ruby script to cloud-init as a file will most probably not work, unless you already have Python or Ruby installed in your instance as part of your image or template.

Cloud-config Syntax

Cloud-config has its own syntax that is based on YAML, a human-readable data serialization language. There are a number of basic rules that you should be aware of when using YAML:

  • Indentation with white spaces (not tabs) defines the relationship and structure of the resources in the script.

  • Members of a list can be identified with the leading dash on the line.

  • Blocks of text are indented.

  • Text that is to be interpreted as is, should be preceded by a pipe character (|). For example:

    examples:
    - comment: |
        Example 1: (optional) description of the expected behavior of the example
    

Cloud-config Examples

Users and Groups

When provisioning your instances, a good practice is to ensure that you have a default group and a user defined for the instance. This allows you to ensure that you have a standard configuration of all your provisioned instances and also allows you to comply with requirements as needed.

#cloud-config
users:  - name: strato
          groups: sudo
          shell: /bin/bash
          sudo: ['ALL=(ALL) NOPASSWD:ALL']
          ssh-authorized-keys: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf0q4PyG0doiBQYV7OlOxbRjle026hJPBWDAaaaaxcdxd +eKHWuVXIpAiQlSElEBqQn0pOqNJZ3IBCvSLnrdZTUph4czNC4885AArS9NkyM7lK27Oo8RV8 +NI5xPB/QT3Um2Zi7GRkIwIgNPN5uqUtXvjgAaaaaaaffcdc+i1CS0Ku4ld8vndXvr504jV9BM QoZrXEST3YlriOb8Wf7hYqphVMpF3b+8df96Pxsj0+iZqayS9wFcL8ITPApHi0yVwS8T jxEtI3FDpCbf7Y/DmTGOv49+AWBkFhS2ZwwGTX65L61PDlTSAzL+rPFmHaQBHnsli8U9N6E4X HDEOjbSMRX user@example.com

What the code snippet above does:

The first line, #cloud-config, tells cloud-init that this is a cloud-config file and should be treated as such.

Next, there is a top level object users with the following characteristics:

  • A new user with the name strato

  • This user is a member of the sudo group with a bash shell, with privileges in the sudoers file that allow the user to run all privileged commands without having to provide a password

  • Specifies the key to be added to the user’s ~/.ssh/authorized_keys file when the user is created

Injecting Key-Value Pairs

When deploying at scale you are probably already using some kind of configuration management system such as Puppet, Salt or Chef to customize your instances. Attempting to manage customization on each instance individually does not scale well.

How can cloud-config help?

When you provision an instance, you would like to be able to identify the instance to be provisioned in a certain way.

For example, you would like the instance to be installed as a web server, to provide static content for your web application. The flow would be as follows:

  1. Provision an instance with cloud-config

  2. Configure the instance to point to your configuration management server

  3. Identify the instance as a web server

This can be accomplished by defining a custom variable as part of your user-data, which will be parsed by cloud-init and then used further for the provisioning of the instance.

Following is an abbreviated example (this is not a full solution) of how this would be accomplished:

#!/bin/sh set -e -x # Standard role defaultrole=web #
# get role from commandline or if absent from hiera
# if [ $# -gt 0 ]; then  role=$1 else  role="`hiera -c
/etc/puppet/hiera.yaml
role $defaultrole 2>&1`" fi # # Run puppet.
# if [ -f /etc/puppet/manifests/$role.pp  ]; then  puppet apply
/etc/puppet/manifests/$role.pp else
echo "/etc/puppet/manifests/$role.pp was not found!"
exit 1 fi

Here we have defined the instance with the role of a web server, and instructed the instance to apply the appropriate modules according to the role for which the instance was defined. This could also be accomplished by setting specific metadata on the instance through your cloud platform upon instantiation, and then configuring the instance to retrieve that information and act upon it.

Adding Specific Yum Repositories

To install your software, configure a specific yum or apt repository on the instance so that it will know from where to pull the correct packages. This can be accomplished by adding the following lines to your cloud-config file:

#cloud-config # # Add yum repository configuration to the system
# # The following example adds the file /etc/yum.repos.d/epel_testing.repo
# which can then subsequently be used by yum for later operations.
yum_repos:
# The name of the repository    epel-testing:
baseurl: http://download.fedoraproject.org/pub/epel/testing/5/$basearch
enabled: false
failovermethod: priority
gpgcheck: true
gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL
name: Extra Packages for Enterprise Linux 5 - Testing

Creating a custom image

Linux

To create your own custom image with its own custom cloud-init behavior, you’ll need to do the following to prepare the image.

  • Install any software packages you want in the final image, including the cloud-init package.

  • Configure /etc/cloud/cloud.cfg or /etc/cloud/cloud.cfg.d as desired.

  • Run cloud-init clean to clean or reset cloud-init.

  • Manually clean up anything else you don’t want baked into the image, such as installers, temporary files, shell history, and so on.

  • Shutdown and create an image from the volume.

The cloud-init documentation outlines all of this in more detail.

Cloud-init is a 3rd-party application and standard. This page provides some basic guidance.

Important

The specifics of the configuration will be something that your team should build based on requirements.

The configuration of the cloud-init client software is outside the scope of Zadara’s support.

The following guidance comes with no warranties or support. Ensure that you thoroughly review the cloud-init documentation before implementing anything for production use.

Looking at the default configuration for cloud-init found on Canonical’s Ubuntu 22.04 image, the user section looks like this:

users:
  - default

Instead of using cloud-init to create the default user, you can replace it. For example:

users:
  - name: asigra
    lock_passwd: True
    groups: [comma-separated list of groups needed for your usecase]
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    shell: /bin/bash

This creates an asigra user instead of an ubuntu user.

The lock_passwd parameter forces users to set a password at their first sign-on. Initially, they must sign on via SSH using their SSH key, as they don’t yet have a password. After signing on via SSH for the first time and setting a password, they can subsequently sign on to the VM via VNC using that password.

This configuration also grants the asigra user password-free sudo permissions. It adds them to the groups specified in the groups list, and sets their default shell to /bin/bash.

Windows

For Windows, the steps for creating a custom image are largely the same as for Linux.

  1. Install any software that you need, and apply your customizations.

  2. Install cloud-init and create or edit the configuration file to suit your needs.

  3. To get Windows into a fresh state, clean up installers, event logs, and other temporary files.

  4. Run sysprep, just as you would with any Windows OS image.

Key Pairs and Windows Access

For accessing a Windows VM, key pairs are typically not used in the same way as with Linux VMs.

Instead, after configuring the necessary settings in the cloud-init configuration, you would likely use Remote Desktop Protocol (RDP) or another remote access method to connect to the instance.

For further information, see Get a Windows instance password.