Heat has supported SoftwareConfig and SoftwareDeployment resources since the Icehouse release, in an effort to provide flexible and non-opinionated abstractions which enable integration with existing software configuration tools and scripts.
The key concepts and some examples are described in our user guide, but what follows is more of a primer, to provide necessary context before we get in to decomposing the TripleO heat templates. If what follows looks a little scary, check out my introductory (very simple) screencast, which was recorded for the Heat Beyond the Basics session at the Paris OpenStack summit.
Heat SoftwareConfig resources
There are three resources necessary in a typical software configuration scenario:
- An OS::Heat::SoftwareConfig resource - this encapsulates the config to be applied, e.g a script, puppet manifest, or any other config definition format you care to use. This is just a wrapper for the config to apply, optionally parameterized with input values, it doesn't actually configure anything.
- An OS::Heat::SoftwareDeployment resource - this is the thing which actually applies the config from (1) - when it moves to and IN_PROGRESS state, it makes the config available to the specified server. By default, the deployment will stay in the IN_PROGRESS state until a signal is received via the Heat API, notifying the service of success (or failure..) applying the config.
- An OS::Nova::Server resource - this is the instance (or physical server in the case of TripleO deploying via Nova and Ironic) being configured, it must contain some tools to support SoftwareConfig, as discussed below, and define the user_data_format property to enable SoftwareConfig.
There are also OS::Heat::StructuredConfig and OS::Heat::StructuredDeployment resources, which are basically identical to SoftwareConfig/SoftwareDeployment resources, except the config is defined as a map, rather than a string (which is useful for some tools such as os-apply-config, which consumes a map of config data, rather than a string such as is used e.g applying a script or a puppet manifest). So I'll refer only to SoftwareConfig/SoftwareDeployment from here on, but all the concepts are applicable to both.
The server being configured requires some agents in order to collect and process the configuration made available via the deployment. Typically, this works as follows:
- os-collect-config polls the Heat API for updated resource metadata associated with the OS::Nova::Server resource
- When metadata is updated, os-refresh-config runs, and triggers an element called heat-config.
- heat-config then uses the "group" property defined in the SoftwareConfig properties to process applying the configuration via a hook script. Heat provides (via the heat-templates repo) a variety of ready-made hook scripts for some popular tools, but it's simple to write your own if needed, and it involves no changes to Heat, only a script inside the image you deploy.
- On completion, the hook uses "heat-config-notify" to send a signal back to Heat, which includes the return code of the thing we ran, along with stdout/stderr from the tool invoked by the hook script. This information is then made available via "heat deployment-show" via the Heat API.
- If the signal notified success, we move the SoftwareDeployment to COMPLETE state, e.g CREATE_COMPLETE. If it failed, we move it to e.g CREATE_FAILED state.
SoftwareDeployment HOT template definitionWe have example templates for many popular tools, but one thing to emphasize is that the template definition is not dependent on the tool doing the configuration - the coupling between the config to apply and the tool applying it only happens inside the instance via the heat-config hook logic.
Looking at the puppet example step-by step:
1. Define the SoftwareConfig resourceconfig:
- name: foo
- name: bar
- name: result
Here, we can see the following:
- We define the SoftwareConfig, which references a puppet manifest via get_file.
- We parameterize applying the manifest by providing some input values, which can specify a default value
- The "group" is specified as "puppet", which will enable heat-config to correctly apply the manifest using the heat-config-puppet hook.
- We specify an output - this means inside the manifest we can reference the special "heat_outputs_path" input, and write a file containing a result related to this output.
2. Define the Server resourceserver:
Here, the some things to note:
- The image provided must contain the tools previously discussed (os-collect-config, os-refresh-config, heat-config and whatever hooks you need for the "group" properties you want to specify)
- user_data_format must be set to "SOFTWARE_CONFIG"
- user_data may still be specified - this is useful where you want to combine first-boot configuration (e.g via cloud-init) with subsequent application deployment via SoftwareConfig. A recent TripleO patch illustrates this approach.
3. Define the SoftwareDeployment resourcedeployment:
I've put the SoftwareDeployment resource last on purpose - to highlight the normal deployment flow:
- heat creates the SoftwareConfig, then the Server, then the Deployment
- The Deployment applies the config, depending on both the SoftwareConfig and Server resources (implicitly via the get_resource references).
- The Deployment resource status depends on the status of the signal sent back to heat after applying the config (via the heat-config hook).
input_values is used to provide the values for the parameters defined in the SoftwareConfig resource - thus it's perfectly fine for multiple Deployment resources to reference the same Config resource (potentially with different input_values and/or actions specified), but each deployment references exactly one Config (e.g a SoftwareDeployment cannot apply multiple SoftwareConfig resources, only one).
Dealing with dependencies
A common pattern is doing a series of configuration steps, for example configure a database, then some application that uses the database (and requires it to be installed and configured).
There are a couple of ways to handle this:
- SoftwareDeployment resources have a "name" property, which can influence the sort-order so that, for example, heat-config will apply "config1" before "config2".
- Template directive "depends_on" can be used to specify an explicit dependency between two (or more) SoftwareDeployment resources (Note: the dependency is between the *deployment* resources, not the SoftwareConfig resources!)
Conclusion and further resourcesHopefully that concludes a reasonable overview of heat SoftwareConfiguration capabilities. For further information, please see the heat documentation, the user guide and template guide and example templates are a good starting point.
If you're feeling brave, you can also dive into the TripleO heat templates, which make extensive use of SoftwareConfig/StructuredConfig and SoftwareDeployment/Structured deployment resources. More on TripleO specifically in a future post! :)