d871edc2c6
removed: to name given to the instance changed sentence - additional to addition, (in addition) added key after public Change-Id: I5cb22fece1e868503bda35c4f1da1d43ea64c4ee
506 lines
26 KiB
XML
506 lines
26 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 has, by default,
|
||
a primary disk size of 10 GB. 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 the
|
||
<filename>/etc/rc.local</filename> file. 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/linux-rootfs-resize"
|
||
>linux-rootfs-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 any additional space is
|
||
available on the disk. For example, parse
|
||
the output of <command>parted /dev/sda
|
||
--script "print
|
||
free"</command>.</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Create a new LVM partition with the
|
||
additional space. For example,
|
||
<command>parted /dev/sda --script
|
||
"mkpart lvm ..."</command>.</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Create a new physical volume. For
|
||
example, <command>pvcreate
|
||
/dev/<replaceable>sda6</replaceable></command>.</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Extend the volume group with this
|
||
physical partition. For example,
|
||
<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. For
|
||
example, <command>lvextend
|
||
/dev/mapper/<replaceable>node-root</replaceable>
|
||
/dev/<replaceable>sda6</replaceable></command>.</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Resize the root file system. For
|
||
example, <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>Use 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 <literal>admin</literal>, edit the configuration
|
||
file so it has the line:</para>
|
||
<programlisting>user: admin</programlisting>
|
||
</simplesect>
|
||
<simplesect>
|
||
<title>Write 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 key 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=0
|
||
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 "*****************"
|
||
else
|
||
FAILED=`expr $FAILED + 1`
|
||
if [ $FAILED -ge $ATTEMPTS ]; then
|
||
echo "Failed to retrieve public key from instance metadata after $FAILED attempts, quitting"
|
||
break
|
||
fi
|
||
echo "Could not retrieve public key from instance metadata (attempt #$FAILED/$ATTEMPTS), retrying in 5 seconds..."
|
||
sleep 5
|
||
fi
|
||
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 addition to 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 might want to set the
|
||
host name of the instance when it is booted. Or, you might
|
||
wish to configure your image so that it executes user data
|
||
content as a script on boot.</para>
|
||
<para>This information is accessible through 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>, which
|
||
looks something like this:</para>
|
||
<programlisting>linux /boot/vmlinuz-3.2.0-49-virtual root=UUID=6d2231e4-0975-4f35-a94f-56738c1a8150 ro console=ttyS0</programlisting>
|
||
<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>Manage 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>
|