22f1952bfe
The XML is generated from the hot-guide RST source and imported manually (see doc/user-guide/hot/README.rst to know how). Fix a broken link in the HOT guide to pass the checklinks gate. Change-Id: I839dd7219189c94930f7166ef921bceba0b9b27b
400 lines
18 KiB
XML
400 lines
18 KiB
XML
<?xml version='1.0' encoding='UTF-8'?>
|
|
<section xmlns="http://docbook.org/ns/docbook" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="hot-software-deployment">
|
|
<!--WARNING: This file is automatically generated. Do not edit it.-->
|
|
<title>Software configuration</title>
|
|
<para>There are a variety of options to configure the software which runs on the
|
|
servers in your stack. These can be broadly divided into the following:</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Custom image building</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>User-data boot scripts and cloud-init</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Software deployment resources</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>This section will describe each of these options and provide examples for
|
|
using them together in your stacks.</para>
|
|
<section xml:id="image-building">
|
|
<?dbhtml stop-chunking?>
|
|
<title>Image building</title>
|
|
<para>The first opportunity to influence what software is configured on your servers
|
|
is by booting them with a custom-built image. There are a number of reasons
|
|
you might want to do this, including:</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><emphasis role="Boot speed"/> - since the required software is already on the image there
|
|
is no need to download and install anything at boot time.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><emphasis role="Boot reliability"/> - software downloads can fail for a number of reasons
|
|
including transient network failures and inconsistent software repositories.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><emphasis role="Test verification"/> - custom built images can be verified in test
|
|
environments before being promoted to production.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><emphasis role="Configuration dependencies"/> - post-boot configuration may depend on
|
|
agents already being installed and enabled</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>A number of tools are available for building custom images, including:</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><link xlink:href="https://github.com/openstack/diskimage-builder">diskimage-builder</link> image building tools for OpenStack</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><link xlink:href="http://imgfac.org/">imagefactory</link> builds images for a variety of operating system/cloud
|
|
combinations</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>Examples in this guide which require custom images will use
|
|
<link xlink:href="https://github.com/openstack/diskimage-builder">diskimage-builder</link>.</para>
|
|
</section>
|
|
<section xml:id="user-data-boot-scripts-and-cloud-init">
|
|
<?dbhtml stop-chunking?>
|
|
<title>User-data boot scripts and cloud-init</title>
|
|
<para>When booting a server it is possible to specify the contents of the user-data
|
|
to be passed to that server. This user-data is made available either from
|
|
configured config-drive or from the <link xlink:href="http://docs.openstack.org/admin-guide-cloud/content/section_metadata-service.html">Metadata service</link>.</para>
|
|
<para>How this user-data is consumed depends on the image being booted, but the most
|
|
commonly used tool for default cloud images is <link xlink:href="http://cloudinit.readthedocs.org/en/latest/">Cloud-init</link>.</para>
|
|
<para>Whether the image is using <link xlink:href="http://cloudinit.readthedocs.org/en/latest/">Cloud-init</link> or not, it should be possible to
|
|
specify a shell script in the user_data property and have it be executed by
|
|
the server during boot:</para>
|
|
<programlisting language="yaml">resources:
|
|
|
|
the_server:
|
|
type: OS::Nova::Server
|
|
properties:
|
|
# flavor, image etc
|
|
user_data: |
|
|
#!/bin/bash
|
|
echo "Running boot script"
|
|
# ...</programlisting>
|
|
<!---->
|
|
<blockquote>
|
|
<para><emphasis role="Tip"/>: debugging these scripts it is often useful to view the boot
|
|
log using <literal>nova console-log <server-id></literal> to view the progress of boot
|
|
script execution.</para>
|
|
</blockquote>
|
|
<para>Often there is a need to set variable values based on parameters or resources
|
|
in the stack. This can be done with the <literal>str_replace</literal> intrinsic function:</para>
|
|
<programlisting language="yaml">parameters:
|
|
foo:
|
|
default: bar
|
|
|
|
resources:
|
|
|
|
the_server:
|
|
type: OS::Nova::Server
|
|
properties:
|
|
# flavor, image etc
|
|
user_data:
|
|
str_replace:
|
|
template: |
|
|
#!/bin/bash
|
|
echo "Running boot script with $FOO"
|
|
# ...
|
|
params:
|
|
$FOO: {get_param: foo}</programlisting>
|
|
<!---->
|
|
<blockquote>
|
|
<para><emphasis role="Warning"/>: If a stack-update is performed and there are any changes
|
|
at all to the content of user_data then the server will be replaced
|
|
(deleted and recreated) so that the modified boot configuration can be
|
|
run on a new server.</para>
|
|
</blockquote>
|
|
<para>When these scripts grow it can become difficult to maintain them inside the
|
|
template, so the <literal>get_file</literal> intrinsic function can be used to maintain the
|
|
script in a separate file:</para>
|
|
<programlisting language="yaml">parameters:
|
|
foo:
|
|
default: bar
|
|
|
|
resources:
|
|
|
|
the_server:
|
|
type: OS::Nova::Server
|
|
properties:
|
|
# flavor, image etc
|
|
user_data:
|
|
str_replace:
|
|
template: {get_file: the_server_boot.sh}
|
|
params:
|
|
$FOO: {get_param: foo}</programlisting>
|
|
<!---->
|
|
<blockquote>
|
|
<para><emphasis role="Tip"/>: <literal>str_replace</literal> can replace any strings, not just strings
|
|
starting with <literal>$</literal>. However doing this for the above example is useful
|
|
because the script file can be executed for testing by passing in
|
|
environment variables.</para>
|
|
</blockquote>
|
|
<section xml:id="choosing-the-user-data-format">
|
|
<title>Choosing the user_data_format</title>
|
|
<para>The <literal><link xlink:href="http://docs.openstack.org/hot-reference/content/OS__Nova__Server.html">OS::Nova::Server</link></literal> user_data_format property determines how the
|
|
user_data should be formatted for the server. For the default value
|
|
<literal>HEAT_CFNTOOLS</literal>, the user_data is bundled as part of the heat-cfntools
|
|
cloud-init boot configuration data. While <literal>HEAT_CFNTOOLS</literal> is the default
|
|
for <literal>user_data_format</literal>, it is considered legacy and <literal>RAW</literal> or
|
|
<literal>SOFTWARE_CONFIG</literal> will generally be more appropriate.</para>
|
|
<para>For <literal>RAW</literal> the user_data is passed to Nova unmodified. For a <link xlink:href="http://cloudinit.readthedocs.org/en/latest/">Cloud-init</link>
|
|
enabled image, the following are both valid <literal>RAW</literal> user-data:</para>
|
|
<programlisting language="yaml">resources:
|
|
|
|
server_with_boot_script:
|
|
type: OS::Nova::Server
|
|
properties:
|
|
# flavor, image etc
|
|
user_data_format: RAW
|
|
user_data: |
|
|
#!/bin/bash
|
|
echo "Running boot script"
|
|
# ...
|
|
|
|
server_with_cloud_config:
|
|
type: OS::Nova::Server
|
|
properties:
|
|
# flavor, image etc
|
|
user_data_format: RAW
|
|
user_data: |
|
|
#cloud-config
|
|
final_message: "The system is finally up, after $UPTIME seconds"</programlisting>
|
|
<para>For <literal>SOFTWARE_CONFIG</literal> user_data is bundled as part of the software config
|
|
data, and metadata is derived from any associated software deployment
|
|
resources.</para>
|
|
</section>
|
|
<section xml:id="signals-and-wait-conditions">
|
|
<title>Signals and wait conditions</title>
|
|
<para>Often it is necessary to pause further creation of stack resources until the
|
|
boot configuration script has notified that it has reached a certain state.
|
|
This is usually either to notify that a service is now active, or to pass out
|
|
some generated data which is needed by another resource. The resources
|
|
<literal><link xlink:href="http://docs.openstack.org/hot-reference/content/OS__Heat__WaitCondition.html">OS::Heat::WaitCondition</link></literal> and <literal><link xlink:href="http://docs.openstack.org/hot-reference/content/OS__Heat__SwiftSignal.html">OS::Heat::SwiftSignal</link></literal> both perform
|
|
this function using different techniques and tradeoffs.</para>
|
|
<para><literal><link xlink:href="http://docs.openstack.org/hot-reference/content/OS__Heat__WaitCondition.html">OS::Heat::WaitCondition</link></literal> is implemented as a call to the
|
|
<link xlink:href="http://developer.openstack.org/api-ref-orchestration-v1.html">Orchestration API</link> resource signal. The token is created using credentials
|
|
for a user account which is scoped only to the wait condition handle
|
|
resource. This user is created when the handle is created, and is associated
|
|
to a project which belongs to the stack, in an identity domain which is
|
|
dedicated to the orchestration service.</para>
|
|
<para>Sending the signal is a simple HTTP request, as with this example using <link xlink:href="http://curl.haxx.se/">curl</link>:</para>
|
|
<programlisting language="sh">curl -i -X POST -H 'X-Auth-Token: <token>' \
|
|
-H 'Content-Type: application/json' -H 'Accept: application/json' \
|
|
'<wait condition URL>' --data-binary '<json containing signal data>'</programlisting>
|
|
<para>The JSON containing the signal data is expected to be of the following format:</para>
|
|
<programlisting language="json">{
|
|
"status": "SUCCESS",
|
|
"reason": "The reason which will appear in the 'heat event-list' output",
|
|
"data": "Data to be used elsewhere in the template via get_attr",
|
|
"id": "Optional unique ID of signal"
|
|
}</programlisting>
|
|
<para>All of these values are optional, and if not specified will be set to the
|
|
following defaults:</para>
|
|
<programlisting language="json">{
|
|
"status": "SUCCESS",
|
|
"reason": "Signal <id> received",
|
|
"data": null,
|
|
"id": "<sequential number starting from 1 for each signal received>"
|
|
}</programlisting>
|
|
<para>If <literal>status</literal> is set to <literal>FAILURE</literal> then the resource (and the stack) will go
|
|
into a <literal>FAILED</literal> state using the <literal>reason</literal> as failure reason.</para>
|
|
<para>The following template example uses the convenience attribute <literal>curl_cli</literal>
|
|
which builds a curl command with a valid token:</para>
|
|
<programlisting language="yaml">resources:
|
|
wait_condition:
|
|
type: OS::Heat::WaitCondition
|
|
properties:
|
|
handle: {get_resource: wait_handle}
|
|
# Note, count of 5 vs 6 is due to duplicate signal ID 5 sent below
|
|
count: 5
|
|
timeout: 300
|
|
|
|
wait_handle:
|
|
type: OS::Heat::WaitConditionHandle
|
|
|
|
the_server:
|
|
type: OS::Nova::Server
|
|
properties:
|
|
# flavor, image etc
|
|
user_data_format: RAW
|
|
user_data:
|
|
str_replace:
|
|
template: |
|
|
#!/bin/sh
|
|
# Below are some examples of the various ways signals
|
|
# can be sent to the Handle resource
|
|
|
|
# Simple success signal
|
|
wc_notify --data-binary '{"status": "SUCCESS"}'
|
|
|
|
# Or you optionally can specify any of the additional fields
|
|
wc_notify --data-binary '{"status": "SUCCESS", "reason": "signal2"}'
|
|
wc_notify --data-binary '{"status": "SUCCESS", "reason": "signal3", "data": "data3"}'
|
|
wc_notify --data-binary '{"status": "SUCCESS", "reason": "signal4", "data": "data4"}'
|
|
|
|
# If you require control of the ID, you can pass it.
|
|
# The ID should be unique, unless you intend for duplicate
|
|
# signals to overrite each other. The following two calls
|
|
# do the exact same thing, and will be treated as one signal
|
|
# (You can prove this by changing count above to 7)
|
|
wc_notify --data-binary '{"status": "SUCCESS", "id": "5"}'
|
|
wc_notify --data-binary '{"status": "SUCCESS", "id": "5"}'
|
|
|
|
# Example of sending a failure signal, optionally
|
|
# reason, id, and data can be specified as above
|
|
# wc_notify --data-binary '{"status": "FAILURE"}'
|
|
params:
|
|
wc_notify: { get_attr: [wait_handle, curl_cli] }
|
|
|
|
outputs:
|
|
wc_data:
|
|
value: { get_attr: [wait_condition, data] }
|
|
# this would return the following json
|
|
# {"1": null, "2": null, "3": "data3", "4": "data4", "5": null}
|
|
|
|
wc_data_4:
|
|
value: { get_attr: [wait_condition, data, '4'] }
|
|
# this would return "data4"</programlisting>
|
|
<!---->
|
|
<para><literal><link xlink:href="http://docs.openstack.org/hot-reference/content/OS__Heat__SwiftSignal.html">OS::Heat::SwiftSignal</link></literal> is implemented by creating an Object Storage
|
|
API temporary URL which is populated with signal data with an HTTP PUT. The
|
|
orchestration service will poll this object until the signal data is available.
|
|
Object versioning is used to store multiple signals.</para>
|
|
<para>Sending the signal is a simple HTTP request, as with this example using <link xlink:href="http://curl.haxx.se/">curl</link>:</para>
|
|
<programlisting language="sh">curl -i -X PUT '<object URL>' --data-binary '<json containing signal data>'</programlisting>
|
|
<para>The above template example only needs to have the <literal>type</literal> changed to the
|
|
swift signal resources:</para>
|
|
<programlisting language="yaml">resources:
|
|
signal:
|
|
type: OS::Heat::SwiftSignal
|
|
properties:
|
|
handle: {get_resource: wait_handle}
|
|
timeout: 300
|
|
|
|
signal_handle:
|
|
type: OS::Heat::SwiftSignalHandle
|
|
# ...</programlisting>
|
|
<para>The decision to use <literal><link xlink:href="http://docs.openstack.org/hot-reference/content/OS__Heat__WaitCondition.html">OS::Heat::WaitCondition</link></literal> or
|
|
<literal><link xlink:href="http://docs.openstack.org/hot-reference/content/OS__Heat__SwiftSignal.html">OS::Heat::SwiftSignal</link></literal> will depend on a few factors:</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal><link xlink:href="http://docs.openstack.org/hot-reference/content/OS__Heat__SwiftSignal.html">OS::Heat::SwiftSignal</link></literal> depends on the availability of an Object
|
|
Storage API</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><literal><link xlink:href="http://docs.openstack.org/hot-reference/content/OS__Heat__WaitCondition.html">OS::Heat::WaitCondition</link></literal> depends on whether the orchestration
|
|
service has been configured with a dedicated stack domain (which may depend
|
|
on the availability of an Identity V3 API).</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>The preference to protect signal URLs with token authentication or a
|
|
secret webhook URL.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
<section xml:id="software-config-resources">
|
|
<title>Software config resources</title>
|
|
<para>Boot configuration scripts can also be managed as their own resources. This
|
|
allows configuration to be defined once and run on multiple server resources.
|
|
These software-config resources are stored and retrieved via dedicated calls
|
|
to the <link xlink:href="http://developer.openstack.org/api-ref-orchestration-v1.html">Orchestration API</link>. It is not possible to modify the contents of an
|
|
existing software-config resource, so a stack-update which changes any
|
|
existing software-config resource will result in API calls to create a new
|
|
config and delete the old one.</para>
|
|
<para>The resource <literal><link xlink:href="http://docs.openstack.org/hot-reference/content/OS__Heat__SoftwareConfig.html">OS::Heat::SoftwareConfig</link></literal> is used for storing configs
|
|
represented by text scripts, for example:</para>
|
|
<programlisting language="yaml">resources:
|
|
boot_script:
|
|
type: OS::Heat::SoftwareConfig
|
|
properties:
|
|
group: ungrouped
|
|
config: |
|
|
#!/bin/bash
|
|
echo "Running boot script"
|
|
# ...
|
|
|
|
server_with_boot_script:
|
|
type: OS::Nova::Server
|
|
properties:
|
|
# flavor, image etc
|
|
user_data_format: RAW
|
|
user_data: {get_resource: boot_script}</programlisting>
|
|
<para>The resource <literal><link xlink:href="http://docs.openstack.org/hot-reference/content/OS__Heat__CloudConfig.html">OS::Heat::CloudConfig</link></literal> allows <link xlink:href="http://cloudinit.readthedocs.org/en/latest/">Cloud-init</link> cloud-config to
|
|
be represented as template YAML rather than a block string. This allows
|
|
intrinsic functions to be included when building the cloud-config. This also
|
|
ensures that the cloud-config is valid YAML, although no further checks for
|
|
valid cloud-config are done.</para>
|
|
<programlisting language="yaml">parameters:
|
|
file_content:
|
|
type: string
|
|
description: The contents of the file /tmp/file
|
|
|
|
resources:
|
|
boot_config:
|
|
type: OS::Heat::CloudConfig
|
|
properties:
|
|
cloud_config:
|
|
write_files:
|
|
- path: /tmp/file
|
|
content: {get_param: file_content}
|
|
|
|
server_with_cloud_config:
|
|
type: OS::Nova::Server
|
|
properties:
|
|
# flavor, image etc
|
|
user_data_format: RAW
|
|
user_data: {get_resource: boot_config}</programlisting>
|
|
<!---->
|
|
<para>The resource <literal><link xlink:href="http://docs.openstack.org/hot-reference/content/OS__Heat__MultipartMime.html">OS::Heat::MultipartMime</link></literal> allows multiple
|
|
<literal><link xlink:href="http://docs.openstack.org/hot-reference/content/OS__Heat__SoftwareConfig.html">OS::Heat::SoftwareConfig</link></literal> and <literal><link xlink:href="http://docs.openstack.org/hot-reference/content/OS__Heat__CloudConfig.html">OS::Heat::CloudConfig</link></literal>
|
|
resources to be combined into a single <link xlink:href="http://cloudinit.readthedocs.org/en/latest/">Cloud-init</link> multi-part message:</para>
|
|
<programlisting language="yaml">parameters:
|
|
file_content:
|
|
type: string
|
|
description: The contents of the file /tmp/file
|
|
|
|
other_config:
|
|
type: string
|
|
description: The ID of a software-config resource created elsewhere
|
|
|
|
resources:
|
|
boot_config:
|
|
type: OS::Heat::CloudConfig
|
|
properties:
|
|
cloud_config:
|
|
write_files:
|
|
- path: /tmp/file
|
|
content: {get_param: file_content}
|
|
|
|
boot_script:
|
|
type: OS::Heat::SoftwareConfig
|
|
properties:
|
|
group: ungrouped
|
|
config: |
|
|
#!/bin/bash
|
|
echo "Running boot script"
|
|
# ...
|
|
|
|
server_init:
|
|
type: OS::Heat::MultipartMime
|
|
properties:
|
|
parts:
|
|
- config: {get_resource: boot_config}
|
|
- config: {get_resource: boot_script}
|
|
- config: {get_resource: other_config}
|
|
|
|
server:
|
|
type: OS::Nova::Server
|
|
properties:
|
|
# flavor, image etc
|
|
user_data_format: RAW
|
|
user_data: {get_resource: server_init}</programlisting>
|
|
<!---->
|
|
</section>
|
|
</section>
|
|
</section>
|