Thursday, November 8, 2012

High-Availability storage using DRBD with OCFS2 on Ubuntu 12.04

This howto is designed to solve the following problems:
  • Files in sync over multiple servers in case of
    • Power outage in a single location
    • Hardware failure
    • OS lockup
  • Optimized read performance
  • Mounted filesystem on multiple servers
Other considerations specific to my solution:
  • Limited amount of writes
  • Low latency and high bandwidth between locations

Prerequisites

  • Two servers
  • Ubuntu 12.04
  • Equally sized raw harddrive partition on both servers
  • NTP client installed and running

DRBD set up to act as raid 1 (mirroring)

All steps should be done on both nodes unless stated otherwise

Install and activate DRBD tools and kernel module:
apt-get install drbd8-utils
modprobe drbd


Set up a resource config:
sudo nano /etc/drbd.d/disk.res
# Config by Jon Skarpeteig -- 06.11.2012
resource r0 {
        protocol C;
        syncer { rate 1000M; }
        startup {
                wfc-timeout  15;
                degr-wfc-timeout 60;
                become-primary-on both;
        }
        net {
# allow-two-primaries - Generally, DRBD has a primary and a secondary node.
# In this case, we will allow both nodes to have the filesystem mounted at
# the same time. Do this only with a clustered filesystem. If you do this
# with a non-clustered filesystem like ext2/ext3/ext4 or reiserfs, you will
# have data corruption.
                allow-two-primaries;

# after-sb-0pri discard-zero-changes - DRBD detected a split-brain scenario,
# but none of the nodes think they're a primary. DRBD will take the newest
# modifications and apply them to the node that didn't have any changes.
                after-sb-0pri discard-zero-changes;

# after-sb-1pri discard-secondary - DRBD detected a split-brain scenario,
# but one node is the primary and the other is the secondary. In this case,
# DRBD will decide that the secondary node is the victim and it will sync data
# from the primary to the secondary automatically.
                after-sb-1pri discard-secondary;

# after-sb-2pri disconnect - DRBD detected a split-brain scenario, but it can't
# figure out which node has the right data. It tries to protect the consistency
# of both nodes by disconnecting the DRBD volume entirely. You'll have to tell
# DRBD which node has the valid data in order to reconnect the volume.
                after-sb-2pri disconnect;

                cram-hmac-alg sha1;
                shared-secret "secret";
        }
        on server1 {
                device /dev/drbd0;
                disk /dev/sdb1;
                address 10.0.0.101:7788;
                meta-disk internal;
        }
        on server2 {
                device /dev/drbd0;
                disk /dev/sdb1;
                address 10.0.0.102:7788;
                meta-disk internal;
        }
}

Note: Here, the server1 and server2 are from the output of 'uname -n', and must be resolvable in DNS with both A and PTR records. For good measure, we can add these in /etc/hosts directly as well, not to break the DRBD link on DNS issues.

Initialize DRBD volume, and start drbd daemon:
drbdadm create-md r0
/etc/init.d/drbd start 
Then make Server1 the primary node (run this on server1 only!)
drbdadm -- --overwrite-data-of-peer primary all

At this point, it should synchronize the disks from Server1 => Server2. You can view the progress using
/etc/init.d/drbd status

Once the sync is complete, you can make server2 primary as well (run on server2 only):
drbdadm primary r0

OCFS2 to allow for file system to be mounted more than one place

All steps should be done on both nodes unless stated otherwise
 
First get management tools:
apt-get install ocfs2-tools

My config in /etc/ocfs2/cluster.conf
cluster:
        node_count = 2
        name = www

node:
        ip_port = 7777
        ip_address = 10.0.0.101
        number = 1
        name = server1
        cluster = www

node:
        ip_port = 7777
        ip_address = 10.0.0.102
        number = 2
        name = server2
        cluster = www

Note: The 'name' parameter must match exactly the 'on' parameter from drbd, and resolve to the local ip

Configure ocfs2 cluster:
sudo dpkg-reconfigure ocfs2-tools

Now, you can create the filesystem (on one server only):
mkfs.ocfs2 -L "www" /dev/drbd0

And mounting:
mkdir /var/www
echo "/dev/drbd0  /var/www  ocfs2  noauto,noatime,nodiratime,_netdev  0 0" >> /etc/fstab
mount /dev/drbd0

Now you should be all set up! Go ahead and test how it behaves by creating files, and removing them - and notice how all the changes are replicated.

Tuesday, March 6, 2012

Installing Bugzilla 3.6 on Ubuntu 10.04 LTS

Unfortunately this isn't as easy as it should be, due to dependencies not getting installed properly out of the box. First, download and unpack bugzilla:
wget http://ftp.mozilla.org/pub/mozilla.org/webtools/bugzilla-3.6.8.tar.gz
tar xvf bugzilla-3.6.8
mkdir /var/www/bugzilla
mv bugzilla-3.6.8/* /var/www/bugzilla/
Then check what dependencies are missing with checksetup.pl script:
cd /var/www/bugzilla
./checksetup.pl
This is likely to produce a lot of red lines with missing dependencies, and a way to install it which is supposed to be helpful (/usr/bin/perl install-module.pl --all). In a perfect world, this would solve all problems, but unfortunately it doesn't, as some of the modules simply fails to install. Luckily Ubuntu comes with some precompiled per modules that can be installed using apt:
sudo apt-get update
sudo apt-get install mysql-server build-essential -y
####################
# Required modules #
####################
# DBD::Mysql
sudo apt-get install libdbd-mysql-perl -y
# DateTime
sudo apt-get install libdatetime-perl -y
# Template
sudo apt-get install libtemplate-perl  -y
/usr/bin/perl install-module.pl Template
####################
# Optional modules #
####################
# GD, Chart::Lines, Template::Plugin::GD::Image, GD::Text, GD::Graph
sudo apt-get install libtemplate-plugin-gd-perl -y
# Test::Taint
sudo apt-get install libtest-taint-perl -y
# Math::Random::Secure
sudo apt-get install libany-moose-perl libnamespace-clean-perl
/usr/bin/perl install-module.pl Math::Random::Secure
# mod-perl2
sudo apt-get install libapache2-mod-perl2 -y
Now we're ready to change localconfig, and set up database login for instance:
nano localconfig
Some changes:
# Ubuntu default webserver group
$webservergroup = 'www-data';
Then it's time to create database, and set up virtualhost for Apache:
./checksetup.pl
sudo nano /etc/apache2/sites-enabled/bugzilla
Paste the following config into it:

   DocumentRoot /var/www/bugzilla

   
      AddHandler cgi-script cgi pl
      Options +Indexes +ExecCGI
      DirectoryIndex index.cgi
      AllowOverride Limit
   

After a quick restart of apache, you should be able to browse your newly installed bugzilla.
sudo /etc/init.d/apache2 restart
If you want to install the Bugzilla REST api, you can check out my post at: http://rdstash.blogspot.com/2010/10/bugzilla-rest-importexport-api.html

Thursday, March 1, 2012

SSH keypair exchange made easy

On the client side, only two commands are needed:

To create a local key:
ssh-keygen -t dsa

To add the key as a valid key to the remote machine:
ssh-copy-id -i $HOME/.ssh/id_dsa.pub username@remote.box

Wednesday, February 29, 2012

Installing Gearman PHP Extension 1.0.2 on Ubuntu 10.04 LTS, 11.04, 11.10 and 12.04 LTS from pecl

I started off nice and easy:
sudo apt-get install python-software-properties -y
sudo add-apt-repository ppa:gearman-developers/ppa 
sudo apt-get update
sudo apt-get install gearman-job-server libgearman-dev gearman-tools php-pear php5-dev -y
sudo apt-get install libevent-dev uuid-dev -y
pecl install gearman

Bug then I hit: configure: error: libgearman version 0.21 or later required

To fix it I needed to compile a newer gearman from source, which in turn has another couple of issues with Boost.

To fix this for Ubuntu 10.04 LTS
sudo apt-get install libboost-program-options1.40-dev libboost-thread1.40-dev -y

For Ubuntu 11.04:
sudo apt-get install libboost-thread1.42-dev libcloog-ppl0 libboost-program-options-dev -y
For Ubuntu 11.10 and 12.04:
sudo apt-get install libboost-thread1.46-dev libcloog-ppl0 libboost-program-options-dev -y

Now compile should work, in order for libgearman requirement to be met for pecl:
apt-get install uuid-dev libevent-dev -y
wget https://launchpad.net/gearmand/trunk/0.28/+download/gearmand-0.28.tar.gz
tar xfv gearmand-0.28.tar.gz
cd gearmand-0.28
./configure
make && make install
sudo ldconfig

If you want to use the newly compiled gearmand, you need to edit /etc/init.d/gearman-job-server to include /usr/local:
prefix=/usr/local
Retry pecl install and install module into php:
sudo pecl install gearman
echo "extension=gearman.so" > /etc/php5/conf.d/gearman.ini

Wednesday, October 6, 2010

Bugzilla REST import/export API installation on Ubuntu 10.04

I wanted to export, and import bugs to and from Bugzilla. From the bugzilla irc channel I got a tip about REST API.

This isn't anything supplied by Bugzilla by default, so a separate install is needed, including a couple of patches to Bugzilla itself.

My setup is currently a default Bugzilla 3.6.2 installation on Ubuntu 10.04.

First off, get dependencies:
sudo apt-get install build-essential libcatalyst-perl libcatalyst-modules-perl libmoose-perl apache2 \
libapache2-mod-fastcgi libfcgi-perl libfcgi-procmanager-perl mercurial liblog-handler-perl libarray-diff-perl \
libcatalyst-action-rest-perl libdata-walk-perl libdatetime-format-iso8601-perl libmodule-install-perl -y

PERL_MM_USE_DEFAULT=1 perl -MCPAN -e "install BZ::Client"
PERL_MM_USE_DEFAULT=1 perl -MCPAN -e "install Moose"
PERL_MM_USE_DEFAULT=1 perl -MCPAN -e "install Test::More"
PERL_MM_USE_DEFAULT=1 perl -MCPAN -e "install Catalyst::Controller::REST" #(inc. optional modules)
PERL_MM_USE_DEFAULT=1 perl -MCPAN -e "install Catalyst::Plugin::Log::Handler"
PERL_MM_USE_DEFAULT=1 perl -MCPAN -e "install Slurp"

Patch Bugzilla using the patches from: https://wiki.mozilla.org/Bugzilla:REST_API *DEPRECATED*
cd /var/www/bugzilla
wget https://bugzilla.mozilla.org/attachment.cgi?id=408495 -O JSON_template_for_config.cgi.diff
patch < JSON_template_for_config.cgi.diff
wget https://bugzilla.mozilla.org/attachment.cgi?id=475044 -O template/en/default/config.json.tmpl
chown root:www-data template/en/default/config.json.tmpl
Get the bzapi files:
cd /var/www
hg clone http://hg.mozilla.org/webtools/bzapi bzapi
Copy extension into place and set up config file:
cd /var/www/bzapi
cp -r extension/BzAPI ../bugzilla/extension/
cp bugzilla_api.conf.sample bugzilla_api.conf
nano bugzilla_api.conf
Check that all dependencies are met, by trying to start the fastcgi server:
cd /var/www/bzapi
./script/bugzilla_api_server.pl
Set up apache:
a2enmod ssl
nano /etc/apache2/sites-enabled/bzapi
Example config for apache (I simply added these lines to my bugzilla installation):
# Config for port 80 without ssl (will redirect)
  FastCgiServer /var/www/bzapi/script/bugzilla_api_fastcgi.pl -processes 10 -idle-timeout 180
  Alias /bzapi /var/www/bzapi/script/bugzilla_api_fastcgi.pl/

# Config for port 443 with ssl
  Alias /bzapi /var/www/bzapi-1.0/script/bugzilla_api_fastcgi.pl/
Restart apache to enable config:
apache2ctl restart
At this point I hit a problem with: Can't locate Bugzilla/API.pm in @INC (@INC contains: .. /etc/perl /usr/local/lib/perl/5.10.1 /usr/local/share/perl/5.10.1 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.10 /usr/share/perl/5.10 /usr/local/lib/site_perl .) at /usr/local/share/perl/5.10.1/Module/Runtime.pm line 317. I solved it by adding the following to line 2 in /var/www/bzapi/script/bugzilla_api_fastcgi.pl:
use lib "/var/www/bzapi/lib";
And then restart apache again.

Monday, October 4, 2010

OpenDS kinks

When trying to import users from NIS, typically using Migrationtools, you need to allow import of hashed passwords into the OpenDS server.

This is done by:
Allow LDIF imports of encoded passwords: config/config.ldif, under cn=Default Password Policy,cn=Password Policies,cn=config

change ds-cfg-allow-pre-encoded-passwords : true

Wednesday, September 29, 2010

IPv6 - The PTR record

dig AAAA ipv6.he.net (gets you the address)
dig -x 2001:470:0:64::2
host -t PTR 2001:470:0:64::2
nslookup -type=PTR 2001:470:0:64::2