經過Rex管理全部的web服務器節點

        爲何要用到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服務

相關文章
相關標籤/搜索