前面寫過
2篇文章介紹過OpenStack,今天介紹一下配合Haproxy實(shí)現(xiàn)Web application auto scaling。
在用OpenStack實(shí)施云計(jì)算之前,要實(shí)現(xiàn)應(yīng)用的水平擴(kuò)展,通常是用這樣的架構(gòu):
一臺(tái)Haproxy將動(dòng)態(tài)請(qǐng)求轉(zhuǎn)發(fā)到N臺(tái)nginx服務(wù)器,當(dāng)流量增加的時(shí)候,我們需要手工安裝物理的服務(wù)器,將它添加到集群中去,然后再手工修改haproxy的配置,讓它生效。就算用自動(dòng)化的安裝管理工具,這樣擴(kuò)展一臺(tái)機(jī)器也差不多要3~4小時(shí)。
用OpenStack實(shí)施云計(jì)算之后,整個(gè)架構(gòu)和上圖是一樣的,但是我們可以通過幾十行代碼在5分鐘內(nèi)實(shí)現(xiàn)auto scaling,來看一下具體的步驟:
首先,我們先在OpenStack上的一臺(tái)虛擬機(jī)安裝好nginx以及其他應(yīng)用,然后對(duì)它做一個(gè)snapshot:
記錄一下這個(gè)snapshot的ID:
接下來寫一個(gè)腳本,能夠用這個(gè)snapshot來自動(dòng)的創(chuàng)建實(shí)例,因?yàn)槲覍?duì)Ruby比較熟悉,這里用Ruby的
openstack-computegem 來寫(OpenStack有多種客戶端可以調(diào)用API,比如python,php):
- require 'rubygems'
- require 'openstack/compute'
-
- username = 'quake'
- api_key = 'password'
- auth_url = 'http://10.199.21.210:5000/v2.0/'
- image_id = '9'
- flavor_id = '1'
-
- cs = OpenStack::Compute::Connection.new(:username => username, :api_key => api_key, :auth_url => auth_url)
- image = cs.get_image(image_id)
- flavor = cs.get_flavor(flavor_id)
-
- newserver = cs.create_server(:name => "rails#{Time.now.strftime("%Y%m%d%H%M")}", :imageRef => image.id, :flavorRef => flavor.id)
- p "New Server #{newserver.name} created"
-
- while newserver.progress < 100
- p "Server status #{newserver.status}, progress #{newserver.progress}"
- sleep 10
- newserver.refresh
- end
- p "Server status #{newserver.status}, progress #{newserver.progress}"
- p "Done"
當(dāng)需要擴(kuò)展一臺(tái)新的nginx instance時(shí)候,只需要執(zhí)行上面的代碼:
- # ruby create_new_server.rb
- "New Server rails201112161042 created"
- "Server status BUILD, progress 0"
- "Server status ACTIVE, progress 100"
- "Done"
差不多30秒左右的時(shí)間(視你的鏡像大小和網(wǎng)絡(luò)速度),這臺(tái)虛擬機(jī)就創(chuàng)建好了,我們可以在dashboard看到這臺(tái)最新的機(jī)器:
接下去我們?cè)賹懸粋€(gè)腳本,自動(dòng)更新haproxy的配置文件:
- cs = OpenStack::Compute::Connection.new(:username => username, :api_key => api_key, :auth_url => auth_url)
-
- `cp haproxy.cfg.template haproxy.cfg`
-
- File.open('haproxy.cfg', 'a') do |f|
- cs.servers.each do |s|
- server = cs.server(s[:id])
-
- if server.image['id'] == image_id
- ip = server.addresses.first.address
- p "Found matched server #{server.name} #{ip}, add to haproxy"
- f.puts " server #{server.name} #{ip}:80 maxconn 512"
- end
- end
- end
-
-
- `cp haproxy.cfg /etc/haproxy.cfg`
- p "Reload haproxy"
- `/etc/init.d/haproxy reload`
執(zhí)行該代碼:
- # ruby update_haproxy.rb
- "Found matched server rails201112161042 10.199.18.6, add to haproxy"
- "Found matched server rails201112161003 10.199.18.5, add to haproxy"
- "Found matched server rails201112160953 10.199.18.4, add to haproxy"
- "Found matched server rails201112160924 10.199.18.8, add to haproxy"
- "Found matched server rails201112160923 10.199.18.7, add to haproxy"
- "Reload haproxy"
這樣就實(shí)現(xiàn)了將剛剛創(chuàng)建的 rails201112161042 實(shí)例添加到了haproxy集群。
通過不到50行的代碼,就實(shí)現(xiàn)了auto scaling,是不是很方便?我們還能夠更自動(dòng)化一些,配合監(jiān)控腳本,設(shè)定一個(gè)指標(biāo),比如說當(dāng)整個(gè)集群的CPU用量達(dá)到70%的時(shí)候,自動(dòng)調(diào)用create_server,當(dāng)CPU小于10%的時(shí)候,調(diào)用delete_server,這樣就實(shí)現(xiàn)了按需scaling up/down.