openstack-manuals/doc/image-guide/ch_openstack_images.xml

381 lines
24 KiB
XML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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 &lt; 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" =&gt; no storage provisioning
is done up front, "space" =&gt; 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>