Automate RHEL Based OS Deployments with PXE Boot and Kickstart

One of the keys to building a private cloud infrastructure is the ability to quickly roll out operating systems onto newly provisioned VM’s. Seeing as you likely already have a robust network in place if you’re considering a private cloud infrastructure, it makes sense to leverage your existing investment. In this post we’re going to look at the process of setting up a network deployment server using PXE and explore how we can build on that platform with Kickstart to create a fully automated deployment point.

First, a few housekeeping notes to make things easier for any novice Linux users who may come across this tutorial:

1. Any configuration files provided in this post (and any other posts on my Blog) are provided as examples and intended for reference only. You may copy and paste these files if you would like to use them as templates, but insure you change any values inside brackets (<>) to values that will work within your environment.

2. Linux servers are typically deployed without a GUI and administered via the command line. This tutorial assumes the instance of CentOS that is manually deployed in step 1 of the tutorial is deployed without a GUI and will be configured and administered via the command line.

3. All of the commands below should be run as root. To run a command as root you can either prepend sudo to each command (i.e. – sudo vim /etc/sysconfig/iptables) or elevate to root for the duration of configuration by issuing su and entering the password for the root user.

4. In one of the commands below you will notice “name-of-centos-image.iso”. If you copy and paste command you’ll the error “No such file or directory”. To continue you need to download a CentOS ISO image and substitute the name of the image file for “name-of-centos-image.iso”. The easiest way to download a CentOS ISO image in a command line environment is with the following command:

[bash]wget http://mirror.teklinks.com/centos/6.3/isos/x86_64/CentOS-6.3-x86_64-bin-DVD1.iso[/bash]

Step 1: Deploy base Operating System

Manually install CentOS 64-bit.

Step 2: Disable SElinux

Though not typically recommended in production environments, SElinux should be disabled on this server for all network boot components to function correctly. To completely disable SElinux, open the SElinux configuration file with the following command:

[bash]vim /etc/sysconfig/selinux[/bash]

and edit the file to match the following example:

[bash]

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing – SELinux security policy is enforced.
# permissive – SELinux prints warnings instead of enforcing.
# disabled – No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of these two values:
# targeted – Targeted processes are protected,
# mls – Multi Level Security protection.
SELINUXTYPE=targeted

[/bash]

Once you have finished editing the file save your changes by pressing the escape key, typing :wq, and pressing enter.

Step 3: Install and Configure system services

Install DHCPD

DHCPD will be installed using out-of-box CentOS repositories with the following command:

[bash]yum install dhcp[/bash]

Install HTTPD

HTTPD will be installed using out-of-box CentOS repositories with the following command:

[bash]yum install httpd[/bash]

Apache (httpd) will be configured as the network installation source.

Install TFTP

TFTP will be installed using out-of-box CentOS repositories with the following command:

[bash]yum install tftp-server[/bash]

xinetd is a tftp dependency and is installed with the above command

Install Syslinux

Syslinux isn’t installed as part of the standard server installation options of CentOS 6 so it has to be installed manually with YUM using the following command:

[bash]yum install syslinux[/bash]

Configure DHCPD

To avoid authoring an entire dhcp configuration file from scratch, you can simply copy the content of dhcpd.conf.sample from /usr/share/doc/dhcp*/  to dhcpd.conf using the following command:

[bash]cat /usr/share/doc/dhcp*/dhcpd.conf.sample > /etc/dhcp/dhcpd.conf[/bash]

The out-of-box dhcpd.conf file will need to be configured to suit your particular environment. The example shown below is a minimal sample that contains all of the necessary options to run a simple DHCP server.

/etc/dhcp/dhcpd.conf

[bash]
# dhcpd.conf

# Default and max lease times changed to 1 day (24 hours)

default-lease-time 86400;

max-lease-time 86400;

authoritative;

# Use this to send dhcp log messages to a different log file (you also

# have to hack syslog.conf to complete the redirection).

log-facility local7;

#ddns-update-style interim

subnet <local subnet address> netmask <corresponding subnet mask> {

range <DHCP scope>;

option routers <IP_address_of_router>;

option domain-name-servers <DNS server 1, DNS server 2>;

option domain-name “<desired domain name>”;

# PXE Boot specific configuration options

allow-unknown-clients;

allow booting;

allow bootp;

next-server <IP_address_of_pxe_server>;

filename “pxelinux.0”;

}
[/bash]

Configure Apache (HTTPD)

Since Apache is only being used as a basic network boot transport mechanism, extensive configuration is not required. A directory structure in the Apache root directory should be created to house Kickstart configuration files, scripts, and OS installation files. Our PXE boot environment will initially support CentOS so our directory tree should look something like this:

To create this directory structure, execute the following commands:

[bash]mkdir -p /var/www/html/netboot/distros/centos/5.5/x86_64/{isos,ks,scripts}[/bash]
[bash]mkdir  /var/www/html/netboot/distros/centos/6.0/x86_64/{isos,ks,scripts}[/bash]

Once the directory structure has been created, you need to copy the contents of the installation media for CentOS into the appropriate folder. This can be accomplished with the following commands:

[bash]mount -t iso9660 -o loop name-of-centos-image.iso /mnt[/bash]
[bash]cp -avr /mnt/* /var/www/html/netboot/distros/centos/6.0/x86_64/isos/[/bash]

Configure TFTP

TFTP is controlled by xinetd in RHEL-based distros and must be enabled by editing /etc/xintd.d/tftp. Once edited, the file should look similar to the example below.

/etc/xinetd.d/tftp

[bash]

# default: off

# description: The tftp server serves files using the trivial file transfer

# protocol.  The tftp protocol is often used to boot diskless

# workstations, download configuration files to network-aware printers,

# and to start the installation process for some operating systems.

service tftp

{

socket_type = dgram

protocol = udp

wait = yes

user = root

server = /usr/sbin/in.tftpd

server_args =  -s /tftpboot

disable = no

per_source = 11

cps = 100 2

flags = IPv4

}
[/bash]

The final step in configuring the TFTP server is to create a tftpboot directory to house the Linux kernel image and other files required to boot machines across the network. To create the directory execute the following command:

[bash]mkdir /tftpboot[/bash]

Configure firewall rules

For the network deployment server to function correctly ports 80 (tcp) and 69 (udp) need to be opened. To open these ports, open the iptables rule file with the following command:

[bash]vi /etc/sysconfig/iptables[/bash]

Edit it so it is identical to the example below:

[bash]

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1135:1616350]
-A INPUT -m state –state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state –state NEW -m tcp –dport 22 -j ACCEPT
-A INPUT -p tcp -m state –state NEW -m tcp –dport 80 -j ACCEPT
-A INPUT -p udp -m state –state NEW -m udp –dport 69 -j ACCEPT
-A INPUT -j REJECT –reject-with icmp-host-prohibited
-A FORWARD -j REJECT –reject-with icmp-host-prohibited
COMMIT

[/bash]

Once you have edited the rules file, save and restart the firewall with the following command:

[bash]service iptables restart;service iptables save[/bash]

Step 4: Setup network boot files

The first step to configure the required network boot files is to create a folder structure within the tftpboot directory that was created in the last step. To create the folder structure execute the following command:

[bash]mkdir -p /tftpboot/images/centos/{5.5,6.0}/x86_64/[/bash]

Next, we need to copy the various files from the installation media into our newly created folder structure. To do so, execute the following commands:

[bash]cp /usr/share/syslinux/pxelinux.0 /tftpboot[/bash]
[bash]cp /var/www/html/netboot/distros/centos/6.0/x86_64/isos/isolinux/vmlinuz /tftpboot/images/centos/6.0/x86_64/[/bash]
[bash]cp /var/www/html/netboot/distros/centos/6.0/x86_64/isos/images/pxeboot/initrd.img /tftpboot/images/centos/6.0/x86_64/[/bash]

Step 5: Create PXE Menu

To create the PXE menu cop the menu.c32 file form /usr/share/syslinux to /tftpboot using the following command:

[bash]cp /usr/share/syslinux/menu.c32 /tftpboot[/bash]

Next we need to create the pxelinux.cnf directory inside /tftpboot using the following command:

[bash]mkdir /tftpboot/pxelinux.cfg[/bash]

Within the newly created directory we now need to create a default configuration file wit the following command:

[bash]vi /tftpboot/pxelinux.cfg/default[/bash]

Enter the following into the newly created file

/tftpboot/pxelinux.cfg/default

[bash]

default menu.c32
prompt 0
timeout 300
MENU TITLE <desired menu title>
LABEL Install CentOS 6.2 64-Bit (Manual)
MENU LABEL Install CentOS 6.2 64-Bit
KERNEL images/centos/6.0/x86_64/vmlinuz append vga=normal initrd=images/centos/6.0/x86_64/initrd.img ramdisk_size=32768

[/bash]

Finally save and close the file

Step 6: Set Appropriate File Permissions

Though insecure, the /tftpboot directory and all files and directories within it must be world readable and writable. These permissions can be set in octal form using the following command:

[bash]chmod -R 777 /tftpboot[/bash]

Step 7: Set service persistence

Newly installed services should be configured so that they are persistent across system restarts and do not require manual intervention to start. Service persistence can be set with the following commands:

[bash]chkconfig httpd on[/bash]
[bash]chkconfig dhcpd on[/bash]

Please note that xinetd is automatically configured to start at boot.

Step 8: Restart services

Now that system configuration is complete pertinent system services should be restarted to ensure all configuration changes are recognized. This is accomplished with the following commands:

[bash]service httpd restart[/bash]
[bash]service dhcpd restart[/bash]
[bash]service xinetd restart[/bash]

Step 9: Integrate Kickstart (optional)

If you have successfully configured PXE booting and would like to continue using manual installations you may stop reading here. However, if you would like to configure a fully-automated PXE install you can integrate kickstart by appending the ks parameter to your existing deployment menu entry or creating a new menu entry as shown below. The advantage of creating a separate menu entry is that you retain the flexibility of performing either a manual install or automated install using a single deployment point.

/tftpboot/pxelinux.cfg/default – With Kickstart parameter

[bash]

default menu.c32
prompt 0
timeout 300
MENU TITLE System Deployment
LABEL Install CentOS 6.2 64-Bit
MENU LABEL Install CentOS 6.2 64-Bit (Manual)
KERNEL images/centos/6.0/x86_64/vmlinuz append vga=normal initrd=images/centos/6.0/x86_64/initrd.img ramdisk_size=32768

LABEL CentOS-6.2-32-bit-Kickstart
MENU LABEL Install CentOS 6.2 64-bit (Kickstart)
KERNEL images/centos/6.0/x86_64/vmlinuz append vga=normal initrd=images/centos/6.0/x86_64/initrd.img ramdisk_size=32768 ks=http://<PXE_server_ip_address>/netboot/distros/centos/6.0/x86_64/ks/ks.cfg

[/bash]

To begin integrating a Kickstart file into your deployment process, you should first create an encrypted password hash for use as an argument in the kickstart file. To create the hash of your desired password on OS X or most any modern Linux distribution you can use Python. To create an encrypted hash suitable for use in a Kickstart file run the following bit of Python:

[python]python -c ‘import crypt; print(crypt.crypt(“your desired password”, “$6$salt”))'[/python]

In the above code snippet, you need to replace “your desired password” with the password you want machines deployed with the Kickstart file to use and “salt” with some data (a random word, phrase, etc) that will be concatenated with the password to make the resulting hash stronger. Make sure you paste the output of the hashing process into a temporary file since you’ll need it when working with the Kickstart file.

Next, you must create the ks.cfg file referenced in the new kernel parameter. To create the file use the following command:

[bash]vi /var/www/html/netboot/distros/centos/6.0/x86_64/ks/ks.cfg[/bash]

Once the file has been created you can simply copy and paste the template below and configure it to your needs.

/var/www/html/netboot/distros/centos/6.0/x86_64/ks/ks.cfg

[bash]

# platform=x86, AMD64, or Intel EM64T

# version=1.0

# Firewall configuration

firewall –enabled –service=ssh

# Install OS instead of upgrade

install

# Use network installation

url –url=<“http://PXE_server_ip_address/netboot/distros/centos/6.0/ks/ks.cfg”>

# Root password

rootpw –iscrypted <encrypted password hash created above>

# System authorization information

auth  –useshadow  –passalgo=sha512

# Use text mode install

text

# System keyboard

keyboard us

# System language

lang en_US

# SELinux configuration

selinux –enforcing

# Do not configure the X Window System

skipx

# Installation logging level

logging –level=info

# Reboot after installation

reboot

# System timezone

timezone  America/New_York

# Network information

network  –bootproto=dhcp –device=eth0 –onboot=on

# System bootloader configuration

bootloader –location=mbr

# Clear the Master Boot Record

zerombr

# Partition clearing information

clearpart –all –initlabel

# Disk partitioning information

part swap –fstype=”swap” –size=1024

part / –fstype=”ext4″ –grow –size=1

# Post installation section. You can specify any commands you want executed once
# installation has finished in this section. In this example, the system is
# updated and the output is logged to the post_install.log file.
# Keep in mind that any commands that execute in the post installation section are
# chrooted by default.

%post

/usr/bin/yum -y update >> /root/post_install.log 2>&1

%end

%packages

@core

[/bash]

If you’ve followed this post to this point you should have a functional network deployment server. With the hard work out of the way, it’s time to spin up a test VM and test the functionality of your shiny new server. Let’s take a look at what the deployment process looks like from the client machine perspective:

pxe_bios_dhcp

 

In the above screenshot, the VM has booted, determined the hard drive isn’t a viable boot device as it doesn’t have an OS or boot partition, and is attempting to contact the DHCP server we configured so it can obtain IP information and the next-server address.

pxe_menu

 

In the above screenshot, the VM has successfully contacted our DHCP server and is displaying the PXE boot menu configured earlier. You may notice Install CentOS 6.2 64-bit (Kickstart) is highlighted above. That particular menu choice is highlighted because we included the menu default parameter for that menu choice in the pxelinux.cfg/default file. You can change the default menu choice by simply moving the menu default parameter to another menu choice in the pxelinux.cfg/default file.

pxe_kernel

 

In the above screenshot, a choice of OS to deploy has been made (or the 30 second timeout has occurred (the OS that is represented by the default menu choice was automatically selected) and the VM has begun downloading a compressed, bootable linux kernel and initial ramdisk file so the kernel and other files needed to boot the OS across the network can be loaded into memory.

pxe_img_download

 

In the above screenshot, the VM has successfully downloaded the files required to boot the OS, started Anaconda (the CnetOS installer) and is downloading the install.img file from the network deployment point.

pxe_package_install

 

In the above screenshot the installation of CentOS has begun and packages required for a minimal installation are being downloaded from the network deployment point.

pxe_post_install_scripts

 

In the above screenshot package installation has completed and the post install actions we defined in the Kickstart file are running.

Though setting up a network deployment server is a rather lengthy process, it does produce a single network deployment point that can scale from ten to thousands of machines and eliminates the need for optical or USB based installs. If you have any questions or corrections please don’t hesitate to post them in the comments.

Leave a Reply

Your email address will not be published. Required fields are marked *