e360c144a4
* removing newlines at start and end * setting/adding correct language * converting from programlistings to screens backport: havana Change-Id: Idceefccf057abe43433a2ddd52743f8b7b960646
380 lines
24 KiB
XML
380 lines
24 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
||
<chapter 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="ch_openstack_images">
|
||
<title>OpenStack Linux image requirements</title>
|
||
<?dbhtml stop-chunking?>
|
||
<para>For a Linux-based image to have full functionality in an OpenStack Compute cloud, there
|
||
are a few requirements. For some of these, the requirement can be fulfilled by installing
|
||
the <link xlink:href="https://cloudinit.readthedocs.org/en/latest/">cloud-init</link>
|
||
package. You should read this section before creating your own image to be sure that the
|
||
image supports the OpenStack features you plan on using.<itemizedlist>
|
||
<listitem>
|
||
<para>Disk partitions and resize root partition on boot (cloud-init)</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>No hard-coded MAC address information</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>SSH server running</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Disable firewall</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Access instance using ssh public key (cloud-init)</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Process user data and other metadata (cloud-init)</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Paravirtualized Xen support in Linux kernel (Xen hypervisor only with Linux
|
||
kernel version < 3.0)</para>
|
||
</listitem>
|
||
</itemizedlist></para>
|
||
<section xml:id="support-resizing">
|
||
<title>Disk partitions and resize root partition on boot (cloud-init)</title>
|
||
<para>When you create a new Linux image, the first decision you will need to make is how to
|
||
partition the disks. The choice of partition method can affect the resizing
|
||
functionality, as described below.</para>
|
||
<para>The size of the disk in a virtual machine image is determined when you initially
|
||
create the image. However, OpenStack lets you launch instances with different size
|
||
drives by specifying different flavors. For example, if your image was created with a 5
|
||
GB disk, and you launch an instance with a flavor of <literal>m1.small</literal>, the
|
||
resulting virtual machine instance will have (by default) a primary disk of 10GB. When
|
||
an instance's disk is resized up, zeros are just added to the end.</para>
|
||
<para>Your image needs to be able to resize its partitions on boot to match the size
|
||
requested by the user. Otherwise, after the instance boots, you will need to manually
|
||
resize the partitions if you want to access the additional storage you have access to
|
||
when the disk size associated with the flavor exceeds the disk size your image was
|
||
created with.</para>
|
||
<simplesect>
|
||
<title>Xen: 1 ext3/ext4 partition (no LVM, no /boot, no swap)</title>
|
||
<para>If you are using the OpenStack XenAPI driver, the Compute service will
|
||
automatically adjust the partition and filesystem for your instance on boot.
|
||
Automatic resize will occur if the following are all true:<itemizedlist>
|
||
<listitem>
|
||
<para><literal>auto_disk_config=True</literal> is
|
||
set as a property on the image in the Image Registry.</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>The disk on the image has only one partition.</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>The file system on the one partition is ext3 or ext4.</para>
|
||
</listitem>
|
||
</itemizedlist></para>
|
||
<para>Therefore, if you are using Xen, we recommend that when you create your images,
|
||
you create a single ext3 or ext4 partition (not managed by LVM). Otherwise, read
|
||
on.</para>
|
||
</simplesect>
|
||
<simplesect>
|
||
<title>Non-Xen with cloud-init/cloud-tools: 1 ext3/ext4 partition (no LVM, no /boot, no
|
||
swap)</title>
|
||
<para>Your image must be configured to deal with two issues:<itemizedlist>
|
||
<listitem>
|
||
<para>The image's partition table describes the original size of the
|
||
image</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>The image's filesystem fills the original size of the image</para>
|
||
</listitem>
|
||
</itemizedlist></para>
|
||
<para>Then, during the boot process:<itemizedlist>
|
||
<listitem>
|
||
<para>the partition table must be modified to be made aware of the
|
||
additional space<itemizedlist>
|
||
<listitem>
|
||
<para>If you are not using LVM, you must modify the table to
|
||
extend the existing root partition to encompass this
|
||
additional space</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>If you are using LVM, you can create add a new LVM entry
|
||
to the partition table, create a new LVM physical volume,
|
||
add it to the volume group, and extend the logical partition
|
||
with the root volume</para>
|
||
</listitem>
|
||
</itemizedlist></para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>the root volume filesystem must be resized</para>
|
||
</listitem>
|
||
</itemizedlist></para>
|
||
<para>The simplest way to support this in your image is to install the <link
|
||
xlink:href="https://launchpad.net/cloud-utils">cloud-utils</link> package
|
||
(contains the <command>growpart</command> tool for extending partitions), the <link
|
||
xlink:href="https://launchpad.net/cloud-initramfs-tools"
|
||
>cloud-initramfs-tools</link> package (which will support resizing root
|
||
partition on the first boot), and the <link
|
||
xlink:href="https://launchpad.net/cloud-init">cloud-init</link> package into
|
||
your image. With these installed, the image will perform the root partition resize
|
||
on boot (for example in <filename>/etc/rc.local</filename>). These packages are in the
|
||
Ubuntu and Debian package repository, as well as the EPEL repository (for
|
||
Fedora/RHEL/CentOS/Scientific Linux guests).</para>
|
||
<para>If you are not able to install <literal>cloud-initramfs-tools</literal>, Robert
|
||
Plestenjak has a github project called <link
|
||
xlink:href="https://github.com/flegmatik/centos-image-resize"
|
||
>centos-image-resize</link> that contains scripts that will update a ramdisk
|
||
using <command>growpart</command> so that the image will resize properly on
|
||
boot.</para>
|
||
<para>If you are able to install the cloud-utils and cloud-init packages, we recommend
|
||
that when you create your images, you create a single ext3 or ext4 partition (not
|
||
managed by LVM).</para>
|
||
</simplesect>
|
||
<simplesect>
|
||
<title>Non-Xen without cloud-init/cloud-tools: LVM</title>
|
||
<para>If you cannot install cloud-init and cloud-tools inside of your guest, and you
|
||
want to support resize, you will need to write a script that your image will run on
|
||
boot to modify the partition table. In this case, we recommend using LVM to manage
|
||
your partitions. Due to a limitation in the Linux kernel (as of this writing), you
|
||
cannot modify a partition table of a raw disk that has partition currently mounted,
|
||
but you can do this for LVM.</para>
|
||
<para>Your script will need to do something like the following:<orderedlist>
|
||
<listitem>
|
||
<para>Detect if there is any additional space on the disk (e.g., parsing
|
||
output of <command>parted /dev/sda --script "print
|
||
free"</command>)</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Create a new LVM partition with the additional space (e.g.,
|
||
<command>parted /dev/sda --script "mkpart lvm ..."</command>)</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Create a new physical volume (e.g., <command>pvcreate
|
||
/dev/<replaceable>sda6</replaceable></command> )</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Extend the volume group with this physical partition (e.g.,
|
||
<command>vgextend <replaceable>vg00</replaceable>
|
||
/dev/<replaceable>sda6</replaceable></command>)</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Extend the logical volume contained the root partition by the amount
|
||
of space (e.g., <command>lvextend
|
||
/dev/mapper/<replaceable>node-root</replaceable>
|
||
/dev/<replaceable>sda6</replaceable></command>)</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Resize the root file system (e.g., <command>resize2fs
|
||
/dev/mapper/<replaceable>node-root</replaceable></command>).</para>
|
||
</listitem>
|
||
</orderedlist></para>
|
||
<para>You do not need to have a <filename>/boot</filename> partition, unless your image
|
||
is an older Linux distribution that requires that <filename>/boot</filename> is not
|
||
managed by LVM. You may elect to use a swap per</para>
|
||
</simplesect>
|
||
</section>
|
||
<section xml:id="mac-adddress"><title>No hard-coded MAC address information</title>
|
||
<para>You must remove the network persistence rules in the image as their presence will
|
||
result in the network interface in the instance coming up as an interface other than
|
||
eth0. This is because your image has a record of the MAC address of the network
|
||
interface card when it was first installed, and this MAC address will be different each
|
||
time the instance boots up. You should alter the following files:<itemizedlist>
|
||
<listitem>
|
||
<para>Replace <filename>/etc/udev/rules.d/70-persistent-net.rules</filename>
|
||
with an empty file (contains network persistence rules, including MAC
|
||
address)</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Replace
|
||
<filename>/lib/udev/rules.d/75-persistent-net-generator.rules</filename>
|
||
with an empty file (this generates the file above)</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Remove the HWADDR line from
|
||
<filename>/etc/sysconfig/network-scripts/ifcfg-eth0</filename> on
|
||
Fedora-based images</para>
|
||
</listitem>
|
||
</itemizedlist><note>
|
||
<para>If you delete the network persistent rules files, you may get a udev kernel
|
||
warning at boot time, which is why we recommend replacing them with empty files
|
||
instead.</para>
|
||
</note></para>
|
||
|
||
</section>
|
||
<section xml:id="ensure-ssh-server">
|
||
<title>Ensure ssh server runs</title>
|
||
<para>You must install an ssh server into the image and ensure that it starts up on boot, or
|
||
you will not be able to connect to your instance using ssh when it boots inside of
|
||
OpenStack. This package is typically called <literal>openssh-server</literal>.</para>
|
||
</section>
|
||
|
||
<section xml:id="disable-firewall">
|
||
<title>Disable firewall</title>
|
||
<para>In general, we recommend that you disable any firewalls inside of your image and use
|
||
OpenStack security groups to restrict access to instances. The reason is that having a
|
||
firewall installed on your instance can make it more difficult to troubleshoot
|
||
networking issues if you cannot connect to your instance.</para>
|
||
</section>
|
||
<section xml:id="ssh-public-key">
|
||
<title>Access instance using ssh public key (cloud-init)</title>
|
||
<para>The typical way that users access virtual machines running on OpenStack is to ssh
|
||
using public key authentication. For this to work, your virtual machine image must be
|
||
configured to download the ssh public key from the OpenStack metadata service or config
|
||
drive, at boot time.</para>
|
||
<simplesect>
|
||
<title>Using cloud-init to fetch the public key</title>
|
||
<para>The cloud-init package will automatically fetch the public key from the metadata
|
||
server and place the key in an account. The account varies by distribution. On
|
||
Ubuntu-based virtual machines, the account is called "ubuntu". On Fedora-based
|
||
virtual machines, the account is called "ec2-user".</para>
|
||
<para>You can change the name of the account used by
|
||
cloud-init by editing the
|
||
<filename>/etc/cloud/cloud.cfg</filename> file and
|
||
adding a line with a different user. For example, to
|
||
configure cloud-init to put the key in an account
|
||
named "admin", edit the config file so it has the
|
||
line:<programlisting>user: admin</programlisting></para>
|
||
</simplesect>
|
||
<simplesect>
|
||
<title>Writing a custom script to fetch the public key</title>
|
||
<para>If you are unable or unwilling to install cloud-init inside the guest, you can
|
||
write a custom script to fetch the public and add it to a user account.</para>
|
||
<para>To fetch the ssh public key and add it to the root account, edit the
|
||
<filename>/etc/rc.local</filename> file and add the following lines before the
|
||
line “touch /var/lock/subsys/local”. This code fragment is taken from the <link
|
||
xlink:href="https://github.com/rackerjoe/oz-image-build/blob/master/templates/centos60_x86_64.tdl"
|
||
>rackerjoe oz-image-build CentOS 6 template</link>.</para>
|
||
<programlisting language="bash">if [ ! -d /root/.ssh ]; then
|
||
mkdir -p /root/.ssh
|
||
chmod 700 /root/.ssh
|
||
fi
|
||
|
||
# Fetch public key using HTTP
|
||
ATTEMPTS=30
|
||
FAILED=0subl
|
||
while [ ! -f /root/.ssh/authorized_keys ]; do
|
||
curl -f http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key > /tmp/metadata-key 2>/dev/null
|
||
if [ \$? -eq 0 ]; then
|
||
cat /tmp/metadata-key >> /root/.ssh/authorized_keys
|
||
chmod 0600 /root/.ssh/authorized_keys
|
||
restorecon /root/.ssh/authorized_keys
|
||
rm -f /tmp/metadata-key
|
||
echo "Successfully retrieved public key from instance metadata"
|
||
echo "*****************"
|
||
echo "AUTHORIZED KEYS"
|
||
echo "*****************"
|
||
cat /root/.ssh/authorized_keys
|
||
echo "*****************"
|
||
done</programlisting>
|
||
<note>
|
||
<para>Some VNC clients replace : (colon) with ; (semicolon) and _ (underscore) with
|
||
- (hyphen). If editing a file over a VNC session, make sure it's http: not http;
|
||
and authorized_keys not authorized-keys.</para>
|
||
</note>
|
||
|
||
|
||
</simplesect>
|
||
|
||
</section>
|
||
<section xml:id="metadata">
|
||
<title>Process user data and other metadata (cloud-init)</title>
|
||
<para>In additional the ssh public key, an image may need to retrieve additional information
|
||
from OpenStack, such as <link
|
||
xlink:href="http://docs.openstack.org/user-guide/content/user-data.html"
|
||
>user data</link> that the user submitted when requesting the image. For example,
|
||
you may wish to set the host name of the instance to name given to the instance when it
|
||
is booted. Or, you may wish to configure your image so that it executes user data
|
||
content as a script on boot.</para>
|
||
<para>This information is accessible via the metadata service or the <link
|
||
xlink:href="http://docs.openstack.org/user-guide/content/config-drive.html"
|
||
>config drive</link>. As the OpenStack metadata service is compatible with version
|
||
2009-04-04 of the Amazon EC2 metadata service, consult the Amazon EC2 documentation on
|
||
<link
|
||
xlink:href="http://docs.amazonwebservices.com/AWSEC2/2009-04-04/UserGuide/AESDG-chapter-instancedata.html"
|
||
>Using Instance Metadata</link> for details on how to retrieve user data.</para>
|
||
|
||
<para>The easiest way to support this type of functionality is to install the
|
||
cloud-init package into your image, which is configured by default to treat user data as
|
||
an executable script, and will set the host name.</para>
|
||
</section>
|
||
<section xml:id="write-to-console">
|
||
<title>Ensure image writes boot log to console</title>
|
||
<para>You must configure the image so that the kernel writes the boot log to the
|
||
<literal>ttyS0</literal> device. In particular, the <literal>console=ttyS0</literal>
|
||
argument must be passed to the kernel on boot.</para>
|
||
<para>If your image uses grub2 as the boot loader, there should be a line in the grub
|
||
configuration file (for example, <filename>/boot/grub/grub.cfg</filename>) that looks
|
||
something like
|
||
this:<programlisting>linux /boot/vmlinuz-3.2.0-49-virtual root=UUID=6d2231e4-0975-4f35-a94f-56738c1a8150 ro console=ttyS0</programlisting></para>
|
||
<para>If <literal>console=ttyS0</literal> does not appear, you will need to modify your grub
|
||
configuration. In general, you should not update the grub.cfg directly, since it is
|
||
automatically generated. Instead, you should edit <filename>/etc/default/grub</filename>
|
||
and modify the value of the <literal>GRUB_CMDLINE_LINUX_DEFAULT</literal> variable:
|
||
<programlisting language="bash">GRUB_CMDLINE_LINUX_DEFAULT="console=ttyS0"</programlisting></para>
|
||
<para>Next, update the grub configuration. On Debian-based operating-systems such as Ubuntu,
|
||
do:<screen><prompt>$</prompt> <userinput>sudo update-grub</userinput></screen></para>
|
||
<para>On Fedora-based systems such as RHEL and CentOS,
|
||
do:<screen><prompt>$</prompt> <userinput>sudo grub2-mkconfig -o /boot/grub2/grub.cfg</userinput></screen></para>
|
||
</section>
|
||
|
||
<section xml:id="image-xen-pv"><title>Paravirtualized Xen support in the kernel (Xen hypervisor only)</title>
|
||
<para>Prior to Linux kernel version 3.0, the mainline branch of the Linux kernel did not
|
||
have support paravirtualized Xen virtual machine instances (what Xen calls DomU guests).
|
||
If you are running the Xen hypervisor with paravirtualization, and you want to create an
|
||
image for an older Linux distribution that has a pre 3.0 kernel, you will need to ensure
|
||
that the image boots a kernel that has been compiled with Xen support.</para>
|
||
</section>
|
||
<section xml:id="image-cache-management">
|
||
<title>Managing the image cache</title>
|
||
<para>Use options in <filename>nova.conf</filename> to control whether, and for how long,
|
||
unused base images are stored in <filename>/var/lib/nova/instances/_base/</filename>. If
|
||
you have configured live migration of instances, all your compute nodes share one common
|
||
<filename>/var/lib/nova/instances/</filename> directory.</para>
|
||
<para>For information about libvirt images in OpenStack, refer to <link xlink:href="http://www.pixelbeat.org/docs/openstack_libvirt_images/">The life of an OpenStack libvirt image from Pádraig Brady</link>.</para>
|
||
<table rules="all">
|
||
<caption>Image cache management configuration options</caption>
|
||
<col width="50%"/>
|
||
<col width="50%"/>
|
||
<thead>
|
||
<tr>
|
||
<td>Configuration option=Default value</td>
|
||
<td>(Type) Description</td>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>preallocate_images=none</td>
|
||
<td>(StrOpt) VM image preallocation mode: "none" => no storage provisioning
|
||
is done up front, "space" => storage is fully allocated at instance
|
||
start. If this is set to 'space', the $instance_dir/ images will be <link
|
||
xlink:href="http://www.kernel.org/doc/man-pages/online/pages/man2/fallocate.2.html"
|
||
>fallocate</link>d to immediately determine if enough space is
|
||
available, and to possibly improve VM I/O performance due to ongoing
|
||
allocation avoidance, and better locality of block allocations.</td>
|
||
</tr>
|
||
<tr>
|
||
<td>remove_unused_base_images=True</td>
|
||
<td>(BoolOpt) Should unused base images be removed? When set to True, the
|
||
interval at which base images are removed are set with the following two
|
||
settings. If set to False base images are never removed by Compute.</td>
|
||
</tr>
|
||
<tr>
|
||
<td>remove_unused_original_minimum_age_seconds=86400</td>
|
||
<td>(IntOpt) Unused unresized base images younger than this will not be removed. Default is 86400 seconds, or 24 hours.</td>
|
||
</tr>
|
||
<tr>
|
||
<td>remove_unused_resized_minimum_age_seconds=3600</td>
|
||
<td>(IntOpt) Unused resized base images younger than this will not be removed. Default is 3600 seconds, or one hour.</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<para>To see how the settings affect the deletion of a running instance, check the directory where the images are stored:</para>
|
||
<screen><prompt>$</prompt> <userinput>sudo ls -lash /var/lib/nova/instances/_base/</userinput></screen>
|
||
<para>Then look for the identifier in
|
||
<filename>/var/log/compute/compute.log</filename>:</para>
|
||
<screen><computeroutput>2012-02-18 04:24:17 41389 WARNING nova.virt.libvirt.imagecache [-] Unknown base file: /var/lib/nova/instances/_base/06a057b9c7b0b27e3b496f53d1e88810
|
||
a0d1d5d3_20
|
||
2012-02-18 04:24:17 41389 INFO nova.virt.libvirt.imagecache [-] Removable base files: /var/lib/nova/instances/_base/06a057b9c7b0b27e3b496f53d1e88810
|
||
a0d1d5d3 /var/lib/nova/instances/_base/06a057b9c7b0b27e3b496f53d1e88810a0d1d5d3_20
|
||
2012-02-18 04:24:17 41389 INFO nova.virt.libvirt.imagecache [-] Removing base file: /var/lib/nova/instances/_base/06a057b9c7b0b27e3b496f53d1e88810a0d1d5d3</computeroutput></screen>
|
||
<para>Since 86400 seconds (24 hours) is the default time for
|
||
<literal>remove_unused_original_minimum_age_seconds</literal>, you can either wait
|
||
for that time interval to see the base image removed, or set the value to a shorter time
|
||
period in <filename>nova.conf</filename>. Restart all nova services after changing a
|
||
setting in <filename>nova.conf</filename>.</para>
|
||
</section>
|
||
</chapter>
|