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

Who Needs Clouds?: HA in Your Datacenter

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.

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