Wednesday, February 18, 2015

[OpenVZ] Create an Alpine Linux container from scratch

Containers are pretty much popular those days, especially due to Docker, but I have to say that when it comes to production environment, I stick with OpenVZ that has been proven to be rock solid and stable for ages

With OpenVZ, a lot of precreated os templates are available out of the box (CentOS, Ubuntu, etc...), and they come in deferent flavors (minimal, devel, ... ), but even the smallest one is around 100MB in its tar.gz format, and uses ~500MB once created and started as a vanilla live container (CT)

This makes things a little bit inefficient as it takes time to download (vztmpl-dl), create (vzctl create), migrate (vzmigrate), upload CT backups to S3, and it can waste a lot of disk space on the hardware node (HN), especially when you have a lot of containers that expose a few services in a micro service way

You usually end up using most of the HN disk space for the bare OS (no deduplication between mostly identical CTs on the HNs), and only a couple of MB for what the CT is really meant to do/specialized for

More over, if you decide to keep the last n versions for each service container in the form of a customized os template/tarball, (so that you can instantly recreate your full IT stack at any given version using the under rated but beautiful ${TMPL_REPO_PREFIX} exposed thru /etc/vz/download.conf), you just waste space or have to limit you to a few versions

This is where Alpine Linux can help you !!

A barbone Alpine Linux is just 6MB in size and has access to a surprisingly rich package repository

Even if the "dists/scripts support for Alpine Linux" as been added to OpenVZ since vzctl 3.3, no precreated template seams to be available, and if you google "Alpine Linux" + "OpenVZ" + "os template", the result is pretty much disappointing and leads to incomplete informations or old and partially working Alpine template 

If you are interested in creating your own Alpine Linux os tempalte for OpenVZ, here are the quick steps you could follow :

  - Step 1 : From your HN command line, create a minimal CentOS container from which you will install Alpine Linux in a chroot

vzctl create ${CTID} --ipadd ${IP} --hostname ${HOSTNAME} --ostemplate centos-6-x86-minimal
  - Step 2 : From this newly created build container, download the latest apk static package :

export mirror=""
wget ${mirror}/v3.1/main/x86_64/apk-tools-static-2.5.0_rc1-r0.apk
tar -xzf apk-tools-static-2.5.0_rc1-r0.apk
  - Step 3 : Install the alpine base installation into the chroot

export chroot_dir="/tmp/alp"
mkdir -p ${chroot_dir}
./sbin/apk.static -X ${mirror}/v3.1/main -U --allow-untrusted --root ${chroot_dir} --initdb add alpine-base
  - Step 4 : Create the necessary devices in the chroot :

mknod -m 666 ${chroot_dir}/dev/full c 1 7
mknod -m 666 ${chroot_dir}/dev/ptmx c 5 2
mknod -m 644 ${chroot_dir}/dev/random c 1 8
mknod -m 644 ${chroot_dir}/dev/urandom c 1 9
mknod -m 666 ${chroot_dir}/dev/zero c 1 5
mknod -m 666 ${chroot_dir}/dev/tty c 5 0
rm -rf  ${chroot_dir}/dev/null
mknod -m 666 ${chroot_dir}/dev/null c 1 3
  - Step 5 : Edit fstab and inittab so that it can work in an OpenVZ environment

vi ${chroot_dir}/etc/fstab
# START -------------------------------------
none /dev/pts devpts rw,gid=5,mode=620 0 0
none /dev/shm tmpfs defaults 0 0
# END ---------------------------------------
vi ${chroot_dir}/etc/inittab
# START -------------------------------------
# Set up a couple of getty's
#tty1::respawn:/sbin/getty 38400 tty1
#tty2::respawn:/sbin/getty 38400 tty2
#tty3::respawn:/sbin/getty 38400 tty3
#tty4::respawn:/sbin/getty 38400 tty4
#tty5::respawn:/sbin/getty 38400 tty5
#tty6::respawn:/sbin/getty 38400 tty6
#1:2345:respawn:/sbin/getty 38400 console
#2:2345:respawn:/sbin/getty 38400 tty2
# END ---------------------------------------   
  - Step 6 : [optional] Set up the latest APK mirror :

echo "${mirror}/v3.1/main/" > ${chroot_dir}/etc/apk/repositories
At this step you could skip to step 9, but sometimes it is interesting to add a few services at startup or even add sshd into the container

  - Step 7 :  [optional] Install sshd

./sbin/apk.static -X ${mirror}/v3.1/main -U --allow-untrusted --root ${chroot_dir} add sshd
  - Step 8 :  [optional]  Enter the chroot and customize a few things as you see fit :

mount -t proc none ${chroot_dir}/proc
mount -o bind /sys ${chroot_dir}/sys
chroot ${chroot_dir} /bin/sh -l 
Ex : Setup init services

rc-update add hostname default
rc-update add localmount default
rc-update add klogd default
rc-update add networking default
rc-update add syslog default
rc-update add dmesg default
rc-update add sshd default      
  - Step 9 :  Create the OpenVZ template

exit #exit from chroot 
umount ${chroot_dir}/proc
umount ${chroot_dir}/sys    
tar zcf ./alpine-3.1.2-x86_64.tar.gz -C ${chroot_dir} . 
  - Step 10 : Copy the created template at the HN template dir :

exit # exit from centos ct and get back to the HN command line
scp ${IP}:/root/alpine-3.1.2-x86_64.tar.gz /vz/template/cache/
  - Step 11 : Start a brand new CT using your Alpine Linux template

vzctl create ${CTID2} --ipadd ${IP2} --hostname ${HOSTENAME2} --ostemplate alpine-3.1.2-x86_64
vzctl start ${CTID2}
  - Step 12 : Enter your CT

vzctl enter ${CTID2}
or ssh into the CT if you have installed sshd into your template (optional step 7) : 

vzctl set ${CTID2} --userpasswd ${LOGIN}:${PASSWORD}
ssh ${LOGIN}@${IP2}

Happy hacking !!

[TODO] : Add fancy formatting to this terrible blog post that hurts my eyes

1 comment:

phlogiston said...

Could you share a recent ready-to-use template?