# Track2Agenda: ex-lvm-scripted-install.htm

File ex-lvm-scripted-install.htm, 37.1 KB (added by trac, 4 years ago)
Line
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2<html xmlns="http://www.w3.org/1999/xhtml">
4  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5  <meta http-equiv="Content-Style-Type" content="text/css" />
6  <meta name="generator" content="pandoc" />
7  <title>VM image management: LVM and scripted installs</title>
8  <style type="text/css">code{white-space: pre;}</style>
11<body>
13<h1 class="title">VM image management: LVM and scripted installs</h1>
14</div>
15<div id="TOC">
16<ul>
17<li><a href="#lvm"><span class="toc-section-number">1</span> LVM</a></li>
18<li><a href="#scripted-installs"><span class="toc-section-number">2</span> Scripted installs</a><ul>
19<li><a href="#install-grml-debootstrap"><span class="toc-section-number">2.1</span> Install grml-debootstrap</a></li>
20</ul></li>
21<li><a href="#build-an-image-in-a-logical-volume"><span class="toc-section-number">3</span> Build an image in a logical volume</a><ul>
22<li><a href="#examine-the-image"><span class="toc-section-number">3.1</span> Examine the image</a></li>
23<li><a href="#booting-the-image"><span class="toc-section-number">3.2</span> Booting the image</a></li>
24</ul></li>
25<li><a href="#build-a-vm-image-file"><span class="toc-section-number">4</span> Build a VM image file</a><ul>
26<li><a href="#check-the-image"><span class="toc-section-number">4.1</span> Check the image</a></li>
27<li><a href="#convert-the-image"><span class="toc-section-number">4.2</span> Convert the image</a></li>
28<li><a href="#start-a-vm"><span class="toc-section-number">4.3</span> Start a VM</a></li>
29</ul></li>
30<li><a href="#optional-exercises"><span class="toc-section-number">5</span> Optional exercises</a><ul>
31<li><a href="#cloning-virtual-machines"><span class="toc-section-number">5.1</span> Cloning virtual machines</a><ul>
32<li><a href="#duplicate-the-image-file"><span class="toc-section-number">5.1.1</span> Duplicate the image file</a></li>
33<li><a href="#create-a-new-vm-definition"><span class="toc-section-number">5.1.2</span> Create a new VM definition</a></li>
34<li><a href="#patch-up-the-vm"><span class="toc-section-number">5.1.3</span> Patch up the VM</a></li>
35</ul></li>
37</ul></li>
38</ul>
39</div>
40<p>Objectives:</p>
41<ul>
42<li>use LVM commands to create and manage logical volumes</li>
43<li>perform a scripted install for a fully-automatic OS installation</li>
44</ul>
45<p>All of the actions in this exercise are done as &quot;root&quot;, so if you are not root already type:</p>
46<pre><code>$sudo -s 47#</code></pre> 48<h1 id="lvm"><a href="#lvm"><span class="header-section-number">1</span> LVM</a></h1> 49<p>First, try each of the following commands to list the logical volumes you have:</p> 50<pre><code># lvscan 51# lvs 52# lvdisplay</code></pre> 53<p>Compare the output - it has differing levels of detail but should show the same logical volumes.</p> 54<p>Have a look at the device nodes:</p> 55<pre><code># ls -l /dev/mapper 56# ls -l /dev/ganeti</code></pre> 57<p>Now create a new logical volume called &quot;foo&quot; (or some other name you choose) inside the &quot;ganeti&quot; volume group:</p> 58<pre><code># lvcreate --size 1G --name foo ganeti</code></pre> 59<p>Use these commands to check that the device node exists, and to see the size of the block device you have created:</p> 60<pre><code># ls -l /dev/ganeti 61# blockdev --getsize64 /dev/ganeti/foo</code></pre> 62<p>Now we can create a filesystem within it, and mount it. MAKE SURE YOU DO THESE OPERATIONS ON THE CORRECT DEVICE NODE - if you write to your root, var or swap volumes you will break your system!</p> 63<pre><code># mkfs.ext4 /dev/ganeti/foo 64# mkdir /opt # if /opt already exists, ignore the error 65# mount /dev/ganeti/foo /opt 66# df -h /opt</code></pre> 67<p>You should now be able to create files in /opt if you wish, and they will be stored in this logical volume.</p> 68<p>Now let's grow the filesystem. This requires two steps: firstly add some extents to the logical volume.</p> 69<pre><code># lvextend --size +1G /dev/ganeti/foo 70# blockdev --getsize64 /dev/ganeti/foo 71# df -h /opt</code></pre> 72<p>You'll see that although the logical volume is bigger, the filesystem is still the same size. You need to resize the filesystem to fill the larger space available. Fortunately, with ext4 you can do this even while the filesystem is mounted:</p> 73<pre><code># resize2fs /dev/ganeti/foo 74# df -h /opt</code></pre> 75<p>Now let's undo everything. Unmount the filesystem and delete the logical volume.</p> 76<pre><code># umount /opt 77# lvremove /dev/ganeti/foo 78# lvscan</code></pre> 79<p>As you can see, creating and destroying logical volumes is a straightforward process. There is plenty of additional LVM documentation online that you can read.</p> 80<p>From the point of view of a virtual machine, a logical volume behaves much like a raw disk image file, but avoids the overhead of going through the host filesystem.</p> 81<h1 id="scripted-installs"><a href="#scripted-installs"><span class="header-section-number">2</span> Scripted installs</a></h1> 82<p>Scripted installs can be used to automate the creation of new VM images, and avoid most of the interactive questions asked during a CD install.</p> 83<p>Under Ubuntu, the tool &quot;python-vm-builder&quot; can be used for this; under Debian the equivalent tool is &quot;grml-debootstrap&quot;, and this is what you will use in this exercise.</p> 84<h2 id="install-grml-debootstrap"><a href="#install-grml-debootstrap"><span class="header-section-number">2.1</span> Install grml-debootstrap</a></h2> 85<pre><code># apt-get install grml-debootstrap</code></pre> 86<p>The configuration settings are available by reading <code>man grml-debootstrap</code> and by looking in the file <code>/etc/debootstrap/config</code></p> 87<h1 id="build-an-image-in-a-logical-volume"><a href="#build-an-image-in-a-logical-volume"><span class="header-section-number">3</span> Build an image in a logical volume</a></h1> 88<p>Since you now know how to create logical volumes, you will create one for this image.</p> 89<pre><code># lvcreate --size 4G --name debian1 ganeti 90# grml-debootstrap --target /dev/ganeti/debian1 --hostname debian1 -v \ 91 --mirror http://apt.ws.nsrc.org:3142/cdn.debian.net/debian</code></pre> 92<p>You will be asked to confirm the settings. If it looks ok, answer <code>y</code>.</p> 93<p>This will take a few minutes. You will see it installing the packages into the filesystem. After the initial confirmation to proceed, the only questions you are asked are to set a root password.</p> 94<p>Once finished, you should see:</p> 95<pre><code> * Finished execution of grml-debootstrap. Enjoy your Debian system.</code></pre> 96<h2 id="examine-the-image"><a href="#examine-the-image"><span class="header-section-number">3.1</span> Examine the image</a></h2> 97<p>When built this way, the logical volume contains a single filesystem (with no partition table), and it is easy to mount and examine, which is very useful.</p> 98<pre><code># mount /dev/ganeti/debian1 /mnt 99# ls /mnt</code></pre> 100<p>Let's make a small change to the filesystem: we will enable the serial console. For a Debian image it's done like this:</p> 101<pre><code># vi /mnt/etc/inittab 102 103---- Uncomment this line (remove the '#' in front of it) ---- 104T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100</code></pre> 105<p>Save the change. Finally, unmount the fileystem:</p> 106<pre><code># umount /mnt</code></pre> 107<p>NOTE: to avoid filesystem corruption, it's VERY IMPORTANT that the same block device is not mounted in two places at once. So NEVER mount a volume like this while it is attached to a running VM; and always remember to unmount it before you start a VM which uses it.</p> 108<h2 id="booting-the-image"><a href="#booting-the-image"><span class="header-section-number">3.2</span> Booting the image</a></h2> 109<p>Now we want to boot the image as a VM.</p> 110<p>However there is a problem. Because this image is a straight filesystem, without a partition table, it does not contain a Master Boot Record (MBR) and doesn't have the GRUB boot loader. So it won't boot in the way a normal PC does.</p> 111<p>What we can do instead is to pass KVM two files (a kernel and init ramdisk) stored on the host. We will use the same kernel and initrd as is used to boot the Debian host you have built.</p> 112<p>Rather than write the libvirt XML for this all by hand, you could use the virt-manager GUI, but this time you will use the command line tool &quot;virt-install&quot; to create the machine. You pass a number of parameters telling it the parameters of the machine to build.</p> 113<blockquote> 114<p>Hint: if you are inside the X11 graphical environment then it's better to run this as a regular user, not root, so that it can open the graphical console window for you.</p> 115</blockquote> 116<pre><code>$ virt-install --name debian1 --ram 512 \
118  --import --disk /dev/ganeti/debian1 --network=bridge:br-lan \
119  --boot kernel=/vmlinuz,initrd=/initrd.img,kernel_args=&quot;root=/dev/sda&quot;</code></pre>
120<blockquote>
121<p>Hint: If you don't get a console, use your laptop's VNC client to connect. <code>virsh vncdisplay debian1</code> will show you which VNC screen to connect to.</p>
122</blockquote>
123<p><code>kernel_args=&quot;root=/dev/sda&quot;</code> tells the kernel which device to mount as its root filesystem.</p>
124<p>You should now have a running VM using the image you built. If not, ask for help. Remember to do some basic debugging first:</p>
125<pre><code># virsh list
126# virsh dumpxml debian1
127# virsh console debian1</code></pre>
128<h1 id="build-a-vm-image-file"><a href="#build-a-vm-image-file"><span class="header-section-number">4</span> Build a VM image file</a></h1>
129<p><code>grml-debootstrap</code> can also be used to create a familiar disk image file, containing an MBR and a partition table, so it can be booted directly.</p>
130<pre><code># grml-debootstrap --vmfile --target /var/lib/libvirt/images/debian2.img \
131    --hostname debian2 -v \
132    --mirror http://apt.ws.nsrc.org:3142/cdn.debian.net/debian</code></pre>
133<p>This will take a few minutes. It builds a raw image, default size 2GB. If you watch carefuly, you will see messages about devices like <code>/dev/mapper/loop0p1</code>, which should become clearer in the next section.</p>
134<h2 id="check-the-image"><a href="#check-the-image"><span class="header-section-number">4.1</span> Check the image</a></h2>
135<p>First, notice that this file is &quot;sparse&quot; - the host operating system has only allocated space for blocks which have been written to. You can see this by comparing the size of the file with the disk space allocated to the file.</p>
136<pre><code># ls -lh /var/lib/libvirt/images/debian2.img      # size of file = 2GB
137# ls -sh /var/lib/libvirt/images/debian2.img      # space used &lt; 2GB
138# du -h /var/lib/libvirt/images/debian2.img       # another way to get the same info</code></pre>
139<p>It would be very useful if we could look inside this file to see its contents. The &quot;loop&quot; device lets us attach a file as if it were a block device. However it's slightly awkward because the image is not just a filesystem - it's an image of a disk containing a partition table <em>and</em> a filesystem, which is offset from the beginning of the disk.</p>
140<p>Try running the <code>file</code> command on the <code>debian2.img</code> file:</p>
141<pre><code># file /var/lib/libvirt/images/debian2.img
142
143/var/lib/libvirt/images/debian2.img: x86 boot sector; partition 1: ID=0x83, starthead 0, startsector 4096, 4190208 sectors, code offset 0x31</code></pre>
144<p>The 'kpartx' utility is able to set up separate loopback devices for each partition contained within the image:</p>
145<pre><code># kpartx -av /var/lib/libvirt/images/debian2.img
146# ls /dev/mapper/loop*</code></pre>
147<p>You should now see you have a device <code>/dev/mapper/loop0p1</code> which is a block device to access the data in partition 1 of the image, and now you can mount the filesystem and look inside:</p>
148<pre><code># mount /dev/mapper/loop0p1 /mnt
149# ls /mnt
150... do whatever you need inside the /mnt directory</code></pre>
151<p><em>IMPORTANT!!</em> As before, once you have finished using the mount, it's vital to unmount it and deconfigure the loopback device - otherwise you risk corruption if you start running a VM on this image at the same time as the host system has it mounted.</p>
152<pre><code># umount /mnt
153# kpartx -d /var/lib/libvirt/images/debian2.img</code></pre>
154<p>We will discuss loopback devices and the associated tools (<code>losetup</code>) in class, as well as the difference between the image we created using LVM initially (debian1) and the second image created as a file (debian2).</p>
155<h2 id="convert-the-image"><a href="#convert-the-image"><span class="header-section-number">4.2</span> Convert the image</a></h2>
156<p>If you want the image in a different format, e.g. qcow2, then use <code>qemu-img convert</code> to convert it. This will take a little while as it has to read and rewrite the entire image.</p>
157<pre><code># qemu-img convert -f raw -O qcow2 /var/lib/libvirt/images/debian2.img /var/lib/libvirt/images/debian2.qcow2</code></pre>
158<p>qemu-img is part of the <code>qemu-utils</code> package.</p>
159<p>Once it is finished, compare the file size:</p>
160<pre><code># du -sh debian2.*</code></pre>
161<p>qcow2 images can be mounted in a different way, using qemu-nbd (network block device):</p>
162<pre><code># modprobe nbd max_part=4
163# qemu-nbd -c /dev/nbd0 /var/lib/libvirt/images/debian2.qcow2
164# mount /dev/nbd0p1 /mnt
165# ls /mnt
166... do work here
167# umount /mnt
168# qemu-nbd -d /dev/nbd0</code></pre>
169<h2 id="start-a-vm"><a href="#start-a-vm"><span class="header-section-number">4.3</span> Start a VM</a></h2>
170<p>Finally, to boot this as a VM using libvirt, you need to create a VM inside libvirt and attach the image. Again, you will use virt-install to set this up.</p>
171<pre><code>\$ virt-install --name debian2 --ram 512 \
173  --import --disk /var/lib/libvirt/images/debian2.qcow2,format=qcow2 \
174  --network=bridge:br-lan</code></pre>
175<p>This time there is no need to provide any kernel, because it boots using GRUB and the kernel within the filesystem. However the existence of the partition table makes this sort of image much harder to grow.</p>
176<h1 id="optional-exercises"><a href="#optional-exercises"><span class="header-section-number">5</span> Optional exercises</a></h1>
177<h2 id="cloning-virtual-machines"><a href="#cloning-virtual-machines"><span class="header-section-number">5.1</span> Cloning virtual machines</a></h2>
178<p>Another approach to creating VMs is to clone one you have already installed. This can be much faster than doing an installation from scratch, but some work may be needed to update the clone before it can be used.</p>
179<p>You need to duplicate the disk image or logical volume, create a new VM definition, start it, and then patch up the new VM.</p>
180<h3 id="duplicate-the-image-file"><a href="#duplicate-the-image-file"><span class="header-section-number">5.1.1</span> Duplicate the image file</a></h3>
181<p>This part is easy! Let's say you have a VM backed by &quot;debian2.qcow2&quot;, and we want to create &quot;debian3.qcow2&quot;</p>
182<pre><code># cd /var/lib/libvirt/images
183# cp debian2.qcow2 debian3.qcow2</code></pre>
184<h3 id="create-a-new-vm-definition"><a href="#create-a-new-vm-definition"><span class="header-section-number">5.1.2</span> Create a new VM definition</a></h3>
185<p>We will take the libvirt XML definition of debian2, and make some minimal changes to make a machine called debian3 with the same parameters.</p>
186<pre><code># virsh dumpxml debian2 &gt;debian3.xml
187# vi debian3.xml
188
189-- CHANGE the name
190&lt;name&gt;debian3&lt;/name&gt;
191
192-- DELETE the &lt;uuid&gt;...&lt;/uuid&gt; line
193
194-- CHANGE the source file line
195&lt;source file='/var/lib/libvirt/images/debian3.qcow2'/&gt;
196
197-- DELETE the &lt;mac address='52:54:xx:xx:xx:xx'/&gt; line</code></pre>
198<p>Now define the new VM from this file (the missing UUID and MAC address should be assigned automatically).</p>
199<pre><code># virsh define debian3.xml</code></pre>
200<p>If that gives no error, then start your new VM:</p>
201<pre><code># virsh start debian3</code></pre>
202<h3 id="patch-up-the-vm"><a href="#patch-up-the-vm"><span class="header-section-number">5.1.3</span> Patch up the VM</a></h3>
203<p>Get a console onto your new VM, and you'll find there are some changes you need to make.</p>
204<p>Firstly, this host still thinks its name is &quot;debian2&quot;. So you need to edit <code>/etc/hostname</code>, <code>/etc/hosts</code>, <code>/etc/mailname</code> and maybe others.</p>
205<p>Secondly, this host may still be configured with the IP address of debian2. In our case we're using DHCP so it's not a problem, but with static addressing you would have to be very careful to avoid conflicts.</p>
206<p>Thirdly, this host may still remember the MAC address which used to be on <code>eth0</code>, and so call its primary interface something else (like eth1), because it doesn't recognize the MAC address assigned when we did a virsh define - and thinkg it's a new interface.</p>
207<p>If the VM is Ubuntu, check <code>/etc/udev/rules.d/70-persistent-net.rules</code>. If it is CentOS, check for MAC addresses in <code>/etc/sysconfig/network-scripts/ifcfg-eth*</code></p>
208<p>For operating systems like Windows, there may be other things to do such as changing the machine ID in the registry. We do not have time in this workshop to go into details.</p>