Sunday, January 10, 2016

Oracle database 12c with Oracle Linux 7.x and LXC

Linux Containers (LXC) are now certified to run Oracle Database 12c, including Oracle RAC and ASM. You can check out for yourself in the Virtualization Support Matrix as well as in the Database 12.1 Release Notes. If you want to give it quick try and figure out what could be done, nothing is very complicated. Below is a quick introduction. It demonstrates how to use Oracle database 12.1 with Oracle Linux 7.x and LXC container.

After a few reading about Linux vs “the rest of the world” containers, it appears LXC and Docker libcontainer focus more on the management and orchestration side than, for example, true isolation. Before you even start and, assuming you read Oracle Database Release Notes, be advised to patch Oracle Grid Infrastructure, in case you want to use RAC or ASM: Patch 20920711: CSSD FAILURE IN A LXC WOULD CAUSE PHYSICAL NODE REBOOT.

Installing LXC on Oracle Linux 7

Thank to YUM, installing and starting LXC on Oracle Linux 7 doesn’t require more than a few lines of command. I’ve tested it on the UEK4 kernel as you can see from below:
uname -a
Linux 4.1.12-32.el7uek.x86_64 #2 SMP ...
For some undocumented reason, LXC containers don’t get their passwords changed as expected when used with a host running with SELinux in Enforcing mode. In order to get it work, you might want to switch SELinux configuration to Disabled or, at least, Permissive.
Installing LXC and BRTFS require you use the latest UEK3 or UEK4 kernels on Oracle Linux ; you can simply install the software as root from the following command:
yum -y install btrfs-progs lxc wget
Once done, there are 2 configuration steps to perform; one consists in starting and enabling the libvirt daemon with systemctl like below:
systemctl start libvirtd
systemctl enable libvirtd
The second consists in creating a BTRFS filesystem on a LUN/Disk/LV you’ve provisioned like below; change /dev/sdb to meet your requirements:
mkfs.btrfs /dev/sdb
echo "/dev/sdb      /container    btrfs    defaults   0 0" >>/etc/fstab
mount /container

Playing with Containers

Container configuration templates are stored in /usr/share/lxc/templates. To create an Oracle 7.x container, all you need to do it run the following command ; don’t forget “--privileged=rt” as it is a requirement to run Oracle Grid Infrastructure in a way that is supported by Oracle:
lxc-create -n ol7 -B btrfs -t oracle \
   -- --release=7.latest --privileged=rt
You then, can start it as a daemon (-d):
lxc-start -n ol7 -d -o /container/ol7_info.log -l INFO
If you are connected to the host, you can access processes inside the container; it you want to view what is currently part of it, you can install the pstree command and run it with the lxc-start pid as a parameter:
yum -y install psmisc
pstree -g `lxc-info -n ol7|grep "PID:" |awk '{print $2}'`
The output shows the container is running init, a few tty, syslogd, the ssh server and a dhcp client:
                             │                ├─{rsyslogd}(3824)
                             │                └─{rsyslogd}(3824)
You can connect to your container console from the host with the command below; it should prompt for a login/password and you can use the "<Ctrl+a> q" key combination to log out:
lxc-console -n ol7
You can also start a bash shell or any command directly inside the container with lxc-attach. It does not require any credential from the container:
lxc-attach -n ol7
Obviously the container being, by default, attached to a network bridge, you should also be able to connect from the host with a SSH client. In order to proceed, you will need to figure out what IP address has been provided to the container from the dnsmasq service :
lxc-info -n ol7 
Name:           ol7
State:          RUNNING
PID:            13343
CPU use:        17.51 seconds
BlkIO use:      49.71 MiB
Memory use:     1.06 GiB
KMem use:       0 bytes
Link:           vethDACVKP
 TX bytes:      1.42 KiB
 RX bytes:      6.04 KiB
 Total bytes:   7.46 KiB
You then should be able to connect from a simple SSH client :
ssh root@

Playing with Oracle Database 12.1

Now that you’ve created, started and played with LXC, you can create an Oracle Database. But first you have to fulfill the Oracle Database requirements by installing the oracle-rdbms-server-12cR1-preinstall RPM. As root, set the enable value for ol7_UEKR3 in /etc/yum.repos.d/public-yum-ol7.repo to enabled=1. Install the required RPMs with the command below:
yum -y install oracle-rdbms-server-12cR1-preinstall unzip
The Oracle has been created before you install the pre-installation RPM, As a result, dba and oinstall groups are created but not added to the user. Run the command below and disconnect from Oracle to fix the issue:
usermod -G dba -g oinstall oracle
As root, create the inventory file and directories
if [ ! -d /u01 ]; then
   mkdir -p /u01/app/oracle/distribs
   mkdir -p /u01/app/oraInventory
   chown -R oracle:dba /u01

if [ ! -f /etc/oraInst.loc ]; then
   cat >/etc/oraInst.loc <<EOF
  chown root:oinstall /etc/oraInst.loc
  chown 640 /etc/oraInst.loc
As oracle, download and unzip the Oracle distributions ; we will assume they are stored in /u01/app/oracle/distribs/database. As root, add the container name in its /etc/hosts file:
MYIPADDR=`ip addr|grep inet|grep -v inet6|grep global|awk '{print $2}'|cut -d '/' -f 1`
sed -i /localhost/d /etc/hosts
sed “ localhost localhost.localdomain” >> /etc/hosts
echo "$MYIPADDR `hostname`" >> /etc/hosts
As oracle, install the Oracle Database Software
export DISTRIB=`pwd`
./runInstaller -silent -showProgress -ignorePrereq \
 -ignoreSysPrereqs -waitforcompletion \
 -responseFile $DISTRIB/response/db_install.rsp \
  oracle.install.option=INSTALL_DB_SWONLY \
  ORACLE_HOME=/u01/app/oracle/product/12.1.0/db_1 \
  ORACLE_BASE=/u01/app/oracle \
  oracle.install.db.InstallEdition=EE \
  oracle.install.db.DBA_GROUP=dba \
  oracle.install.db.OPER_GROUP=dba \
  oracle.install.db.BACKUPDBA_GROUP=dba \
  oracle.install.db.DGDBA_GROUP=dba \

As root, run the file
As oracle, create the listener in silent mode:
. oraenv
ORACLE_SID = [oracle] ? x
ORACLE_HOME = [/home/oracle] ? /u01/app/oracle/product/12.1.0/db_1

netca -silent  \
   -responsefile $ORACLE_HOME/network/install/netca_typ.rsp
As oracle, create a database in silent mode:
dbca -silent -createDatabase \
  -templateName New_Database.dbt  \
  -gdbName WHITE \
  -createAsContainerDatabase true \
  -numberOfPDBs 1 \
  -pdbName PURPLE \
  -pdbAdminPassword Welcome1 \
  -sysPassword Welcome1 \
  -systemPassword Welcome1 \
  -emConfiguration NONE \
  -datafileDestination /u01/app/oracle/oradata \
  -redoLogFileSize 100 \
  -storageType FS \
  -characterSet AL32UTF8 \
  -sampleSchema true \
  -automaticMemoryManagement false \
  -totalMemory 1536  \
  -databaseType OLTP
As root, create and enable a systemd service to start the instance automatically:
cd /etc/systemd/system
cat >/lib/systemd/system/oradb.service <<EOF
Description=Oracle Database

ExecStart=/u01/app/oracle/product/12.1.0/db_1/bin/dbstart /u01/app/oracle/product/12.1.0/db_1
ExecStop=/u01/app/oracle/product/12.1.0/db_1/bin/dbshut /u01/app/oracle/product/12.1.0/db_1


sed -i s/\:N$/:Y/ /etc/oratab

ln -s /lib/systemd/system/oradb.service /etc/systemd/system/oradb.service

systemctl daemon-reload
systemctl start oradb.service
systemctl status oradb.service
systemctl enable oradb.service

Playing with container again

Now that you’ve setup your configuration, you can stop it and clone it with the lxc-clone command. From the host, run what follows:
lxc-attach -n ol7 -- systemctl disable oradb.service
lxc-stop -n ol7
lxc-clone -s -B btrfs ol7 pink-panther
lxc-start -n ol7 -d -o /container/ol7_info.log -l INFO
sleep 2
lxc-attach -n ol7 -- systemctl enable oradb.service
lxc-attach -n ol7 -- systemctl start oradb.service
lxc-attach -n ol7 -- ps -fu oracle

lxc-start -n pink-panther -d -o /container/pink-panther.log -l INFO
MYIPADDR=`lxc-info -n pink-panther |grep "IP:" |awk '{print $2}'`
lxc-attach -n pink-panther -- sed -i /pink-panther/d /etc/hosts
lxc-attach -n pink-panther -- bash -c "echo \"$MYIPADDR pink-panther\"  >>/etc/hosts"
lxc-attach -n pink-panther -- sed -i s/ol7/pink-panther/ \
lxc-attach -n pink-panther -- systemctl enable oradb.service
lxc-attach -n pink-panther -- systemctl start oradb.service
lxc-attach -n pink-panther -- ps -fu oracle
lxc-attach  -n pink-panther
Once you are done with your container, you can simply destroy it and unreference the storage from the command below:
lxc-destroy -f -n pink-panther
You can verify the associated filesystems has been destroyed with the command below:
ls -ltra /container/pink-panther/rootfs
You can actually do much much more with LXC, starting by managing IO or CPU with cgroups. I’m curious to see if DBA will adopt the technology anytime soon...