Saturday, 25 February 2012

Building Centos 6 KVM Virtual Host via Standalone Puppet

This is a sample quick install that I did to create a KVM VM Host Centos 6.2 physical machine and one Guest VM bridged on physical network. I normally don't like to use puppetmaster or run puppet automatically as daemon. Therefore, puppet configs are shared via NFS. You would possibly like to review and change bits to fit your needs. The Host is using 192.168.0.40 as IP and the Guest is 192.168.0.41. This installation is ideal if you have a server in a data center and would like to use it to its max by having multiple VMs inside. One architecture which I would recommend is to use the Host as Apache ProxyPass to VMs. For extra security you may use private NATed IPs for Guests. This way you will need only a single public IP on Host, exposing all backend web or application VM servers and possibly even load-balancing them. I used http://blog.mattbrock.co.uk/2012/02/12/virtualisation-with-kvm-and-lvm-on-centos-6-via-the-command-line/ as a reference to do this. Therefore, I highly recommend to read it first. It has nice hints for managing the VMs. Once you did the first Guest VM installed, you may clone it to create more.

1- For VM Host, do basic server install. Following is partial ks file. Nothing interesting here. Just remember to create a Physical Volume to host VMs. It gives better performance compared to flat file system.

part / --fstype=ext4 --onpart=sda1
part swap --onpart=sda2
part pv.008003 --onpart=sda3

repo --name="CentOS"  --baseurl=cdrom:sr1 --cost=100

%packages
@base
@client-mgmt-tools
@console-internet
@core
@debugging
@directory-client
@hardware-monitoring
@java-platform
@large-systems
@network-file-system-client
@performance
@perl-runtime
@server-platform
@server-policy
pax
oddjob
sgpio
certmonger
pam_krb5
krb5-workstation
perl-DBD-SQLite
%end

2- Install Extra repo(obviously this can be scripted):
[root@vmhost ~]# rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-5.noarch.rpm
# Disable it
[root@vmhost yum]# sed -i  "s/enabled=1/enabled=0/g" /etc/yum.repos.d/epel.repo
# Install puppet
[root@vmhost yum]# yum -y install --enablerepo=epel puppet
3- Create /mnt/build to host puppet files. This will be NFS exported so that Guests can access puppet file.
4- Create /mnt/build/vmhost-manifest.pp with following config:
class build-host {
# Some preperation
        file {'motd':
              ensure  => file,
              path    => '/etc/motd',
              mode    => 0644,
              content => "Welcome to ${::fqdn} with IP ${::ipaddress},\nan ${::architecture} ${::operatingsystem} machine part of ${::domain}.\n",
                }

# Setting up bridge network
        file {'eth0':
              ensure  => file,
              path    => '/etc/sysconfig/network-scripts/ifcfg-eth0',
              mode    => 0644,
              content => "DEVICE=\"eth0\"\nNM_CONTROLLED=\"yes\"\nONBOOT=yes\nTYPE=Ethernet\nBRIDGE=\"br0\"\n",
              require => File['br0']
                }

        file {'br0':
              ensure  => file,
              path    => '/etc/sysconfig/network-scripts/ifcfg-br0',
              mode    => 0644,
              content => "DEVICE=\"br0\"\nONBOOT=yes\nTYPE=Bridge\nBOOTPROTO=none\nIPADDR=192.168.0.40\nPREFIX=24\nGATEWAY=192.168.0.1\nDNS1=192.168.0.1\nDEFROUTE=yes\nIPV4_FAILURE_FATAL=yes\nIPV6INIT=no\n",
              require => Package['bridge-utils']
                }

        exec {'restart_network' :
                        command => "/etc/init.d/network restart", 
                        require => File['br0'],
                        unless => "/sbin/ifconfig | grep virbr",    
                }

# Adding Volume Group to Physical Volume
        $vms = "/dev/sda3"
        exec {'volume_group' :
                        command => "/sbin/vgcreate  vms ${vms}",
                        unless => "/sbin/vgdisplay 2>&1| grep vms",
                }

        exec {'vm0root' :
                        command => "/sbin/lvcreate -L 10G -n vm0-root",
                        unless => "/sbin/lvdisplay 2>&1| grep vm0-root",
                }

        exec {'vm0swap' :
                        command => "/sbin/lvcreate -L 4096M -n vm0-swap",
                        unless => "/sbin/lvdisplay 2>&1| grep vm0-swap",
                }

# Disabling SELinux
        if $selinux != 'false' {
                exec {"disable_selinux_enforcement":
                        command => "/bin/sed -i s/SELINUX=.*/SELINUX=disabled/g /etc/sysconfig/selinux  && /bin/sed -i s/SELINUX=.*/SELINUX=disabled/g /etc/selinux/config", }

                notify {"SELinux disabled! Please reboot!" : require => Exec['disable_selinux_enforcement'], }
        }

# Setting up NFS export for Guest VMs to access puppet configs
        file { '/mnt/build' :
                ensure => "directory", }
        exec {"export_puppet" :
                command => '/bin/echo "/mnt/build 192.168.0.0/24(r)" >> /etc/exports',
                unless => '/bin/grep mnt\/build /etc/exports',
                require => File['/mnt/build']
                }


# Package install
        package{'qemu-kvm' : ensure => installed, } 
        package{'libvirt' : ensure => installed, }
        package{'python-virtinst' : ensure => installed, }
        package{'bridge-utils' : ensure => installed, }
        package{'httpd' : ensure => installed, }
        package{'screen' : ensure => installed, }
        package{'createrepo' : ensure => installed, }

# Turning on and off service resources
        # Turning on used services
        service { 'libvirtd':  ensure => 'running', enable => 'true', hasstatus => true, }
        service { 'avahi-daemon':  ensure => 'running', enable => 'true', hasstatus => true, }
        service { 'libvirt-guests':  ensure => 'running', enable => 'true', hasstatus => true, }
        service { 'ntpd':  ensure => 'running', enable => 'true', hasstatus => true,}
        service { 'ntpdate':  ensure => 'running', enable => 'true', hasstatus => true,}
        service { 'httpd':  ensure => 'running', enable => 'true', hasstatus => true, require => Package['httpd'],}
        service { 'rpcbind':  ensure => 'running', enable => 'true',  hasstatus => true,}
        service { 'nfs':  ensure => 'running', enable => 'true',  hasstatus => true, require => Service['rpcbind'],}
        # Turning off un-used services
        service { 'abrt-ccpp':  ensure => 'stopped', enable => 'false',  hasstatus => true,}
        service { 'abrt-oops':  ensure => 'stopped', enable => 'false',  hasstatus => true,}
        service { 'abrtd':  ensure => 'stopped', enable => 'false',  hasstatus => true,}
        service { 'atd':  ensure => 'stopped', enable => 'false', hasstatus => true, }
        service { 'auditd':  ensure => 'stopped', enable => 'false', hasstatus => true, }
        service { 'autofs':  ensure => 'stopped', enable => 'false',  hasstatus => true,}
        service { 'cups':  ensure => 'stopped', enable => 'false',  hasstatus => true,}
        service { 'ip6tables':  ensure => 'stopped', enable => 'false',  hasstatus => true,}
        service { 'iptables':  ensure => 'stopped', enable => 'false',  hasstatus => true,}
        service { 'iscsi':  ensure => 'stopped', enable => 'false',  hasstatus => true,}
        service { 'netfs':  ensure => 'stopped', enable => 'false',  hasstatus => true,}
        service { 'nfslock':  ensure => 'stopped', enable => 'false',  hasstatus => true,}
        service { 'portreserve':  ensure => 'stopped', enable => 'false',  hasstatus => true,}
        service { 'qpidd':  ensure => 'stopped', enable => 'false',  hasstatus => true,}
        service { 'rpcidmapd':  ensure => 'stopped', enable => 'false',  hasstatus => true,}



# Package['Server Platform'] -> File['/home/dwilson/repos/'] -> Notify['Hello']

  
}

node default {
  include build-host
}

5- Run 'puppet -v /mnt/build/vmhost-manifest.pp' to apply all changes.
6- Run 'brctl show' to check bridge interface.
7- To create an accessible repo for your Guests, mount Centos 6.2 minimal install CD on /mnt/cdrom.
8- cp -rf /mnt/cdrom/. /var/www/html/centos/x86_64
9- In /var/www/html/centos/x86_64, modify .treeinfo to have following:
[images-x86_64]

kernel = isolinux/vmlinuz
initrd = isolinux/initrd.img

10- Create vm0-ks.cfg KickStart file on the apache root as:
[root@vmhost ~]# cat /var/www/html/vm0-ks.cfg 
#KS file for VM

install
url --url http://192.168.0.40/centos/x86_64

# Use logical volumes
zerombr
clearpart --all --initlabel
#clearpart --none
bootloader --location=mbr --driveorder=vda,vdb --append=" rhgb crashkernel=auto quiet"
part / --fstype ext4 --size 1 --grow --ondrive=vda
part swap --size 1 --grow --ondrive=vdb

# Kickstart file automatically generated by anaconda.

#version=DEVEL
lang en_US.UTF-8
keyboard us-acentos
network --onboot yes --device eth0 --bootproto static --ip 192.168.0.41 --netmask 255.255.255.0 --gateway 192.160.0.1 --noipv6 --nameserver 192.168.0.1 --hostname web.local
rootpw  letmein
firewall --disabled
authconfig --enableshadow --passalgo=sha512
selinux --disabled
timezone --utc Europe/London


#part / --fstype=ext4 --grow --asprimary --size=200

#part swap --grow --asprimary --size=200

#repo --name="CentOS"  --baseurl=cdrom:sr0 --cost=100

%packages --nobase
@core

11- Create VM by:

virt-install --name=vm0 --cpuset=1 --ram=1024 --arch=x86_64 --network bridge=br0 --disk=/dev/mapper/vms-vm0--root --disk=/dev/mapper/vms-vm0--swap --location http://192.168.0.40/centos/x86_64/ --vnc --vnclisten=0.0.0.0 --noautoconsole --extra-args "ks=http://192.168.0.40/vm0-ks.cfg" --virt-type kvm --os-variant rhel6

12- To watch the progress vnc to your Host as above command creates a one extra screen for you.

13- To backup your Guest VM use following script:
#!/bin/sh
if [ $1 ]
then
virsh suspend $1;
lvcreate -L 100M -n $1-root-snapshot -s /dev/vms/$1-root;
virsh resume $1;
dd if=/dev/mapper/vms-$1--root--snapshot | gzip > ./$1-root.img.gz;
lvremove /dev/mapper/vms-vm0--root--snapshot
else
echo "Please specify the vm name"
fi

Enjoy!

No comments:

Post a Comment