Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Who Needs Clouds?: HA in Your Datacenter

Avatar for Paul Hinze Paul Hinze
September 28, 2012

Who Needs Clouds?: HA in Your Datacenter

Tony Pitluga and Paul Hinze at Surge Conference 2012

Building highly available services can be a challenge. At Braintree, we value simplicity, open source and cheap commodity hardware. While many companies attempt to achieve high-availability through expensive, proprietary components like SANs and hardware load balancers, these sorts of devices are fraught with their own peril. We'll describe how we built a robust infrastructure using off-the-shelf hardware, Linux-based tools, and a few custom applications to tie everything together. By open-sourcing our work and telling our story, we'll hope to share with the community what we believe is a clean, elegant strategy for structuring highly available services of all shapes and sizes.

Avatar for Paul Hinze

Paul Hinze

September 28, 2012
Tweet

More Decks by Paul Hinze

Other Decks in Technology

Transcript

  1. > 1 million API calls per day $ $ $

    $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $$ $ $ $ $ $ important
  2. 204.109.13.100 app01 204.109.13.7 load01 10.0.0.1 100 10.0.0.2 100 ... 10.0.0.{N}

    {W} POST /transactions 10.0.0.1 201 Created app02 app{N} balancing act 1 2 3 4
  3. 204.109.13.100 app01 204.109.13.7 load01 10.0.0.1 100 10.0.0.2 100 ... 10.0.0.{N}

    {W} POST /transactions 10.0.0.1 201 Created app02 app{N} (1) ip virtual server
  4. 204.109.13.100 app01 204.109.13.7 load01 10.0.0.1 100 10.0.0.2 100 ... 10.0.0.{N}

    {W} POST /transactions 10.0.0.1 201 Created app02 app{N} (2) litmus_paper litmus_paper 100
  5. 204.109.13.100 app01 204.109.13.7 load01 10.0.0.1 100 10.0.0.2 100 ... 10.0.0.{N}

    {W} POST /transactions 10.0.0.1 201 Created app02 app{N} (3) big_brother litmus_paper 201 Created big_brother 100
  6. on your mark iptables --table mangle \ --append PREROUTING \

    --destination 205.109.13.7/32 \ --interface eth70 \ --protocol tcp \ --match tcp --dport 443 \ --jump MARK --set-mark 0x07
  7. iptables --table mangle \ --append PREROUTING \ --destination 205.109.13.7/32 \

    --interface eth70 \ --protocol tcp \ --match tcp --dport 443 \ --jump MARK --set-mark 0x07 on your mark
  8. 204.109.13.100 app01 204.109.13.7 load01 10.0.0.1 100 10.0.0.2 100 ... 10.0.0.{N}

    {W} POST /transactions 10.0.0.1 201 Created app02 app{N} now you’re balancing with FOSS!
  9. a litmus_paper check service "webapp" do |s| s.depends Dependency::HTTP, "http://localhost:3000/heartbeat"

    s.measure_health Metric::CPULoad, :weight => 50 s.measure_health Metric::AvailableMemory, :weight => 50 end
  10. a litmus_paper check service "webapp" do |s| s.depends Dependency::HTTP, "http://localhost:3000/heartbeat"

    s.measure_health Metric::CPULoad, :weight => 50 s.measure_health Metric::AvailableMemory, :weight => 50 end services i *require* to be useful
  11. a litmus_paper check service "webapp" do |s| s.depends Dependency::HTTP, "http://localhost:3000/heartbeat"

    s.measure_health Metric::CPULoad, :weight => 50 s.measure_health Metric::AvailableMemory, :weight => 50 end how healthy am i generally?
  12. easy to extend require 'postfix_litmus' service "mailman" do |s| s.depends

    PostfixLitmus::Dependency, "localhost:543" s.measure_health PostfixLitmus::MailQSize, :max_size => 1000, :weight => 100 end
  13. Maintenance w/ litmusctl $ litmusctl force down webapp Reason? apt

    upgrades $ curl localhost/webapp/status Health: 0 apt upgrades
  14. 204.109.13.100 app01 204.109.13.7 load01 10.0.0.1 100 10.0.0.2 100 ... 10.0.0.{N}

    {W} POST /transactions 10.0.0.1 201 Created app02 app{N} litmus keeping tabs litmus_paper litmus_paper litmus_paper 100 92 55
  15. it’s simple, really while true health = `curl node/app/status \

    | grep Health \ | awk ‘{print $2}’` `ipvsadm --edit-server --weight #{health}` sleep 2 end
  16. config, brother webapp: checkInterval: 2000 scheduler: wlc fwmark: 7 nodes:

    - address: 10.0.0.1 port: 80 path: /webapp/status - address: 10.0.0.2 port: 80 path: /webapp/status
  17. 204.109.13.100 app01 204.109.13.7 load01 10.0.0.1 100 10.0.0.2 100 ... 10.0.0.{N}

    {W} POST /transactions 10.0.0.1 201 Created app02 app{N} big_brother is watching litmus_paper litmus_paper litmus_paper 100 92 55 big_brother 92
  18. 15 load01 new kid on the block app01 app02 10

    app03 25 30% 20% 50% app04 100 yeah!
  19. 15 load01 accosted like a boy band app01 app02 10

    app03 25 10% 6% 16% app04 100 66%
  20. load01 accosted like a boy band app04 66% 5 ouch!

    15 app01 app02 10 app03 25 10% 6% 16%
  21. config, brother webapp: checkInterval: 2000 scheduler: wlc fwmark: 7 ramp_up_time:

    120 nodes: - address: 10.0.0.1 port: 80 path: /webapp/status - address: 10.0.0.2 port: 80 path: /webapp/status try this
  22. 15 load01 Humble kid on the block app01 app02 10

    app03 25 30% 20% 50% app04 5 easy now
  23. 15 load01 ease off the pressure 10 25 27% 18%

    45% app04 5 9% app01 app02 app03
  24. 15 load01 ease off the pressure 10 25 25% 16%

    41% app04 5 16% app01 app02 app03
  25. 78 load01 we all get healthy together 82 95 app04

    93 app01 app02 app03 23% 24% 27% 26%
  26. 204.109.13.100 app01 204.109.13.7 load01 10.0.0.1 100 10.0.0.2 100 ... 10.0.0.{N}

    {W} POST /transactions 10.0.0.1 201 Created app02 app{N} big_brother is watching litmus_paper litmus_paper litmus_paper 100 92 55 big_brother 92 201 Created
  27. XmHELL <group description="Braintree Webapp" id="webapp_group"> <primitive class="ocf" id="ipvs_webapp" provider="braintree" type="ocf_big_brother">

    <instance_attributes id="ipvs_webapp_ia"> <nvpair id="ipvs_monitor_webapp_cluster" name="cluster" value="webapp"/> </instance_attributes> <operations> <op id="ipvs_webapp_op_start" interval="0" name="start" timeout="20s"/> <op id="ipvs_webapp_op_stop" interval="0" name="stop" timeout="40s"/> <op id="ipvs_webapp_op_monitor" interval="61s" name="monitor" timeout="30s"/> </operations> </primitive> <primitive class="ocf" id="ip_204.109.13.7" provider="heartbeat" type="IPaddr2"> <instance_attributes id="ip_204.109.13.7_ia"> <nvpair id="ip_204.109.13.7_ip" name="ip" value="204.109.13.7"/> <nvpair id="ip_204.109.13.7_nm" name="cidr_netmask" value="32"/> <nvpair id="ip_204.109.13.7_nic" name="nic" value="eth70"/> </instance_attributes> <operations> <op id="ip_204.109.13.7_op_start" interval="0" name="start" timeout="30s"/> <op id="ip_204.109.13.7_op_stop" interval="0" name="stop" timeout="90s"/> <op id="ip_204.109.13.7_op_monitor" interval="61s" name="monitor" timeout="30s"/> </operations> </primitive> </group>
  28. groups flock together <group description="Braintree Webapp" id="webapp_group"> <primitive class="ocf" id="ipvs_webapp"

    provider="braintree" type="ocf_big_brother"> <instance_attributes id="ipvs_webapp_ia"> <nvpair id="ipvs_monitor_webapp_cluster" name="cluster" value="webapp"/> </instance_attributes> <operations> <op id="ipvs_webapp_op_start" interval="0" name="start" timeout="20s"/> <op id="ipvs_webapp_op_stop" interval="0" name="stop" timeout="40s"/> <op id="ipvs_webapp_op_monitor" interval="61s" name="monitor" timeout="30s"/> </operations> </primitive> <primitive class="ocf" id="ip_204.109.13.7" provider="heartbeat" type="IPaddr2"> <instance_attributes id="ip_204.109.13.7_ia"> <nvpair id="ip_204.109.13.7_ip" name="ip" value="204.109.13.7"/> <nvpair id="ip_204.109.13.7_nm" name="cidr_netmask" value="32"/> <nvpair id="ip_204.109.13.7_nic" name="nic" value="eth70"/> </instance_attributes> <operations> <op id="ip_204.109.13.7_op_start" interval="0" name="start" timeout="30s"/> <op id="ip_204.109.13.7_op_stop" interval="0" name="stop" timeout="90s"/> <op id="ip_204.109.13.7_op_monitor" interval="61s" name="monitor" timeout="30s"/> </operations> </primitive> </group>
  29. the ipvs resource <group description="Braintree Webapp" id="webapp_group"> <primitive class="ocf" id="ipvs_webapp"

    provider="braintree" type="ocf_big_brother"> <instance_attributes id="ipvs_webapp_ia"> <nvpair id="ipvs_monitor_webapp_cluster" name="cluster" value="webapp"/> </instance_attributes> <operations> <op id="ipvs_webapp_op_start" interval="0" name="start" timeout="20s"/> <op id="ipvs_webapp_op_stop" interval="0" name="stop" timeout="40s"/> <op id="ipvs_webapp_op_monitor" interval="61s" name="monitor" timeout="30s"/> </operations> </primitive> <primitive class="ocf" id="ip_204.109.13.7" provider="heartbeat" type="IPaddr2"> <instance_attributes id="ip_204.109.13.7_ia"> <nvpair id="ip_204.109.13.7_ip" name="ip" value="204.109.13.7"/> <nvpair id="ip_204.109.13.7_nm" name="cidr_netmask" value="32"/> <nvpair id="ip_204.109.13.7_nic" name="nic" value="eth70"/> </instance_attributes> <operations> <op id="ip_204.109.13.7_op_start" interval="0" name="start" timeout="30s"/> <op id="ip_204.109.13.7_op_stop" interval="0" name="stop" timeout="90s"/> <op id="ip_204.109.13.7_op_monitor" interval="61s" name="monitor" timeout="30s"/> </operations> </primitive> </group>
  30. the ipvs important bits <group description="Braintree Webapp" id="webapp_group"> <primitive class="ocf"

    id="ipvs_webapp" provider="braintree" type="ocf_big_brother"> <instance_attributes id="ipvs_webapp_ia"> <nvpair id="ipvs_monitor_webapp_cluster" name="cluster" value="webapp"/> </instance_attributes> <operations> <op id="ipvs_webapp_op_start" interval="0" name="start" timeout="20s"/> <op id="ipvs_webapp_op_stop" interval="0" name="stop" timeout="40s"/> <op id="ipvs_webapp_op_monitor" interval="61s" name="monitor" timeout="30s"/> </operations> </primitive> <primitive class="ocf" id="ip_204.109.13.7" provider="heartbeat" type="IPaddr2"> <instance_attributes id="ip_204.109.13.7_ia"> <nvpair id="ip_204.109.13.7_ip" name="ip" value="204.109.13.7"/> <nvpair id="ip_204.109.13.7_nm" name="cidr_netmask" value="32"/> <nvpair id="ip_204.109.13.7_nic" name="nic" value="eth70"/> </instance_attributes> <operations> <op id="ip_204.109.13.7_op_start" interval="0" name="start" timeout="30s"/> <op id="ip_204.109.13.7_op_stop" interval="0" name="stop" timeout="90s"/> <op id="ip_204.109.13.7_op_monitor" interval="61s" name="monitor" timeout="30s"/> </operations> </primitive> </group>
  31. the ipaddr resource <group description="Braintree Webapp" id="webapp_group"> <primitive class="ocf" id="ipvs_webapp"

    provider="braintree" type="ocf_big_brother"> <instance_attributes id="ipvs_webapp_ia"> <nvpair id="ipvs_monitor_webapp_cluster" name="cluster" value="webapp"/> </instance_attributes> <operations> <op id="ipvs_webapp_op_start" interval="0" name="start" timeout="20s"/> <op id="ipvs_webapp_op_stop" interval="0" name="stop" timeout="40s"/> <op id="ipvs_webapp_op_monitor" interval="61s" name="monitor" timeout="30s"/> </operations> </primitive> <primitive class="ocf" id="ip_204.109.13.7" provider="heartbeat" type="IPaddr2"> <instance_attributes id="ip_204.109.13.7_ia"> <nvpair id="ip_204.109.13.7_ip" name="ip" value="204.109.13.7"/> <nvpair id="ip_204.109.13.7_nm" name="cidr_netmask" value="32"/> <nvpair id="ip_204.109.13.7_nic" name="nic" value="eth70"/> </instance_attributes> <operations> <op id="ip_204.109.13.7_op_start" interval="0" name="start" timeout="30s"/> <op id="ip_204.109.13.7_op_stop" interval="0" name="stop" timeout="90s"/> <op id="ip_204.109.13.7_op_monitor" interval="61s" name="monitor" timeout="30s"/> </operations> </primitive> </group>
  32. the ipaddr important bits <group description="Braintree Webapp" id="webapp_group"> <primitive class="ocf"

    id="ipvs_webapp" provider="braintree" type="ocf_big_brother"> <instance_attributes id="ipvs_webapp_ia"> <nvpair id="ipvs_monitor_webapp_cluster" name="cluster" value="webapp"/> </instance_attributes> <operations> <op id="ipvs_webapp_op_start" interval="0" name="start" timeout="20s"/> <op id="ipvs_webapp_op_stop" interval="0" name="stop" timeout="40s"/> <op id="ipvs_webapp_op_monitor" interval="61s" name="monitor" timeout="30s"/> </operations> </primitive> <primitive class="ocf" id="ip_204.109.13.7" provider="heartbeat" type="IPaddr2"> <instance_attributes id="ip_204.109.13.7_ia"> <nvpair id="ip_204.109.13.7_ip" name="ip" value="204.109.13.7"/> <nvpair id="ip_204.109.13.7_nm" name="cidr_netmask" value="32"/> <nvpair id="ip_204.109.13.7_nic" name="nic" value="eth70"/> </instance_attributes> <operations> <op id="ip_204.109.13.7_op_start" interval="0" name="start" timeout="30s"/> <op id="ip_204.109.13.7_op_stop" interval="0" name="stop" timeout="90s"/> <op id="ip_204.109.13.7_op_monitor" interval="61s" name="monitor" timeout="30s"/> </operations> </primitive> </group>
  33. XmHELL <group description="Braintree Webapp" id="webapp_group"> <primitive class="ocf" id="ipvs_webapp" provider="braintree" type="ocf_big_brother">

    <instance_attributes id="ipvs_webapp_ia"> <nvpair id="ipvs_monitor_webapp_cluster" name="cluster" value="webapp"/> </instance_attributes> <operations> <op id="ipvs_webapp_op_start" interval="0" name="start" timeout="20s"/> <op id="ipvs_webapp_op_stop" interval="0" name="stop" timeout="40s"/> <op id="ipvs_webapp_op_monitor" interval="61s" name="monitor" timeout="30s"/> </operations> </primitive> <primitive class="ocf" id="ip_204.109.13.7" provider="heartbeat" type="IPaddr2"> <instance_attributes id="ip_204.109.13.7_ia"> <nvpair id="ip_204.109.13.7_ip" name="ip" value="204.109.13.7"/> <nvpair id="ip_204.109.13.7_nm" name="cidr_netmask" value="32"/> <nvpair id="ip_204.109.13.7_nic" name="nic" value="eth70"/> </instance_attributes> <operations> <op id="ip_204.109.13.7_op_start" interval="0" name="start" timeout="30s"/> <op id="ip_204.109.13.7_op_stop" interval="0" name="stop" timeout="90s"/> <op id="ip_204.109.13.7_op_monitor" interval="61s" name="monitor" timeout="30s"/> </operations> </primitive> </group>
  34. puppetize! node "load1" { pacemaker::ipvs_resource { "webapp": description => "Braintree

    Webapp", supervisor_id => "webapp", ip_resources => [ { 'address' => '204.109.13.7', 'nic' => 'eth10' } ] } }
  35. 201 Created 204.109.13.7 load02 10.0.0.1 100 10.0.0.2 100 ... 10.0.0.{N}

    {W} POST /transactions 201 Created big_brother 92 load01 load03 204.109.13.100 app01 10.0.0.1 app02 app{N} litmus_paper 100 litmus_paper litmus_paper 92 55
  36. 204.109.13.100 app01 204.109.13.7 load02 10.0.0.1 100 10.0.0.2 100 ... 10.0.0.{N}

    {W} POST /transactions 10.0.0.1 201 Created app02 app{N} litmus_paper litmus_paper litmus_paper 100 92 55 big_brother 92 load01 load03 201 Created