<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0"><channel><title>Thomas Christory's Blog</title> <link>http://blog.christory.net</link> <description>When Cisco, VMware and Linux are your everyday</description> <lastBuildDate>Sat, 12 Jun 2010 18:14:48 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=</generator> <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/ThomasChristory" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="thomaschristory" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><title>Your ideal CCIE R&amp;S rack ?</title><link>http://blog.christory.net/2010/06/12/your-ideal-ccie-rs-rack/</link> <comments>http://blog.christory.net/2010/06/12/your-ideal-ccie-rs-rack/#comments</comments> <pubDate>Sat, 12 Jun 2010 18:14:48 +0000</pubDate> <dc:creator>Thomas Christory</dc:creator> <category><![CDATA[Cisco]]></category> <category><![CDATA[ccie]]></category> <category><![CDATA[rack]]></category> <category><![CDATA[routing]]></category> <category><![CDATA[Switching]]></category><guid isPermaLink="false">http://blog.christory.net/?p=57</guid> <description><![CDATA[Hello folks, I've been given the opportunity to build a CCIE R&#038;S rack with quasi unlimited budget. So here is the question, what would you guys put in it ? Let's rock the comments ! Tags: ccie, Cisco, rack, routing, Switching]]></description> <content:encoded><![CDATA[<div
class="tweetmeme_button" style="float: right; margin-left: 10px;"> <a
href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.christory.net%2F2010%2F06%2F12%2Fyour-ideal-ccie-rs-rack%2F"><br
/> <img
src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.christory.net%2F2010%2F06%2F12%2Fyour-ideal-ccie-rs-rack%2F&amp;source=thomaschristory&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br
/> </a></div><p>Hello folks,</p><p>I've been given the opportunity to build a <a
href="http://blog.christory.net/tag/ccie/" class="st_tag internal_tag" rel="tag" title="Posts tagged with ccie">CCIE</a> R&#038;S <a
href="http://blog.christory.net/tag/rack/" class="st_tag internal_tag" rel="tag" title="Posts tagged with rack">rack</a> with quasi unlimited budget.<br
/> So here is the question, what would you guys put in it ?<br
/> Let's rock the comments !</p>Tags: <a
href="http://blog.christory.net/tag/ccie/" title="ccie" rel="tag">ccie</a>, <a
href="http://blog.christory.net/tag/cisco/" title="Cisco" rel="tag">Cisco</a>, <a
href="http://blog.christory.net/tag/rack/" title="rack" rel="tag">rack</a>, <a
href="http://blog.christory.net/tag/routing/" title="routing" rel="tag">routing</a>, <a
href="http://blog.christory.net/tag/switching/" title="Switching" rel="tag">Switching</a><br
/> ]]></content:encoded> <wfw:commentRss>http://blog.christory.net/2010/06/12/your-ideal-ccie-rs-rack/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>Cisco Contest #1</title><link>http://blog.christory.net/2010/02/10/cisco-contest-1/</link> <comments>http://blog.christory.net/2010/02/10/cisco-contest-1/#comments</comments> <pubDate>Wed, 10 Feb 2010 16:12:26 +0000</pubDate> <dc:creator>Thomas Christory</dc:creator> <category><![CDATA[Cisco]]></category> <category><![CDATA[Switching]]></category> <category><![CDATA[bcmsn]]></category> <category><![CDATA[context]]></category> <category><![CDATA[switch]]></category><guid isPermaLink="false">http://blog.christory.net/?p=48</guid> <description><![CDATA[Fun little Cisco Contest]]></description> <content:encoded><![CDATA[<div
class="tweetmeme_button" style="float: right; margin-left: 10px;"> <a
href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.christory.net%2F2010%2F02%2F10%2Fcisco-contest-1%2F"><br
/> <img
src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.christory.net%2F2010%2F02%2F10%2Fcisco-contest-1%2F&amp;source=thomaschristory&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br
/> </a></div><p>Because it's fun, here is a quick contest when you have to find the difference between the same show command, and find why this output is not twice the same :</p><p>First :</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;">SW3<span style="color: #666666; font-style: italic;">#sh int po 2 tru</span>
&nbsp;
Port        Mode             Encapsulation  Status        Native vlan
Po2         on               n-802.1q       trunking      <span style="color: #000000;">1</span>
&nbsp;
Port        Vlans allowed on trunk
Po2         <span style="color: #000000;">1</span>-<span style="color: #000000;">4094</span>
&nbsp;
Port        Vlans allowed and active <span style="color: #000000; font-weight: bold;">in</span> management domain
Po2         <span style="color: #000000;">1</span>,<span style="color: #000000;">100</span>,<span style="color: #000000;">200</span>,<span style="color: #000000;">300</span>
&nbsp;
Port        Vlans <span style="color: #000000; font-weight: bold;">in</span> spanning <span style="color: #c20cb9; font-weight: bold;">tree</span> forwarding state and not pruned
Po2         none</pre></div></div><p>Second :</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;">SW3<span style="color: #666666; font-style: italic;">#sh int po 2 tru         </span>
&nbsp;
Port        Mode             Encapsulation  Status        Native vlan
Po2         on               802.1q         trunking      <span style="color: #000000;">1</span>
&nbsp;
Port        Vlans allowed on trunk
Po2         <span style="color: #000000;">1</span>-<span style="color: #000000;">4094</span>
&nbsp;
Port        Vlans allowed and active <span style="color: #000000; font-weight: bold;">in</span> management domain
Po2         <span style="color: #000000;">1</span>,<span style="color: #000000;">100</span>,<span style="color: #000000;">200</span>,<span style="color: #000000;">300</span>
&nbsp;
Port        Vlans <span style="color: #000000; font-weight: bold;">in</span> spanning <span style="color: #c20cb9; font-weight: bold;">tree</span> forwarding state and not pruned
Po2         none</pre></div></div><p>Don't focus on the fact that it is an etherchannel, it's not the subject here.</p><p>So, what is different, and -why- ?</p><p>Have Fun,</p><p>Thomas</p>Tags: <a
href="http://blog.christory.net/tag/bcmsn/" title="bcmsn" rel="tag">bcmsn</a>, <a
href="http://blog.christory.net/tag/cisco/" title="Cisco" rel="tag">Cisco</a>, <a
href="http://blog.christory.net/tag/context/" title="context" rel="tag">context</a>, <a
href="http://blog.christory.net/tag/switch/" title="switch" rel="tag">switch</a><br
/> ]]></content:encoded> <wfw:commentRss>http://blog.christory.net/2010/02/10/cisco-contest-1/feed/</wfw:commentRss> <slash:comments>7</slash:comments> </item> <item><title>Building an easy and scalable load-balanced high-availability web-hosting solution. Part One : The front</title><link>http://blog.christory.net/2009/09/15/building-an-easy-and-scalable-load-balanced-high-availability-web-hosting-solution-part-one-the-front/</link> <comments>http://blog.christory.net/2009/09/15/building-an-easy-and-scalable-load-balanced-high-availability-web-hosting-solution-part-one-the-front/#comments</comments> <pubDate>Tue, 15 Sep 2009 14:20:04 +0000</pubDate> <dc:creator>Thomas Christory</dc:creator> <category><![CDATA[HAProxy]]></category> <category><![CDATA[High-Availability]]></category> <category><![CDATA[Linux]]></category> <category><![CDATA[Nginx]]></category> <category><![CDATA[administration]]></category> <category><![CDATA[failover]]></category> <category><![CDATA[heartbeat]]></category> <category><![CDATA[load balancer]]></category> <category><![CDATA[webpulser]]></category><guid isPermaLink="false">http://blog.christory.net/?p=19</guid> <description><![CDATA[I was recently asked for my job to set-up a high-availability solution to make sure our websites and those we are hosting will never be down (or the fewest time possible), plus, we wanted to put some load balancing on top of that. Our hosting architecture was dead simple : A front server, with the [...]]]></description> <content:encoded><![CDATA[<div
class="tweetmeme_button" style="float: right; margin-left: 10px;"> <a
href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.christory.net%2F2009%2F09%2F15%2Fbuilding-an-easy-and-scalable-load-balanced-high-availability-web-hosting-solution-part-one-the-front%2F"><br
/> <img
src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.christory.net%2F2009%2F09%2F15%2Fbuilding-an-easy-and-scalable-load-balanced-high-availability-web-hosting-solution-part-one-the-front%2F&amp;source=thomaschristory&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br
/> </a></div><div
style="text-align: center;"><p
style="text-align: justify;">I was recently asked for my job to set-up a high-availability solution to make sure our websites and those we are hosting will never be down (or the fewest time possible), plus, we wanted to put some load balancing on top of that.</p><p
style="text-align: justify;">Our hosting architecture was dead simple : A front server, with the websites contents, and a Back-end server with the MySQL server.<br
/> What we were aiming at : Two front servers, Two back-end Servers. (We could have also done that with 3/4/5/6 servers and so forth)</p><p
style="text-align: justify;">So what I needed was :</p><ul
style="text-align: justify;"><li>Four servers</li><li>A load-balancer : <a
href="http://blog.christory.net/tag/haproxy/" class="st_tag internal_tag" rel="tag" title="Posts tagged with HAProxy">HAProxy</a></li><li>A way to detect if the load-balancer goes down and be able replace it immediately and automatically : <a
href="http://blog.christory.net/tag/heartbeat/" class="st_tag internal_tag" rel="tag" title="Posts tagged with heartbeat">Heartbeat</a></li><li>A way to replicate the MySQL Server and replace it immediately and automatically if it fails : MySQL replication (+ Heartbeat)</li><li>A way to sync data uploaded by users between X servers (in our case, small files like pdf, images, etc) : Inotify + Rsync</li><li>A bunch of spare IP addresses that can travel from one server to another</li><li>Google</li><li>Optionally a way to have your Vhosts files managed from another place and be able to download them onto your servers automatically (think puppet here).</li></ul></div><p
style="text-align: justify;">In this article I will focus on the front part of the job and leave the MySQL-back-end part for another time/article.</p><h3><span
style="text-decoration: underline;">1/ First : Basic checks</span></h3><p
style="text-align: justify;">I started this project with one of my front server already in production, so I had to be careful with what I was doing. If you start from scratch you might not have to check everything three times to be sure you're not going to destroy something. (Backups is the master keyword here)</p><p
style="text-align: justify;">So we have two servers, Front1 and Front2.</p><p
style="text-align: justify;">Here is the list of things that need to be done :</p><ol
style="text-align: justify;"><li>Same configuration on each side, it does ease the whole process.</li><li>Same data on each side, you need to serve the same content otherwise the whole thing is useless. We do RubyOnRails websites so we use Capistrano to deploy our applications, this way we just had to add another server to our deployment file. Rsync works here too. Be sure to check the permissions if you are making any kind of archive.</li><li>Same Vhosts files on each side. Modifying/adding Vhosts files is not fun as you have to log on every server to do so. I would recommend to use a tool like puppet to easily deploy or modify them, as you can push them really quick and have puppet restart the web-servers automatically.</li><li>Keep your files sync'ed, if your users can upload files on your servers, you need to have them on both(all) servers. There are plenty of ways to do so, from an automatic Rsync (bad), to a remote shared storage(think iscsi+ocfs+dm-multipath)(better). We currently use a custom script with Inotify + Rsync. I won't go into details as it will be the subject of another article sometime soon.</li></ol><p
style="text-align: justify;">This was the easy part that you should be able to do this quickly.</p><p
style="text-align: justify;">Before going on, let me throw some IPs in the mix :</p><ul
style="text-align: justify;"><li>Front1 will be 192.168.1.1</li><li>Front2 will be 192.168.1.2</li><li
style="text-align: justify;">And we will have a special IP, for the load-balancer that will be HAP for the DNS and 192.168.1.3 for the number.</li></ul><h3 style="text-align: justify;"><span
style="text-decoration: underline;">2/ Next : The load-balancer, HAProxy</span></h3><p
style="text-align: justify;">One of the goal of this architecture was being able to split the load between the servers, and one of the best software solution for this is <a
title="HAProxy website" href="http://www.haproxy.org/" target="_blank">HAProxy</a>.</p><p
style="text-align: justify;">You might be telling yourself that for a proper use, we would need a third server to act as a <a
href="http://blog.christory.net/tag/load-balancer/" class="st_tag internal_tag" rel="tag" title="Posts tagged with load balancer">load balancer</a> (and a fourth to back-it-up). Under a constant heavy load that might be true, but for a lot a companies, that is not.</p><p
style="text-align: justify;">We will instead use one of our front servers as the load-balancer, the other one being the backup one. This way, is both servers are up, Front1 is the load balancer and redirect connections to himself and Front2, if it dies, Front2 become the load-balancer and redirect to himself and Front1 (which is dead, so that is silly, but if we had three or more servers, it would make sense.)</p><p
style="text-align: justify;">Here is a picture of the setup :</p><p
style="text-align: justify;"><a
href="http://blog.christory.net/wp-content/uploads/2009/09/archi-mutu.png"><img
class="alignnone size-thumbnail wp-image-20" title="Architecture" src="http://blog.christory.net/wp-content/uploads/2009/09/archi-mutu-150x150.png" alt="Architecture" width="150" height="150" /></a></p><p
style="text-align: justify;"><p
style="text-align: justify;">Note : Sorry for the lame graphic, I'm terrible at drawing !</p><p
style="text-align: justify;">As I mentioned earlier, there is a third IP that will be floating around the servers and will be used to point the A records of our websites so that no matter what, those records will always be valid as the IP will(should) always answer any connection. My servers are rented @ OVH, and those flying IPs are called FailOverIp which I will use to name it.</p><p
style="text-align: justify;">So what we have to do for now is keeping the ip on the side, will see later how to have it attached automatically to the "master" server.</p><p
style="text-align: justify;">I'm using Debian so to install HAProxy, a simple "<span
style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre; ">aptitude install haproxy" <span
style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal; font-size: 13px; ">is enough.</span></span></p><p
style="text-align: justify;"><span
style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre; "><span
style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal; font-size: 13px; ">We now have to stop and think a little. Using one server for the proxy and the web-server instead of two has a little catch. HAProxy and your web-server can't both listen on port 80, and you sure don't want your customers to have to remember another port. What we are going to do instead is moving the ports of the web-server to something else like 5080. </span></span></p><p
style="text-align: justify;"><span
style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre; "><span
style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal; font-size: 13px; ">This is quite simple to do, in <a
href="http://blog.christory.net/tag/nginx/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Nginx">Nginx</a> for example you go from listen 80; to listen 5080;</span></span></p><p
style="text-align: justify;">There is another trick we will be using, as we are cool admins. If we have to perform scheduled maintenance on one of the servers, we don't want to kick the users from it, and have them restart their session.</p><p
style="text-align: justify;"><span
style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre; "><span
style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal; font-size: 13px; ">What we are going to do instead is blocking new connections, but let the old ones finish. For that purpose we will have a main server, and a backup one. the backup one accepting no new connections, but managing the already opened ones. In fact the main server and the backup one will be the exact same machine. We will be playing with iptables to have HAProxy thinks it's 2 servers. </span></span></p><p
style="text-align: justify;"><span
style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre; "><span
style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal; font-size: 13px; ">So from a HAProxy point of view, there will be 4 servers, 2 main, 2 backup, but really, only 2.</span></span></p><p
style="text-align: justify;">Here is a commented configuration file for HAProxy :</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;">front1:~<span style="color: #666666; font-style: italic;"># cat /etc/haproxy/haproxy.cfg</span>
global
 log 127.0.0.1    local0
 <span style="color: #666666; font-style: italic;">#log 127.0.0.1    local1 notice</span>
 log 127.0.0.1    syslog debug
 <span style="color: #666666; font-style: italic;">#log loghost    local0 info</span>
 maxconn <span style="color: #000000;">4096</span>
 <span style="color: #666666; font-style: italic;">#chroot /usr/share/haproxy</span>
 user haproxy
 group haproxy
 daemon
 <span style="color: #666666; font-style: italic;">#debug</span>
 <span style="color: #666666; font-style: italic;">#quiet</span>
&nbsp;
defaults
 log    global
 mode    http
 option    httplog
 option    dontlognull
 retries    <span style="color: #000000;">3</span>
 option redispatch
 maxconn    <span style="color: #000000;">2000</span>
 contimeout    <span style="color: #000000;">5000</span>
 clitimeout    <span style="color: #000000;">50000</span>
 srvtimeout    <span style="color: #000000;">50000</span>
 stats <span style="color: #7a0874; font-weight: bold;">enable</span>
 stats scope    .
 <span style="color: #666666; font-style: italic;">## here you can define a custom url for the stats</span>
 stats uri     <span style="color: #000000; font-weight: bold;">/</span>haproxy?stats
 <span style="color: #666666; font-style: italic;">## and a custom user-name and password</span>
 stats auth     USER:PASS           
&nbsp;
 <span style="color: #666666; font-style: italic;">## you can have haproxy to listen on every address (0.0.0.0) or a specific one, plus you name your &quot;cluster&quot; (WebFarm here)</span>
listen WebFarm 192.168.1.3:<span style="color: #000000;">80</span>
 mode http
 <span style="color: #666666; font-style: italic;">## we want every new connexion to be balanced between the servers</span>
 balance    roundrobin
 <span style="color: #666666; font-style: italic;">## we insert a cookie  to memorize where the previous connections were send to that client</span>
 cookie SERVERID insert indirect
 <span style="color: #666666; font-style: italic;">## you forward the real ip address of the client to the web-server (useful for logs)</span>
 option forwardfor
 <span style="color: #666666; font-style: italic;">## this is the file your HAProxy is going to poll to see if your web-server is still alive.</span>
 option httpchk HEAD <span style="color: #000000; font-weight: bold;">/</span>check.txt HTTP<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">1.0</span>         
&nbsp;
 <span style="color: #666666; font-style: italic;">## here is the fun : We have to block, the front one and the back one</span>
 <span style="color: #666666; font-style: italic;">## the front block is the main servers</span>
 <span style="color: #666666; font-style: italic;">## you can see two cookies, to differentiate each server, and the check that is done on port 2381 every 2 seconds</span>
 server  Front1 192.168.1.1:<span style="color: #000000;">5380</span> cookie A check port <span style="color: #000000;">5381</span> inter <span style="color: #000000;">2000</span>
 server  Front12 192.168.1.2:<span style="color: #000000;">5380</span> cookie B check port <span style="color: #000000;">5381</span> inter <span style="color: #000000;">2000</span>
&nbsp;
 <span style="color: #666666; font-style: italic;">## here are the backup servers, as you can see we use the same cookies. Same check as the front but on port 5380.</span>
 <span style="color: #666666; font-style: italic;">## we added the word backup to specify that HAProxy must use these only is the main servers are down. A trick we use with iptables.</span>
 server  Front1bck 192.168.1.1:<span style="color: #000000;">5380</span> cookie A check port <span style="color: #000000;">5380</span> inter <span style="color: #000000;">2000</span> backup
 server  Front2bck 192.168.1.2:<span style="color: #000000;">5380</span> cookie B check port <span style="color: #000000;">5380</span> inter <span style="color: #000000;">2000</span> backup
&nbsp;
 <span style="color: #666666; font-style: italic;">#errorloc    502    http://192.168.114.58/error502.html</span>
 <span style="color: #666666; font-style: italic;">#errorfile    503    /etc/haproxy/errors/503.http</span>
 errorfile    <span style="color: #000000;">400</span>    <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>haproxy<span style="color: #000000; font-weight: bold;">/</span>errors<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">400</span>.http
 errorfile    <span style="color: #000000;">403</span>    <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>haproxy<span style="color: #000000; font-weight: bold;">/</span>errors<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">403</span>.http
 errorfile    <span style="color: #000000;">408</span>    <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>haproxy<span style="color: #000000; font-weight: bold;">/</span>errors<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">408</span>.http
 errorfile    <span style="color: #000000;">500</span>    <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>haproxy<span style="color: #000000; font-weight: bold;">/</span>errors<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">500</span>.http
 errorfile    <span style="color: #000000;">502</span>    <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>haproxy<span style="color: #000000; font-weight: bold;">/</span>errors<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">502</span>.http
 errorfile    <span style="color: #000000;">503</span>    <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>haproxy<span style="color: #000000; font-weight: bold;">/</span>errors<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">503</span>.http
 errorfile    <span style="color: #000000;">504</span>    <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>haproxy<span style="color: #000000; font-weight: bold;">/</span>errors<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">504</span>.http</pre></div></div><p
style="text-align: justify;">As you can see on my configuration file, the checks for the main servers are made on port 5381 but the servers listen on 5380. The trick is that we add a little iptables rules to redirect everything to the port 5381 to the port 5380 so that when we want the front to serve request, it does. But if we want to take it down, we remove the rule, letting HAProxy thinking it's down and forwarding the request to the backup, which is in fact the same server. Then we wait a little to let the users finish their connections and we can take the server down properly. When everything that needed to be fixed is done, we re-add the rule and voila ! it's working.</p><p
style="text-align: justify;">Here are the rules :</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;">iptables <span style="color: #660033;">-t</span> nat <span style="color: #660033;">-A</span> OUTPUT <span style="color: #660033;">-d</span> 192.168.1.1 <span style="color: #660033;">-p</span> tcp <span style="color: #660033;">--dport</span> <span style="color: #000000;">5381</span> <span style="color: #660033;">-j</span> DNAT <span style="color: #660033;">--to-dest</span> :<span style="color: #000000;">5380</span>
iptables <span style="color: #660033;">-t</span> nat <span style="color: #660033;">-A</span> OUTPUT <span style="color: #660033;">-d</span> 192.168.1.2 <span style="color: #660033;">-p</span> tcp <span style="color: #660033;">--dport</span> <span style="color: #000000;">5381</span> <span style="color: #660033;">-j</span> DNAT <span style="color: #660033;">--to-dest</span> :<span style="color: #000000;">5380</span></pre></div></div><p
style="text-align: justify;">But as you may know, if you reboot your server, your iptables rules will be lost. So I created a script that is launched every time the <a
href="http://blog.christory.net/tag/network/" class="st_tag internal_tag" rel="tag" title="Posts tagged with network">network</a> is started/restarted :</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/sh</span>
iptables <span style="color: #660033;">-t</span> nat <span style="color: #660033;">-D</span> OUTPUT <span style="color: #660033;">-d</span> 192.168.1.1 <span style="color: #660033;">-p</span> tcp <span style="color: #660033;">--dport</span> <span style="color: #000000;">5381</span> <span style="color: #660033;">-j</span> DNAT <span style="color: #660033;">--to-dest</span> :<span style="color: #000000;">5380</span>
iptables <span style="color: #660033;">-t</span> nat <span style="color: #660033;">-D</span> OUTPUT <span style="color: #660033;">-d</span> 192.168.1.2 <span style="color: #660033;">-p</span> tcp <span style="color: #660033;">--dport</span> <span style="color: #000000;">5381</span> <span style="color: #660033;">-j</span> DNAT <span style="color: #660033;">--to-dest</span> :<span style="color: #000000;">5380</span>
iptables <span style="color: #660033;">-t</span> nat <span style="color: #660033;">-A</span> OUTPUT <span style="color: #660033;">-d</span> 192.168.1.1 <span style="color: #660033;">-p</span> tcp <span style="color: #660033;">--dport</span> <span style="color: #000000;">5381</span> <span style="color: #660033;">-j</span> DNAT <span style="color: #660033;">--to-dest</span> :<span style="color: #000000;">5380</span>
iptables <span style="color: #660033;">-t</span> nat <span style="color: #660033;">-A</span> OUTPUT <span style="color: #660033;">-d</span> 192.168.1.2 <span style="color: #660033;">-p</span> tcp <span style="color: #660033;">--dport</span> <span style="color: #000000;">5381</span> <span style="color: #660033;">-j</span> DNAT <span style="color: #660033;">--to-dest</span> :<span style="color: #000000;">5380</span></pre></div></div><p
style="text-align: justify;">The line with -D first remove anything that can still be here from a previous launch of the script otherwise you'll see your rules ten times in a iptables -L -t nat, which I think might cause delay.</p><p
style="text-align: justify;">we called it iptables-haproxy.sh and added the following line to /etc/network/interfaces (on Debian) right after the ip configuration of your interface:</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;">post-up <span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">bash</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>haproxy<span style="color: #000000; font-weight: bold;">/</span>iptables-haproxy.sh</pre></div></div><p
style="text-align: justify;">Now, if we want to take down a server, we have two scripts, one per server :<br
/> remove-front1.sh</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/sh</span>
iptables <span style="color: #660033;">-t</span> nat <span style="color: #660033;">-D</span> OUTPUT <span style="color: #660033;">-d</span> 192.168.1.1 <span style="color: #660033;">-p</span> tcp <span style="color: #660033;">--dport</span> <span style="color: #000000;">2381</span> <span style="color: #660033;">-j</span> DNAT <span style="color: #660033;">--to-dest</span> :<span style="color: #000000;">2380</span></pre></div></div><p
style="text-align: justify;">remote-front2.sh</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/sh</span>
iptables <span style="color: #660033;">-t</span> nat <span style="color: #660033;">-D</span> OUTPUT <span style="color: #660033;">-d</span> 192.168.1.2 <span style="color: #660033;">-p</span> tcp <span style="color: #660033;">--dport</span> <span style="color: #000000;">2381</span> <span style="color: #660033;">-j</span> DNAT <span style="color: #660033;">--to-dest</span> :<span style="color: #000000;">2380</span></pre></div></div><p
style="text-align: justify;">When all the fixes are finished, we just run the iptables-haproxy.sh script and we are good to go.</p><p
style="text-align: justify;">That's pretty much it regarding HAProxy, I'm sure we can tweak the config file a little more, but that's working for us as it is.</p><p
style="text-align: justify;">Also, be sure to apply those configs on BOTH your servers, as we want any of them to be able to take the proxy role at anytime. (Here again, puppet is the way to go)</p><p
style="text-align: justify;">One quick note before continuing to the High-Availability part of this article.</p><p
style="text-align: justify;">We are using Nginx as webserver, and one thing we didn't do the first time was modifying the way Nginx was logging things. We quickly realized that my log files only contained the ip of the active proxy server, which was normal because, well it's a proxy. It's easy to modify the way nginx save logs. Open the file /etc/nginx.conf and add/modify :</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># configure log format</span>
 log_format main <span style="color: #ff0000;">'$http_x_forwarded_for - $remote_user [$time_local] '</span>
 <span style="color: #ff0000;">'&quot;$request&quot; $status  $body_bytes_sent &quot;$http_referer&quot; '</span>
 <span style="color: #ff0000;">'&quot;$http_user_agent&quot; &quot;$remote_addr&quot;'</span>;
&nbsp;
 access_log  <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>log<span style="color: #000000; font-weight: bold;">/</span>nginx<span style="color: #000000; font-weight: bold;">/</span>access.log main;</pre></div></div><p
style="text-align: justify;">So that the IP address of the client will be logged at first, and at the end of the line we keep the proxy address just for logging purpose.</p><p
style="text-align: justify;">Another thing you might to add to you Nginx (or apache) configuration, is a rule that prevent the logging of the check.txt, as HAProxy is going to access it every two seconds. This is a quick rule you have to add in your Vhost(s) file under the server section :</p><p
style="text-align: justify;"><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;">location = <span style="color: #000000; font-weight: bold;">/</span>check.txt <span style="color: #7a0874; font-weight: bold;">&#123;</span>
 root <span style="color: #000000; font-weight: bold;">/</span>whatever<span style="color: #000000; font-weight: bold;">/</span>is<span style="color: #000000; font-weight: bold;">/</span>your<span style="color: #000000; font-weight: bold;">/</span>www<span style="color: #000000; font-weight: bold;">/</span>root;
 access_log off;
 expires 30d;
 <span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div><p
style="text-align: justify;">Before going on with the third part, you could test your HAProxy setup by attaching the FailOverIp to one of the server and test that everything is working, then attach the IP on the other server and test it too.</p><h3 style="text-align: justify;">3/ The High-Availability : Heartbeat</h3><p
style="text-align: justify;">Now comes the tricky stuff, the high-availability. We want to have our mini-cluster (that can easily be extended) to be always up, no matter what happens to any machine. In the mean time, we don't have a very big budget so we want to keep things at minimal, that's why we don't have an external load-balancer because we would need two for the HA.</p><p
style="text-align: justify;">What we're going to use to make the HA possible, is Heartbeat from the <a
title="Linux HA" href="http://www.linux-ha.org/" target="_blank">Linux-HA</a> suite. Heartbeat can be difficult to configure, but I summed up different things to make that easier:</p><p
style="text-align: justify;">First, install heartbeat :</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">aptitude</span> <span style="color: #c20cb9; font-weight: bold;">install</span> heartbeat</pre></div></div><p
style="text-align: justify;">Then we need to adapt/create some configuration files :<br
/> ha.cf :</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># keepalive: how many seconds between heartbeats</span>
keepalive <span style="color: #000000;">2</span>
<span style="color: #666666; font-style: italic;"># deadtime: seconds-to-declare-host-dead</span>
deadtime <span style="color: #000000;">10</span>
<span style="color: #666666; font-style: italic;"># What UDP port to use for udp or ppp-udp communication ?</span>
udpport        <span style="color: #000000;">694</span>
ucast eth0 192.168.1.2 <span style="color: #666666; font-style: italic;"># ip address of the HA peer, don't forget to edit that on each server</span>
<span style="color: #666666; font-style: italic;"># What interfaces to heartbeat over?</span>
udp     eth0
<span style="color: #666666; font-style: italic;"># Facility to use for syslog()/logger (alternative to log/debugfile)</span>
logfacility     local0
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Tell what machines are in the cluster</span>
<span style="color: #666666; font-style: italic;"># node    nodename ...    -- must match uname -n</span>
node    front1
node    front2
<span style="color: #666666; font-style: italic;"># If on, the master get the control once it's back, you might want to check the errors before allowing that, so let it off</span>
auto_failback off</pre></div></div><p
style="text-align: justify;">Note : If you set auto_failback to off, your master server won't become master automatically when it restart, you will have to restart the actual Heartbeat master so that the original one could get it's status back.</p><p
style="text-align: justify;">authkeys :</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;">auth <span style="color: #000000;">3</span>
<span style="color: #000000;">3</span> md5 yourubersecretkey</pre></div></div><p
style="text-align: justify;">haresources:</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#Here you specify the uname -n of your master heartbeat server,</span>
<span style="color: #666666; font-style: italic;">#You specify what to do when it goes down,</span>
<span style="color: #666666; font-style: italic;">#Here we use a pre-made script that will that the FailOverIp and assign it to itself.</span>
Front1 IPaddr::192.168.1.3<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">32</span><span style="color: #000000; font-weight: bold;">/</span>eth0</pre></div></div><p
style="text-align: justify;">That last configuration files does all the magic regarding the FailOverIP, it uses a script that comes with the Heartbeat install that, when something happens, like a peer down or up, configure the IP on the server or take it down automatically. This way if a server crashes in the night, it does takeover by itself and nothing goes down more than a few seconds.</p><p
style="text-align: justify;">And that's it for heartbeat, hopefully I didn't forget anything and you're good to go. You can now test your setup by shutting down the master Heartbeat and watch the second one get the FailOverIp address. Try this with a ping and you should see a very short downtime.</p><h3 style="text-align: justify;">4/ Conclusion</h3><p
style="text-align: justify;">That is it for the first part of this series of articles.<br
/> We are now have a load-balanced front-end that is able to survive the death of one of the servers.<br
/> Next time we will see how to effectively share data between those servers, and how to apply the same load-balanced/high-availability concept with the back-end as in Mysql-back-end.</p><p
style="text-align: justify;">I hope you enjoyed that article, feel free to comment/ask questions !</p><p
style="text-align: justify;">Sources :</p><p
style="text-align: justify;">Here's is a list of websites I used while designing the whole thing :</p><p
style="text-align: justify;"><a
href="http://blog.guiguiabloc.fr/" target="_blank">Guiguiabloc's blog</a></p><p
style="text-align: justify;"><a
href="http://www.haproxy.org" target="_blank">HAProxy</a></p><p
style="text-align: justify;"><a
href="http://www.linux-ha.org/" target="_blank">Linux-HA</a></p><p
style="text-align: justify;"><a
href="http://www.howtoforge.org" target="_blank">HowToForge</a></p>Tags: <a
href="http://blog.christory.net/tag/administration/" title="administration" rel="tag">administration</a>, <a
href="http://blog.christory.net/tag/failover/" title="failover" rel="tag">failover</a>, <a
href="http://blog.christory.net/tag/haproxy/" title="HAProxy" rel="tag">HAProxy</a>, <a
href="http://blog.christory.net/tag/heartbeat/" title="heartbeat" rel="tag">heartbeat</a>, <a
href="http://blog.christory.net/tag/linux/" title="Linux" rel="tag">Linux</a>, <a
href="http://blog.christory.net/tag/load-balancer/" title="load balancer" rel="tag">load balancer</a>, <a
href="http://blog.christory.net/tag/nginx/" title="Nginx" rel="tag">Nginx</a>, <a
href="http://blog.christory.net/tag/webpulser/" title="webpulser" rel="tag">webpulser</a><br
/> ]]></content:encoded> <wfw:commentRss>http://blog.christory.net/2009/09/15/building-an-easy-and-scalable-load-balanced-high-availability-web-hosting-solution-part-one-the-front/feed/</wfw:commentRss> <slash:comments>11</slash:comments> </item> <item><title>Welcome !</title><link>http://blog.christory.net/2009/08/03/welcome/</link> <comments>http://blog.christory.net/2009/08/03/welcome/#comments</comments> <pubDate>Sun, 02 Aug 2009 23:11:51 +0000</pubDate> <dc:creator>Thomas Christory</dc:creator> <category><![CDATA[Various]]></category> <category><![CDATA[administration]]></category> <category><![CDATA[bash]]></category> <category><![CDATA[Cisco]]></category> <category><![CDATA[Linux]]></category> <category><![CDATA[network]]></category> <category><![CDATA[pre]]></category><guid isPermaLink="false">http://blog.christory.net/?p=5</guid> <description><![CDATA[Hi All, Welcome on my new blog focused on network administration, systems administration, Cisco, Linux and stuffs. See you soon. ./start_blog Tags: administration, bash, Cisco, Linux, network, pre]]></description> <content:encoded><![CDATA[<div
class="tweetmeme_button" style="float: right; margin-left: 10px;"> <a
href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.christory.net%2F2009%2F08%2F03%2Fwelcome%2F"><br
/> <img
src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.christory.net%2F2009%2F08%2F03%2Fwelcome%2F&amp;source=thomaschristory&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br
/> </a></div><p>Hi All,</p><p>Welcome on my new blog focused on <a
href="http://blog.christory.net/tag/network/" class="st_tag internal_tag" rel="tag" title="Posts tagged with network">network</a> <a
href="http://blog.christory.net/tag/administration/" class="st_tag internal_tag" rel="tag" title="Posts tagged with administration">administration</a>, systems <a
href="http://blog.christory.net/tag/administration/" class="st_tag internal_tag" rel="tag" title="Posts tagged with administration">administration</a>, <a
href="http://blog.christory.net/tag/cisco/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Cisco">Cisco</a>, <a
href="http://blog.christory.net/tag/linux/" class="st_tag internal_tag" rel="tag" title="Posts tagged with Linux">Linux</a> and stuffs. <img
src='http://static.christory.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><p>See you soon.</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;">.<span style="color: #000000; font-weight: bold;">/</span>start_blog</pre></div></div>Tags: <a
href="http://blog.christory.net/tag/administration/" title="administration" rel="tag">administration</a>, <a
href="http://blog.christory.net/tag/bash/" title="bash" rel="tag">bash</a>, <a
href="http://blog.christory.net/tag/cisco/" title="Cisco" rel="tag">Cisco</a>, <a
href="http://blog.christory.net/tag/linux/" title="Linux" rel="tag">Linux</a>, <a
href="http://blog.christory.net/tag/network/" title="network" rel="tag">network</a>, <a
href="http://blog.christory.net/tag/pre/" title="pre" rel="tag">pre</a><br
/> ]]></content:encoded> <wfw:commentRss>http://blog.christory.net/2009/08/03/welcome/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss><!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk
Page Caching using disk (enhanced)
Database Caching 10/87 queries in 0.016 seconds using disk
Object Caching 1684/1812 objects using disk
Content Delivery Network via static.christory.net

Served from: blog.christory.net @ 2012-05-08 16:02:15 -->

