Monday Aug 05, 2013

Linux Container (LXC) — Part 2: Working With Containers

Containers by Phil Parker, on Flickr
"Containers" by Phil Parker (CC BY 2.0).

Part 1 of this article series provided an overview about the Linux container technology. This second part intends to give you an impression on how to work with containers, by showing a few practical examples. These can be easily followed and reproduced on an up to date Oracle Linux 6 system. For the first steps, it is recommended to install Oracl Linux inside a virtual environment like Oracle VM VirtualBox. Oracle provides a pre-installed and pre-configured Oracle Linux 6 Virtualbox image for free download from the Oracle Technology Network (OTN).

The administration of Linux containers is performed on the command line; so far, there is no integration or support for this technology in applications like Oracle VM Manager or Oracle Enterprise Manager. However, Oracle has developed several enhancements which are included in the lxc package that's part of Oracle Linux 6.4; these changes were also contributed to the upstream LXC project and are now part of the official LXC releases. The support of Linux containers is also included in the libvirt project, which provides a graphical user interface for the management of virtual machines or containers using virt-manager (and other utilities). Libvirt is also included in Oracle Linux.

The creation of Oracle Linux containers can be accomplished on the command line in a few steps, using the LXC utilities. At first, a dedicated directory should be created to host the container file systems. The default location is /container. Creating this directory on top of a Btrfs file system provides a few additional interesting possibilities, e.g. the option to "freeze" a container file system at a certain point in time, or the fast creation (cloning) of additional containers based on a template. Cloning containers using Btrfs snapshots takes place at an instant, without requiring any additional disk space except for the differences to the original template. The creation and management of Btrfs file systems is explained in detail in the chapter "The Btrfs File System" of the "Oracle Linux Administrator's Solutions Guide for Release 6".

The following example creates a Btrfs file system on the second hard disk drive and mounts it to the directory /container:

# mkfs.btrfs /dev/sdb

WARNING! - Btrfs v0.20-rc1 IS EXPERIMENTAL
WARNING! - see http://btrfs.wiki.kernel.org before using

fs created label (null) on /dev/sdb
nodesize 4096 leafsize 4096 sectorsize 4096 size 4.00GB
Btrfs v0.20-rc1

# mdkir -v /container
mkdir: created directory `/container'
# mount -v /dev/sdb /container
mount: you didn't specify a filesystem type for /dev/sdb
I will try type btrfs
/dev/sdb on /container type btrfs (rw)

Now you can create a container of the latest version of Oracle Linux 6 named "ol6cont1" and using the default options by entering the following command. The option "-t" determines the general type of the Linux distribution to be installed (the so-called "template"), e.g. "oracle", "ubuntu" or "fedora". Depending on the template, you can pass template-specific options after the double dashes ("--"). In the case of the Oracle Linux template, you can choose the distribution's version by providing values like "5.8", "6.3" or "6.latest". Further information about the available configuration options can be found in chapter "About the lxc-oracle Template Script" of the Oracle Linux 6 Administrator's Solutions Guide.

# lxc-create -n ol6cont1 -t oracle -- --release=6.latest
/usr/share/lxc/templates/lxc-oracle is /usr/share/lxc/templates/lxc-oracle
Note: Usually the template option is called with a configuration
file option too, mostly to configure the network.
For more information look at lxc.conf (5)

Host is OracleServer 6.4
Create configuration file /container/ol6cont1/config
Downloading release 6.latest for x86_64
Loaded plugins: refresh-packagekit, security
ol6_latest | 1.4 kB 00:00
ol6_latest/primary | 31 MB 01:23
ol6_latest 21879/21879
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package chkconfig.x86_64 0:1.3.49.3-2.el6 will be installed
--> Processing Dependency: libc.so.6(GLIBC_2.4)(64bit) for package: chkconfig-1.3.49.3-2.el6.x86_64
--> Processing Dependency: libc.so.6(GLIBC_2.3.4)(64bit) for package: chkconfig-1.3.49.3-2.el6.x86_64
[...]
--> Processing Dependency: pygpgme for package: yum-3.2.29-40.0.1.el6.noarch
--> Processing Dependency: python-iniparse for package: yum-3.2.29-40.0.1.el6.noarch
--> Processing Dependency: rpm-python for package: yum-3.2.29-40.0.1.el6.noarch
--> Running transaction check
---> Package audit-libs.x86_64 0:2.2-2.el6 will be installed
---> Package bash.x86_64 0:4.1.2-15.el6_4 will be installed
---> Package checkpolicy.x86_64 0:2.0.22-1.el6 will be installed
---> Package coreutils.x86_64 0:8.4-19.0.1.el6_4.2 will be installed
--> Processing Dependency: coreutils-libs = 8.4-19.0.1.el6_4.2 for package: coreutils-8.4-19.0.1.el6_4.2.x86_64
[...]
---> Package pinentry.x86_64 0:0.7.6-6.el6 will be installed
--> Running transaction check
---> Package groff.x86_64 0:1.18.1.4-21.el6 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
chkconfig x86_64 1.3.49.3-2.el6 ol6_latest 158 k
dhclient x86_64 12:4.1.1-34.P1.0.1.el6 ol6_latest 316 k
initscripts x86_64 9.03.38-1.0.1.el6_4.1 ol6_latest 937 k
[...]
rootfiles noarch 8.1-6.1.el6 ol6_latest 6.3 k
rsyslog x86_64 5.8.10-6.el6 ol6_latest 648 k
vim-minimal x86_64 2:7.2.411-1.8.el6 ol6_latest 363 k
yum noarch 3.2.29-40.0.1.el6 ol6_latest 995 k
Installing for dependencies:
MAKEDEV x86_64 3.24-6.el6 ol6_latest 88 k
audit-libs x86_64 2.2-2.el6 ol6_latest 60 k
basesystem noarch 10.0-4.0.1.el6 ol6_latest 4.3 k
[...]
yum-metadata-parser x86_64 1.1.2-16.el6 ol6_latest 26 k
zlib x86_64 1.2.3-29.el6 ol6_latest 72 k

Transaction Summary
================================================================================
Install 135 Package(s)

Total download size: 79 M
Installed size: 294 M
Downloading Packages:
(1/135): MAKEDEV-3.24-6.el6.x86_64.rpm | 88 kB 00:00
(2/135): audit-libs-2.2-2.el6.x86_64.rpm | 60 kB 00:00
(3/135): basesystem-10.0-4.0.1.el6.noarch.rpm | 4.3 kB 00:00
(4/135): bash-4.1.2-15.el6_4.x86_64.rpm | 904 kB 00:02
(5/135): binutils-2.20.51.0.2-5.36.el6.x86_64.rpm | 2.8 MB 00:07
[...]
(131/135): vim-minimal-7.2.411-1.8.el6.x86_64.rpm | 363 kB 00:01
(132/135): xz-libs-4.999.9-0.3.beta.20091007git.el6.x86_ | 89 kB 00:00
(133/135): yum-3.2.29-40.0.1.el6.noarch.rpm | 995 kB 00:03
(134/135): yum-metadata-parser-1.1.2-16.el6.x86_64.rpm | 26 kB 00:00
(135/135): zlib-1.2.3-29.el6.x86_64.rpm | 72 kB 00:00
--------------------------------------------------------------------------------
Total 271 kB/s | 79 MB 04:59
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
Installing : libgcc-4.4.7-3.el6.x86_64 1/135
Installing : setup-2.8.14-20.el6.noarch 2/135
Installing : filesystem-2.4.30-3.el6.x86_64 3/135
Installing : basesystem-10.0-4.0.1.el6.noarch 4/135
Installing : ca-certificates-2010.63-3.el6_1.5.noarch 5/135
[...]
Installing : rsyslog-5.8.10-6.el6.x86_64 131/135
Installing : yum-3.2.29-40.0.1.el6.noarch 132/135
Installing : passwd-0.77-4.el6_2.2.x86_64 133/135
Installing : 2:vim-minimal-7.2.411-1.8.el6.x86_64 134/135
Installing : rootfiles-8.1-6.1.el6.noarch 135/135
Verifying : gamin-0.1.10-9.el6.x86_64 1/135
Verifying : procps-3.2.8-25.el6.x86_64 2/135
Verifying : 12:dhclient-4.1.1-34.P1.0.1.el6.x86_64 3/135
Verifying : 2:ethtool-3.5-1.el6.x86_64 4/135
Verifying : ncurses-base-5.7-3.20090208.el6.x86_64 5/135
[...]
Verifying : ca-certificates-2010.63-3.el6_1.5.noarch 130/135
Verifying : libssh2-1.4.2-1.el6.x86_64 131/135
Verifying : cpio-2.10-11.el6_3.x86_64 132/135
Verifying : mingetty-1.08-5.el6.x86_64 133/135
Verifying : libcurl-7.19.7-37.el6_4.x86_64 134/135
Verifying : 1:findutils-4.4.2-6.el6.x86_64 135/135

Installed:
chkconfig.x86_64 0:1.3.49.3-2.el6
dhclient.x86_64 12:4.1.1-34.P1.0.1.el6
initscripts.x86_64 0:9.03.38-1.0.1.el6_4.1
openssh-server.x86_64 0:5.3p1-84.1.el6
[...]
Dependency Installed:
MAKEDEV.x86_64 0:3.24-6.el6
audit-libs.x86_64 0:2.2-2.el6
basesystem.noarch 0:10.0-4.0.1.el6
bash.x86_64 0:4.1.2-15.el6_4
binutils.x86_64 0:2.20.51.0.2-5.36.el6
[...]
upstart.x86_64 0:0.6.5-12.el6_4.1
ustr.x86_64 0:1.0.4-9.1.el6
util-linux-ng.x86_64 0:2.17.2-12.9.el6_4.3
xz-libs.x86_64 0:4.999.9-0.3.beta.20091007git.el6
yum-metadata-parser.x86_64 0:1.1.2-16.el6
zlib.x86_64 0:1.2.3-29.el6

Complete!
Rebuilding rpm database
Configuring container for Oracle Linux 6.4
Added container user:oracle password:oracle
Added container user:root password:root
Container : /container/ol6cont1/rootfs
Config : /container/ol6cont1/config
Network : eth0 () on virbr0
'oracle' template installed
'ol6cont1' created

To prepare a miminal installation of the latest version of Oracle Linux 6 (about 400 MB), the installation script performs a download of the required RPM packages from Oracle's "public-yum" service. The directory structure of the installed container can be found at /container/ol6cont1/rootfs, it can be browsed and evaluated like any other regular directory structure. The script also creates two user accounts "root" and "oracle" and configures a virtual network device, which obtains an IP address via DHCP from the DHCP server provided by the libvirt framework. The container's configuration file created by lxc-create is located at /container/ol6cont1/config and can be adapted and modified using a regular text editor. Before making any changes, it's recommended to create a snapshot of the container first, which can be used to quickly spawn additional containers:

# lxc-clone -o ol6cont1 -n ol6cont2
Tweaking configuration
Copying rootfs...
Create a snapshot of '/container/ol6cont1/rootfs' in '/container/ol6cont2/rootfs'
Updating rootfs...
'ol6cont2' created
# lxc-ls -1
ol6cont1
ol6cont2

Start the container using the following command:

# lxc-start -n ol6cont1 -d -o /container/ol6cont1/ol6cont1.log
# lxc-info -n ol6cont1
state: RUNNING
pid: 311
# lxc-info -n ol6cont2
state: STOPPED
pid: -1

The container has now been started in the background. Eventual log messages will be redirected to the file ol6cont.log. As you can tell from the output of lxc-info, only the container ol6cont1 has been started, while the clone ol6cont2 remains in stopped state until you boot it up using lxc-start.

Now you can log into the container instance's console using the following command. The container's system configuration can now be modified using the usual tools (e.g. yum or rpm to install additional software).

# lxc-console -n ol6cont1

Oracle Linux Server release 6.4
Kernel 2.6.39-400.109.4.el6uek.x86_64 on an x86_64

ol6cont1 login: root
Password:
[root@ol6cont1 ~]# ps x
PID TTY STAT TIME COMMAND
1 ? Ss 0:00 /sbin/init
184 ? Ss 0:00 /sbin/dhclient -H ol6cont1 -1 -q -lf /var/lib/dhclien
207 ? Sl 0:00 /sbin/rsyslogd -i /var/run/syslogd.pid -c 5
249 ? Ss 0:00 /usr/sbin/sshd
256 lxc/console Ss+ 0:00 /sbin/mingetty /dev/console
260 ? Ss 0:00 login -- root
262 lxc/tty2 Ss+ 0:00 /sbin/mingetty /dev/tty2
264 lxc/tty3 Ss+ 0:00 /sbin/mingetty /dev/tty3
266 lxc/tty4 Ss+ 0:00 /sbin/mingetty /dev/tty4
267 lxc/tty1 Ss 0:00 -bash
278 lxc/tty1 R+ 0:00 ps x
[root@ol6cont1 ~]# logout
Oracle Linux Server release 6.4
Kernel 2.6.39-400.109.4.el6uek.x86_64 on an x86_64

ol6cont1 login: CTRL-A Q

The key combination CTRL-A, Q terminates the console session. Alternatively, you can also log in to the container using SSH from the host system. All containers have their own IP address and are connected to a virtual bridge device virbr0 by default, which is also reachable from the host system. This way, you can easily set up simple client/server architectures within a host system.

A running container can easily be suspended using the command lxc-freeze at any time. All running processes will be halted and won't consume CPU ressources anymore, until you release them using lxc-unfreeze again. Since Linux containers are based on the Linux Control Groups (Cgroups) framework, it is also possible to precisely limit the resources available to a container.

A container can be shut down using various ways: either by calling lxc-stop from the host, or from within the container using the usual commands like shutdown -h or poweroff. Containers that are no longer needed can be discarded using the lxc-destroy command.

If you'd like to learn more about this topic, there is a dedicated chapter about Linux containers in the Oracle Linux Administrator's Solutions Guide. It covers the creation, configuration and starting/stopping as well as monitoring of containers in detail. It also explains how to prepare the container storage on a Btrfs file system and how existing containers can be quickly cloned.

More links about the topic of Linux containers:

Wednesday Jun 26, 2013

Linux-Containers — Part 1: Overview

Containers by Phil Parker, on Flickr
"Containers" by Phil Parker (CC BY 2.0).

Linux Containers (LXC) provide a means to isolate individual services or applications as well as of a complete Linux operating system from other services running on the same host. To accomplish this, each container gets its own directory structure, network devices, IP addresses and process table. The processes running in other containers or the host system are not visible from inside a container. Additionally, Linux Containers allow for fine granular control of resources like RAM, CPU or disk I/O.

Generally speaking, Linux Containers use a completely different approach than "classicial" virtualization technologies like KVM or Xen (on which Oracle VM Server for x86 is based on). An application running inside a container will be executed directly on the operating system kernel of the host system, shielded from all other running processes in a sandbox-like environment. This allows a very direct and fair distribution of CPU and I/O-resources. Linux containers can offer the best possible performance and several possibilities for managing and sharing the resources available.

Similar to Containers (or Zones) on Oracle Solaris or FreeBSD jails, the same kernel version runs on the host as well as in the containers; it is not possible to run different Linux kernel versions or other operating systems like Microsoft Windows or Oracle Solaris for x86 inside a container. However, it is possible to run different Linux distribution versions (e.g. Fedora Linux in a container on top of an Oracle Linux host), provided it supports the version of the Linux kernel that runs on the host. This approach has one caveat, though - if any of the containers causes a kernel crash, it will bring down all other containers (and the host system) as well.

For example, Oracle's Unbreakable Enterprise Kernel Release 2 (2.6.39) is supported for both Oracle Linux 5 and 6. This makes it possible to run Oracle Linux 5 and 6 container instances on top of an Oracle Linux 6 system. Since Linux Containers are fully implemented on the OS level (the Linux kernel), they can be easily combined with other virtualization technologies. It's certainly possible to set up Linux containers within a virtualized Linux instance that runs inside Oracle VM Server for Oracle VM Virtualbox.

Some use cases for Linux Containers include:

  • Consolidation of multiple separate Linux systems on one server: instances of Linux systems that are not performance-critical or only see sporadic use (e.g. a fax or print server or intranet services) do not necessarily need a dedicated server for their operations. These can easily be consolidated to run inside containers on a single server, to preserve energy and rack space.
  • Running multiple instances of an application in parallel, e.g. for different users or customers. Each user receives his "own" application instance, with a defined level of service/performance. This prevents that one user's application could hog the entire system and ensures, that each user only has access to his own data set. It also helps to save main memory — if multiple instances of a same process are running, the Linux kernel can share memory pages that are identical and unchanged across all application instances. This also applies to shared libraries that applications may use, they are generally held in memory once and mapped to multiple processes.
  • Quickly creating sandbox environments for development and testing purposes: containers that have been created and configured once can be archived as templates and can be duplicated (cloned) instantly on demand. After finishing the activity, the clone can safely be discarded. This allows to provide repeatable software builds and test environments, because the system will always be reset to its initial state for each run. Linux Containers also boot significantly faster than "classic" virtual machines, which can save a lot of time when running frequent build or test runs on applications.
  • Safe execution of an individual application: if an application running inside a container has been compromised because of a security vulnerability, the host system and other containers remain unaffected. The potential damage can be minimized, analyzed and resolved directly from the host system.

Note: Linux Containers on Oracle Linux 6 with the Unbreakable Enterprise Kernel Release 2 (2.6.39) are still marked as Technology Preview - their use is only recommended for testing and evaluation purposes.

The Open-Source project "Linux Containers" (LXC) is driving the development of the technology behind this, which is based on the "Control Groups" (CGroups) and "Name Spaces" functionality of the Linux kernel. Oracle is actively involved in the Linux Containers development and contributes patches to the upstream LXC code base.

Control Groups provide means to manage and monitor the allocation of resources for individual processes or process groups. Among other things, you can restrict the maximum amount of memory, CPU cycles as well as the disk and network throughput (in MB/s or IOP/s) that are available for an application.

Name Spaces help to isolate process groups from each other, e.g. the visibility of other running processes or the exclusive access to a network device. It's also possible to restrict a process group's access and visibility of the entire file system hierarchy (similar to a classic "chroot" environment).

CGroups and Name Spaces provide the foundation on which Linux containers are based on, but they can actually be used independently as well.

A more detailed description of how Linux Containers can be created and managed on Oracle Linux will be explained in the second part of this article.

Additional links related to Linux Containers:

- Lenz Grimmer

Follow me on:
Personal Blog | Facebook | Twitter | Linux Blog |

About

Contributors:
Rick Ramsey
Kemer Thomson
and members of the OTN community

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
12
13
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today
Blogs We Like