爲何要用到Rex,由於目前線上業務量愈來愈多,服務器數量也愈來愈多,維護的項目也愈來愈多,不管是安裝軟件,修改配置,優化,管理,升級等操做經過寫一堆腳原本集中操做已經很難達到個人要求。這時候就須要將全部不一樣業務類型不一樣項目所對應的集羣環境都統一塊兒來,集中進行管理。java
經常使用的集中管理軟件有puppet salt ansible Rex等。在進行綜合比對後,我選擇了Rex。緣由是Rex是基於SSH來進行集成管理的,不須要再各個服務節點安裝客戶端,簡潔,輕量,是我選擇Rex的一部分緣由,固然其它的集成管理軟件沒有怎麼研究過,不過Rex已經能知足個人全部要求了,模塊Rex既能夠作爲一個庫來調用,也能夠做爲一個集中管理平臺來使用,經過rex命令來進行一切操做。我對perl很是熟練,對於一些特殊的應用場景我會結合把Rex當作一個普通的模塊,經過在本身的腳本中調用Rex模塊提供的一些方法來進行遠程操做,靈活性,可用性都比較強。這也是我選擇Rex的一個主要緣由。linux
介紹一下我線上的環境:nginx
我要管理7個項目,每一個項目都有一個集羣環境(平均都是4個節點左右),每一個節點上的web服務都是用tomcat7.0+jdk1.7的環境;session共享使用的是兩臺memcache組成的集羣環境,數據庫採用的是二臺高性能的物理機+一個iscsi的盤櫃組成的RAC環境。四臺代理服務器(都是採用的nginx),圖片存儲採用的drbd+heartbeat+nfs的形式,由於是商城網站圖片量如今愈來愈多,訪問量愈來愈多,nfs圖片服務器很容易由於I/O問題變的很是不穩定,目前測試用Moosefs和fastDFS,準備將圖片存儲遷移到分佈式存儲。web
我接手以後就是這麼個環境,固然總體的網絡結構設計的很糟糕,不好勁。不管是從安全性,穩定性,高可用性方面去看都存在缺陷。可是上頭不肯意讓我對架構進行改動,只好對現有的環境進行集中管理。(哎,作運維很難!!)shell
廢話很少說,由於實驗環境有限,我只能爲7個項目準備7個節點,也就是一個項目對應的集羣就是一個節點也就是它本身!(公司窮,沒辦法,內部測試用兩臺pc機加一個組裝的盤櫃搞了一個集羣虛擬化,爲了節約資源只能這樣玩) 數據庫
1,由於是內部測試,爲了方便,每一個節點對應的域名都在hosts文件中解析;json
[root@localhost ~]# cat /etc/hosts 127.0.0.1 mail.weike.com mx localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 #192.168.0.128 test1 #192.168.0.129 test2 192.168.0.164 shopwap 192.168.0.193 gerenwap 192.168.0.196 appwap 192.168.0.224 geren 192.168.0.226 chaoshi 192.168.0.228 quanguo 192.168.0.215 boss
則七個節點對應的域名爲 shopwap gerenwap appwap geren chaoshi quanguo boss(實際上線上的項目遠比這多,有的是單個tomcat節點跑多個實例)vim
2,安裝Rex,在安裝以前須要肯定你已經安裝了perl環境(若是沒有就經過yum install perl cpan進行安裝)緩存
[root@localhost src]# perl -v This is perl 5, version 16, subversion 3 (v5.16.3) built for x86_64-linux-thread-multi (with 28 registered patches, see perl -V for more detail) Copyright 1987-2012, Larry Wall
3,對於全部的perl模塊安裝咱們都用cpanm命令來安裝,到cpan或者metacpan 上去找一個叫App-cpanminus 的源碼包,而後下載下來進行解壓編譯安裝tomcat
[root@StorageServer1 src]# ls -l |grep -i app -rw-r--r-- 1 root root 316814 Sep 16 09:52 App-cpanminus-1.7039.tar.gz [root@StorageServer1 src]# tar zxvf App-cpanminus-1.7039.tar.gz App-cpanminus-1.7039/ App-cpanminus-1.7039/bin/ App-cpanminus-1.7039/Changes App-cpanminus-1.7039/cpanfile App-cpanminus-1.7039/lib/ App-cpanminus-1.7039/LICENSE App-cpanminus-1.7039/Makefile.PL App-cpanminus-1.7039/MANIFEST App-cpanminus-1.7039/MANIFEST.SKIP App-cpanminus-1.7039/META.json App-cpanminus-1.7039/META.yml App-cpanminus-1.7039/README App-cpanminus-1.7039/t/ App-cpanminus-1.7039/t/happy_cpantesters.t App-cpanminus-1.7039/lib/App/ App-cpanminus-1.7039/lib/App/cpanminus/ App-cpanminus-1.7039/lib/App/cpanminus.pm App-cpanminus-1.7039/lib/App/cpanminus/fatscript.pm App-cpanminus-1.7039/bin/cpanm [root@StorageServer1 src]# cd App-cpanminus-1.7039 [root@StorageServer1 App-cpanminus-1.7039]# perl Makefile.PL && make && make install Checking if your kit is complete... Looks good Warning: prerequisite Test::More 0 not found. Writing Makefile for App::cpanminus cp lib/App/cpanminus/fatscript.pm blib/lib/App/cpanminus/fatscript.pm cp lib/App/cpanminus.pm blib/lib/App/cpanminus.pm cp bin/cpanm blib/script/cpanm /usr/bin/perl -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/cpanm Manifying blib/man1/cpanm.1 Manifying blib/man3/App::cpanminus::fatscript.3pm Manifying blib/man3/App::cpanminus.3pm Installing /usr/local/share/perl5/App/cpanminus.pm Installing /usr/local/share/perl5/App/cpanminus/fatscript.pm Installing /usr/local/share/man/man1/cpanm.1 Installing /usr/local/share/man/man3/App::cpanminus::fatscript.3pm Installing /usr/local/share/man/man3/App::cpanminus.3pm Installing /usr/local/bin/cpanm Appending installation info to /usr/lib64/perl5/perllocal.pod [root@StorageServer1 App-cpanminus-1.7039]#
3,安裝完成如今可使用cpanm來安裝Rex了(由於源地址默認都是國外的一些站點,有可能會被屏蔽,因此用163提供的源地址),設置下環境變量:
[root@StorageServer1 ~]# cat .bashrc # .bashrc # User specific aliases and functions alias vi='vim' alias rm='rm -i' alias cp='cp -i' alias mv='mv -i' alias cpanm='cpanm --mirror http://mirrors.163.com/cpan --mirror-only' # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi [root@StorageServer1 ~]#
4安裝rex
root@StorageServer1 ~]# cpanm Rex --> Working on Rex Fetching http://www.cpan.org/authors/id/F/FE/FERKI/Rex-1.3.3.tar.gz ... OK ==> Found dependencies: ExtUtils::MakeMaker
安裝過程當中它本身會解決模塊相關的依賴關係,可能會有一些底層的庫須要手動去安裝,好比我在安裝過程當中就失敗了
! Installing the dependencies failed: Module 'XML::LibXML' is not installed, Module 'XML::Simple' is not installed
! Bailing out the installation for Rex-1.3.3.
提示有個XML::LibXML相關的模塊安裝不成功,這個和它依賴的相關的底層xml庫有關係,因此我將libxml相關的底層庫都安裝一下就好了。
[root@StorageServer1 ~]# yum install libxml*
而後再安裝rex
root@StorageServer1 ~]# cpanm Rex --> Working on Rex Fetching http://www.cpan.org/authors/id/F/FE/FERKI/Rex-1.3.3.tar.gz ... OK ==> Found dependencies: ExtUtils::MakeMaker
5,安裝完成後如今就開始進行管理。
用戶:管理用戶我用tomcat(由於root權限不能給測試人員使用);
模塊:創建7個模塊,每一個模塊對應一個不一樣的項目;
模板:創建兩個模板模塊,將對全部項目節點的統一操做都寫進模板裏,好比批量更新軟件,設置時間,刪除軟件等等。
主機名配置文件:以ini形式保存全部項目的主機名。七個項目創建七個組,每一個組中包含的主機名就是屬於該項目集羣環境中的幾點服務器的主機名(由於集羣就一個節點因此只有一個主機名)
Rexfile:配置文件,rex命令全部的操做都是讀取該文件,全部相似於全局設置的選項都保存在該文件裏。
第一步:創建模板:兩個模板對應的名稱爲:
Template::Service :該模板主要存放服務等相關的操做好比操做tomcat,啓動 關閉 等
Template::File: 該模塊主要發佈項目和一些文件,包括文件內容同步等相關工做
創建tomcat用戶並切換到tomcat目錄下,而後建立rex目錄,進入rex目錄在建立兩個模板;以下:
[
tomcat@StorageServer1 ~]$ pwd /home/tomcat [tomcat@StorageServer1 ~]$ mkdir rex [tomcat@StorageServer1 ~]$ cd rex [tomcat@StorageServer1 rex]$ rexify Template::Service --create-module Creating module Template::Service... mkdir Template/Service Creating template file: __module__.pm Creating template file: meta.yml Your module has been created in Template/Service. [tomcat@StorageServer1 rex]$ rexify Template::File --create-module Creating module Template::File... mkdir Template/File Creating template file: __module__.pm Creating template file: meta.yml Your module has been created in Template/File. [tomcat@StorageServer1 rex]$ ls Template [tomcat@StorageServer1 rex]$ ls -ld Template/* drwxr-xr-x 2 tomcat tomcat 4096 Sep 16 12:18 Template/File drwxr-xr-x 2 tomcat tomcat 4096 Sep 16 12:18 Template/Service
第二步:在rex目錄下創建file.ini文件 裏面存放的主要是操做的主機組以下
[tomcat@StorageServer1 rex]$ ls file.ini Template [tomcat@StorageServer1 rex]$ cat file.ini [quanguo_servers] quanguo [chaoshi_servers] chaoshi [geren_servers] geren [boss_servers] boss [shopwap_servers] shopwap [appwap_servers] appwap [gerenwap_servers] gerenwap [all_servers] @quanguo_servers @chaoshi_servers @geren_servers @boss_servers @shopwap_servers @appwap_servers @gerenwap_servers [tomcat@StorageServer1 rex]$
主機名所對應的ip能夠查看hosts文件
第三步:在rex目錄下創建模塊,總共七個項目,我須要創建七個模塊;
[tomcat@StorageServer1 rex]$ rexify Servers::Appwap --create-module Creating module Servers::Appwap... mkdir Servers/Appwap Creating template file: __module__.pm Creating template file: meta.yml Your module has been created in Servers/Appwap. [tomcat@StorageServer1 rex]$ rexify Servers::Boss --create-module Creating module Servers::Boss... mkdir Servers/Boss Creating template file: __module__.pm Creating template file: meta.yml Your module has been created in Servers/Boss. [tomcat@StorageServer1 rex]$ rexify Servers::Chaoshi --create-module Creating module Servers::Chaoshi... mkdir Servers/Chaoshi Creating template file: __module__.pm Creating template file: meta.yml Your module has been created in Servers/Chaoshi. [tomcat@StorageServer1 rex]$ rexify Servers::Geren --create-module Creating module Servers::Geren... mkdir Servers/Geren Creating template file: __module__.pm Creating template file: meta.yml Your module has been created in Servers/Geren. [tomcat@StorageServer1 rex]$ rexify Servers::Gerenwap --create-module Creating module Servers::Gerenwap... mkdir Servers/Gerenwap Creating template file: __module__.pm Creating template file: meta.yml Your module has been created in Servers/Gerenwap. [tomcat@StorageServer1 rex]$ rexify Servers::Quanguo --create-module Creating module Servers::Quanguo... mkdir Servers/Quanguo Creating template file: __module__.pm Creating template file: meta.yml Your module has been created in Servers/Quanguo. [tomcat@StorageServer1 rex]$ rexify Servers::Shopwap --create-module Creating module Servers::Shopwap... mkdir Servers/Shopwap Creating template file: __module__.pm Creating template file: meta.yml Your module has been created in Servers/Shopwap. [tomcat@StorageServer1 rex]$
查看建立的七個模塊
[tomcat@StorageServer1 rex]$ ls Servers/ -l total 28 drwxr-xr-x 2 tomcat tomcat 4096 Sep 16 12:27 Appwap drwxr-xr-x 2 tomcat tomcat 4096 Sep 16 12:27 Boss drwxr-xr-x 2 tomcat tomcat 4096 Sep 16 12:27 Chaoshi drwxr-xr-x 2 tomcat tomcat 4096 Sep 16 12:27 Geren drwxr-xr-x 2 tomcat tomcat 4096 Sep 16 12:28 Gerenwap drwxr-xr-x 2 tomcat tomcat 4096 Sep 16 12:28 Quanguo drwxr-xr-x 2 tomcat tomcat 4096 Sep 16 12:28 Shopwap [tomcat@StorageServer1 rex]$ ls file.ini Servers Template [tomcat@StorageServer1 rex]$
第五步:在rex目錄下建立Rexfile主配置文件
[tomcat@StorageServer1 rex]$ ls file.ini Rexfile Servers Template
稍後會講Rexfile中的內容是什麼意思(如今能夠忽略Rexfie中的內容只須要建立個Rexfile文件就行);
由於我全部項目都是部署的tomcat7.0+jdk1.7 因此我能夠將重啓 關閉 啓動等服務操做寫到Template::Sevice模塊中以下:
[tomcat@StorageServer1 rex]$ cat Template/Service/__module__.pm package Template::Service; use v5.10; use warnings; use Rex -base; task "shutdown_tomcat",group=>"all_servers",sub { my $server = Rex::get_current_connection()->{server}; for my $proc(ps()){ if($proc->{"command"}=~/java.*?tomcat/i){ run "./shutdown.sh", cwd =>"/usr/local/tomcat/bin", only_if =>"pgrep java"; say "[$server]: tomcat服務關閉完成"; last; }else{ next; } } given($server){ when(/\bchaoshi\b/i){ file "/usr/local/tomcat/webapps/osms",ensure=>"absent"; file "/usr/local/tomcat/work/Catalina",ensure=>"absent"; file "/usr/local/tomcat/webapps/ROOT",ensure=>"absent"; say "[$server:緩存清理完成]"; break;} when(/\bquanguo\b/i){ file "/usr/local/tomcat/webapps/olsm",ensure=>"absent"; file "/usr/local/tomcat/work/Catalina",ensure=>"absent"; file "/usr/local/tomcat/webapps/ROOT",ensure=>"absent"; say "[$server:緩存清理完成]"; break;} when(/\bgeren\b/i){ file "/usr/local/tomcat/webapps/imss",ensure=>"absent"; file "/usr/local/tomcat/work/Catalina",ensure=>"absent"; file "/usr/local/tomcat/webapps/ROOT",ensure=>"absent"; say "[$server:緩存清理完成]"; break;} when(/\bboss\b/i){ file "/usr/local/tomcat/webapps/boss",ensure=>"absent"; file "/usr/local/tomcat/work/Catalina",ensure=>"absent"; file "/usr/local/tomcat/webapps/ROOT",ensure=>"absent"; say "[$server:緩存清理完成]"; break;} when(/\bshopwap\b/i){ file "/usr/local/tomcat/webapps/shopwap",ensure=>"absent"; file "/usr/local/tomcat/work/Catalina",ensure=>"absent"; file "/usr/local/tomcat/webapps/ROOT",ensure=>"absent"; say "[$server:緩存清理完成]"; break;} when(/\bappwap\b/i){ file "/usr/local/tomcat/webapps/moser",ensure=>"absent"; file "/usr/local/tomcat/work/Catalina",ensure=>"absent"; file "/usr/local/tomcat/webapps/ROOT",ensure=>"absent"; say "[$server:緩存清理完成]"; break;} when(/\bgerenwap\b/i){ file "/usr/local/tomcat/webapps/imsswap",ensure=>"absent"; file "/usr/local/tomcat/work/Catalina",ensure=>"absent"; file "/usr/local/tomcat/webapps/ROOT",ensure=>"absent"; say "[$server:緩存清理完成]"; break;} default{ say "沒有該服務";} } say "[$server]: 服務已經關閉"; }; task "start_tomcat",group=>"all_servers",sub { my $server = Rex::get_current_connection()->{server}; if(is_file("/usr/local/tomcat/bin/startup.sh")){ run "./startup.sh",sub { my($stdout,$stderr)=@_; say "[$server]: $stdout"; }, cwd =>"/usr/local/tomcat/bin", unless =>"pgrep java"; }else{ say "[$server]:沒有正確安裝tomcat,請認真檢查服務狀態"; exit 0; } for my $proc(ps()){ if($proc->{"command"}=~/java.*tomcat/i){ say "[$server]: tomcat已經啓動,進程pid:".$proc->{"pid"}; last; }else{ next; } } }; task "restart_tomcat",group=>"all_servers",sub { my $server = Rex::get_current_connection()->{server}; needs 'shutdown_tomcat'; sleep 5; needs 'start_tomcat'; say "[$server]: 服務重啓完成"; }; task "show_time",group=>"all_servers",sub { say run "date"; }; 1;
裏面定義了四個任務,分別爲tomcat的啓動,關閉,重啓,和系統當前時間
第四步:調用該模板,查看當前任務,咱們講過全部的操做都是經過rex命令來完成的,rex必需要在有Rexfile的目錄下執行而且讀取Rexfile中的代碼;所以我要經過在Rexfile寫代碼調用這個模板。以下所示
[tomcat@StorageServer1 rex]$ cat Rexfile use Rex -feature => ['1.3']; use strict; use warnings; use Rex::Group::Lookup::INI; #use Data::Dumper; #加載模版 require Template::Service; require Template::File; #設置併發鏈接數,默認是1 parallelism 'max'; #將服務器分組並以文件的形式來保存主機名 groups_file "file.ini"; #將定義好的方法,屬性,以及變量都保存在改模版中(此模板也是一個模塊) auth for =>"all_servers"=> user=>"tomcat", private_key=>"/home/tomcat/.ssh/id_rsa", public_key=> "/home/tomcat/.ssh/id_rsa.pub"; desc "啓動全部web服務"; task "web_start",group=>"all_servers",sub { Template::start_tomcat(); }; desc "關閉全部web服務"; task "web_stop",group=>"all_servers",sub { Template::shutdown_tomcat(); }; desc "重啓全部web服務"; task "web_restart",group=>"all_servers",sub { Template::Service::restart_tomcat(); }; desc "查看全部服務器節點時間"; task "show_times",group=>"all_servers",sub { Template::show_time(); };
經過rex -T來查看當前的任務 以下
[tomcat@StorageServer1 rex]$ rex -T Tasks show_times 查看全部服務器節點時間 web_restart 重啓全部web服務 web_start 啓動全部web服務 web_stop 關閉全部web服務 Server Groups all_servers appwap, boss, chaoshi, geren, gerenwap, quanguo, shopwap appwap_servers appwap boss_servers boss chaoshi_servers chaoshi geren_servers geren gerenwap_servers gerenwap quanguo_servers quanguo shopwap_servers shopwap [tomcat@StorageServer1 rex]$
好比我如今要重啓全部項目的web服務 我只須要經過rex+任務名就好了,
在執行以前我要說明下:由於rex是經過ssh來進行集成管理的,因此我須要用到帳戶和密碼,ssh登錄能夠經過口令登錄
也能夠經過公鑰認證的方式,我這裏使用的是公鑰認證的方式,須要將本地生成的公鑰傳輸到各個節點上,否則登錄的話會提示讓你輸入密碼等交互操做
爲了解決這個問題,我寫了個腳本名爲login.pl執行如下就好了 操做以下
首先生成key
[tomcat@StorageServer1 rex]$ ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/home/tomcat/.ssh/id_rsa): Created directory '/home/tomcat/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/tomcat/.ssh/id_rsa. Your public key has been saved in /home/tomcat/.ssh/id_rsa.pub. The key fingerprint is: 2b:15:90:70:0a:06:99:a6:2d:e1:5f:28:99:11:31:a9 tomcat@StorageServer1 The key's randomart image is: +--[ RSA 2048]----+ |.B* ..o. | |+=.. o.. | |=o+ o . | |E=.. . . | | .o . S | | . . . | | . . | | . | | | +-----------------+
而後在寫個login.pl腳本 賦予執行權限 在執行(由於用到了Expect模塊若是沒安裝的話用cpanm安裝下就好了)
[tomcat@StorageServer1 rex]$ vi login.pl #!/usr/bin/perl use v5.16; use warnings; use Expect; my @serversqw(quanguo chaoshi geren boss shopwap appwap imsswap); for my $host(@servers){ my $exp=Expect->new(); $exp->spawn("ssh-copy-id -i /home/tomcat/.ssh/id_rsa.pub $host"); $exp->exp_internal(1); $exp->log_stdout(0); $exp->debug(3); $exp->expect(2,[ qr/connecting \(yes\/no\)\?/i,sub { my $self=shift; $self->send("yes\n"); exp_continue; }], [ qr/password: /i,sub { my $self=shift; $self->send("tomcat12300.\n"); exp_continue; }] ); [tomcat@StorageServer1 rex]$ chmod a+x login.pl [tomcat@StorageServer1 rex]$ ./login.pl
重啓全部tomcat服務