Heat Orchestration
Especially when dealing with larger setups launching and deleting resources manually via the webui or even the command line clients can get tedious very soon. While there is the possibility to script deployments yourself with a combination of BASH, Python and Ansible Openstack provides a service called Heat that deals specifically with orchestration. Even for just creating VMs you later bootstrap with Ansible Heat can be useful.
The following article should give you a quick introduction on how to use both the webui and the CLI client for Heat orchestration, as for Heat templates itself it will only cover a few useful examples, like creating the server from a volume, as necessary with our Ceph storage backend. For more detailed information about Heat refer to the official documentation: https://docs.openstack.org/heat/queens/ and for more in depth examples for Heat templating and Heat based software deployment check out the template guide: https://docs.openstack.org/heat/queens/template_guide/
Introduction to Heat
Heat organizes resources in so called stacks. These stacks are created according to the YAML formatted template the user provides the Heat service. Besides the mere creation Heat allows you to check, suspend, resume and delete the entire stack at once. Further bootstrapping of the created VMs is basically possible via cloud-init, but Heat extends this by allowing to create more elaborate so-called SoftwareConfigs that can be used in a similar fashion as Ansible.
The Webui
The Heat webui is located at Project->Orchestration:
Creating a stack
1. navigate to the Orchetration tab and click on Launch Stack which open the following dialog:
2. select a Template Source File and provide the YAML template, note that you can find template examples further below:
3. Click Next and enter the Stack Name and a Password, note that this password has nothing to do with any kind of login, this is just for confirmation of certain operation on the stack throughout its life cycle:
4. Click Launch:
5. Wait for completion:
Operations on the Stack
Once the stack is ready you can perform the following operations on it:
Detailed View
When you click on the stacks name you get to the detailed view which has multiple tabs:
Topology Tab
Overview Tab
Resources Tab
Events Tab
Template Tab
The CLI Client
Installation
On a Debian-based system you can install the heat client with:
sudo apt install python3-openstackclient python3-heatclient
Usage
Don't forget to source the openrc file as described in our Tutorial: OpenStack Command Line Tools
Creating a Stack
Creating a stack from a template file is done as follows:
openstack stack create -t server-debian.yml example-stack --wait
The option --wait
lets the client wait for the completion of the stack.
Deleting a Stack
To delete a stack again use:
openstack stack delete --wait example-stack
Again the --wait
option lets the client wait for the completion of the operation. In case the deletion fails possibly because the creation left the stack in an inconsistent state, the option --force
might help.
Template Examples
Just a Server
Because the LRZ Compute Cloud uses a Ceph storage it is necessary to manually create a volume beforehand and then launch an instance from it when using the CLI clients as welll as the Heat client. The following template does just that, it creates a volume from the image Debian-10-buster and then launches a VM using this volume:
heat_template_version: queens description: Launch a server resources: volume: type: OS::Cinder::Volume properties: name: myvolume image: Debian-10-buster size: 20 server: type: OS::Nova::Server depends_on: volume properties: name: myserver flavor: lrz.small key_name: cloud-ssh-key block_device_mapping_v2: - volume_id: { get_resource: volume } networks: - network: internet
The get_resource
is a heat specific macro to the UUID of a resource defined in the template. This example probably won't work for you, since it hard-codes the SSH key name, and yours is likely to be different.
Input Parameters
The previous example hard-coded everything, which is fine for a static setup, but sometimes you might want to make small changes without changing the template itself. The following example allows this by using parameters:
heat_template_version: queens description: Launch a server parameters: server_name: type: string default: myserver volume_name: type: string default: myvolume image: type: string default: Debian-10-buster flavor: type: string default: lrz.small key: type: string volume_size: type: number default: 20 network: type: string default: internet resources: volume: type: OS::Cinder::Volume properties: name: { get_param: volume_name } image: { get_param: image } size: { get_param: volume_size } server: type: OS::Nova::Server depends_on: volume properties: name: { get_param: server_name } flavor: { get_param: flavor } key_name: { get_param: key } block_device_mapping_v2: - volume_id: { get_resource: volume } networks: - network: { get_param: network }
The value of the parameters can be used in the template by calling the get_param
macro. Note that all parameters but key
have a default value, therefore key
is a required parameter. While the webui will ask for the values of the parameters in the dialog, the CLI client requires you to specify it either with the --parameter
option like this:
openstack stack create -t server-params.yml example-stack --wait --parameter key=cloud-ssh-key --parameter image=CentOS-8
Creating and Attaching a Floating IP
Unless you want to use another VM in the same network you will need a floating IP to directly connect to your VM. The following template adds creation and attachment of a floating IP to the previous example:
heat_template_version: queens description: Launch a server parameters: server_name: type: string default: myserver volume_name: type: string default: myvolume image: type: string default: Debian-10-buster flavor: type: string default: lrz.small key: type: string volume_size: type: number default: 20 network: type: string default: internet resources: volume: type: OS::Cinder::Volume properties: name: { get_param: volume_name } image: { get_param: image } size: { get_param: volume_size } server: type: OS::Nova::Server depends_on: volume properties: name: { get_param: server_name } flavor: { get_param: flavor } key_name: { get_param: key } block_device_mapping_v2: - volume_id: { get_resource: volume } networks: - network: { get_param: network } floating_ip: type: OS::Neutron::FloatingIP properties: floating_network: { list_join: ['', [{ get_param: network }, '_pool']] } floating_ip_association: type: OS::Neutron::FloatingIPAssociation depends_on: - server - floating_ip properties: floatingip_id: { get_resource: floating_ip } port_id: { get_attr: [server, addresses, { get_param: network }, 0, port] }
This example also introduces the macros get_attr
and list_join
.
Output
Heat templates do not only allow input but also output. A typical use case is the previous example where we created and attached a floating IP, but actually also want to know the address afterwards. This can be accomplished as follows:
heat_template_version: queens description: Launch a server parameters: server_name: type: string default: myserver volume_name: type: string default: myvolume image: type: string default: Debian-10-buster flavor: type: string default: lrz.small key: type: string volume_size: type: number default: 20 network: type: string default: internet resources: volume: type: OS::Cinder::Volume properties: name: { get_param: volume_name } image: { get_param: image } size: { get_param: volume_size } server: type: OS::Nova::Server depends_on: volume properties: name: { get_param: server_name } flavor: { get_param: flavor } key_name: { get_param: key } block_device_mapping_v2: - volume_id: { get_resource: volume } networks: - network: { get_param: network } floating_ip: type: OS::Neutron::FloatingIP properties: floating_network: { list_join: ['', [{ get_param: network }, '_pool']] } floating_ip_association: type: OS::Neutron::FloatingIPAssociation depends_on: - server - floating_ip properties: floatingip_id: { get_resource: floating_ip } port_id: { get_attr: [server, addresses, { get_param: network }, 0, port] } outputs: public_ip: description: The public ip of the server value: { get_attr: [floating_ip, floating_ip_address] }
While the webui show the outputs in the Overview Tab of the stacks detailed view, in the CLI you have to query it with:
openstack stack output show example-stack public_ip
after the creation of the stack has completed, which makes the --wait
flag in the create command come in handy.
Further Examples
The previous examples only cover the basics of Heat templating, a good starting point for more advanced topics and also a documentation of all the over resource types is the official template guide: https://docs.openstack.org/heat/queens/template_guide/. If you find complete templates online be sure that they are compatible with our Heat version.