gitlab搭建之互備模式


gitlab搭建之互備模式

前言:gitlab目前默認的部署方式是本地單機部署,為了提高gitlab環境的可靠性和穩定性,必須構建一套互備搭建方案:借助gitolilte的mirror功能可以實現此功能;

搭建環境:

2台服務器 -- RedHat 5.4

內核版本 -- linux 2.6.18 x86_64

概要:

1. 搭建兩套gitlab標准環境

2. 構建互備模式

1. 搭建兩套gitlab標准環境

  參考之前博文:http://www.cnblogs.com/lenolix/archive/2013/02/06/2906466.html

      這里假設兩台gitlab環境分別是A和B,在下文中,$A:代表在A機中操作,$B:代表在B機中操作

2. 配置A、B環境的互訪權限

     關於gitolite的mirror功能請參考官方文檔:http://gitolite.com/gitolite/mirroring.html

     1. 克隆本地的gitolite-admin.git

$A: sudo -u gitlab -H git clone git@localhost:gitolite-admin.git  /home/gitlab/gitolite-admin
$B: sudo -u gitlab -H git clone git@localhost:gitolite-admin.git /home/gitlab/gitolite-admin

  2. 修改.gitolilte.rc 設置hostname

$A: sudo -u git -H vi /home/git/.gitolite.rc 
      修改 HOSTNAME                    =>  'hostA',

$B: sudo -u git -H vi /home/git/.gitolite.rc 
      修改 HOSTNAME                    =>  'hostB',

  3. 更新gitolite的配置,添加A、B主機的互訪權限

#更新A、B主機上gitlab賬戶的配置,這一步很重要,因為A、B的gitolite賬戶體系中都有gitlab賬戶,但是其ssh-key是不一樣的,如果同步成相同的值,會影響其中一套gitlab環
#境的運行,解決方案是給gitlab賬戶更換用戶名,並且在A、B上都添加gitlab賬戶,避免同步覆蓋
$A: sudo -u git mv /home/git/.gitolite/keydir/gitlab.pub /home/git/.gitolite/keydir/gitlab-hostA.pub
$A: sudo -u git scp /home/git/.gitolite/keydir/gitlab-hostA.pub git@hostB:/home/git/.gitolite/keydir/
$A: sudo -u git vi /home/git/.gitolite/conf/gitolite.conf
添加:
      repo gitolite-admin
           RW+ = gitlab-hostA
           RW+ = gitlab-hostB
$B: sudo -u git mv /home/git/.gitolite/keydir/gitlab.pub /home/git/.gitolite/keydir/gitlab-hostB.pub
$B: sudo -u git scp /home/git/.gitolite/keydir/gitlab-hostB.pub git@hostA:/home/git/.gitolite/keydir
$B: sudo -u git vi /home/git/.gitolite/conf/gitolite.conf
添加:
      repo gitolite-admin
           RW+ = gitlab-hostA
           RW+ = gitlab-hostB
 
#添加A、B主機上git賬戶的互訪權限
$A: sudo -u git -H ssh-keygen $A: sudo cp /home/git/.ssh/id_rsa.pub /tmp/server-hostA.pub $A: sudo -u git -H cp /tmp/server-hostA.pub /home/git/.gitolite/keydir/ $A: sudo scp /tmp/server-hostA.pub git@B:home/git/.gitolite/keydir/
$A: sudo -u git -H vi /home/git/.gitolite/conf/gitolite.conf
添加:
repo @all
RW+ = gitlab-host47
RW+ = gitlab-host48
RW+ = server-host47
RW+ = server-host48
$B: sudo -u git -H ssh-keygen 
$B: sudo cp /home/git/.ssh/id_rsa.pub /tmp/server-hostB.pub
$B: sudo -u git-H cp /tmp/server-hostB.pub /home/git/.gitolite/keydir
$B: sudo scp /tmp/server-hostB.pub git@A:home/gitlab/.gitolite/keydir/
$B: sudo -u git -H vi /home/git/.gitolite/conf/gitolite.conf
添加:
repo @all
RW+ = gitlab-host47
RW+ = gitlab-host48
RW+ = server-host47
RW+ = server-host48
#重新安裝gitolite,更新conf
$A: sudo -u git /home/git/bin/gitolite setup
$B: sudo -u git /home/git/bin/gitolite setup

#安裝ssh key,很奇怪,用setup只能更新授權配置,卻不能更新keydir中的key,沒辦法,這里只能再搞一次
$A: sudo cd /home/gitlab/gitolite-admin
$A: sudo -u gitlab -H git pull (這里你會發現更新之后,conf/gitolite.conf已經更新了,但是keydir/里面卻沒有新添的文件)
$A: sudo cp /home/git/.gitolite/keydir/* keydir/
$A: sudo chown -R gitlab:git keydir/
$A: sudo -u gitlab git add keydir/*
$A: sudo -u gitlab git commit -m "update"
$A: sudo -u gitlab git push

$B: sudo cd /home/gitlab/gitolite-admin
$B: sudo -u gitlab -H git pull
$B: sudo cp /home/git/.gitolite/keydir/* keydir/
$B: sudo chown -R gitlab:git keydir/
$B: sudo -u gitlab git add keydir/*
$B: sudo -u gitlab git commit -m "update"
$B: sudo -u gitlab git push

      4. 配置ssh的config文件

$A: sudo -u git -H vi /home/git/.ssh/config
host hostB
  user git
  hostname hostB's ip/hostname
  port 22
  identityfile ~/.ssh/id_rsa
$A: sudo -u git -H chmod 644 /home/git/.ssh/config $B: sudo -u git -H vi /home/git/.ssh/config host hostA user git hostname hostA's ip/hostname port 22 identityfile ~/.ssh/id_rsa
$B: sudo -u git -H chmod 644 /home/git/.ssh/config

  測試連通性

$A: sudo -u git ssh hostB
$B: sudo -u git ssh hostA

  如果出現 " hello server-hostA/B, this is ..." 就表示A、B的連通性沒有問題

      測試gitlab賬戶的配置

$A :sudo -u gitlab -H git clone git@localhost:gitolite-admin.git /tmp/gitolite-admin
$A: rm -rf /tmp/gitolite-admin

$B :sudo -u gitlab -H git clone git@localhost:gitolite-admin.git /tmp/gitolite-admin
$B: rm -rf /tmp/gitolite-admin

  如果能正常clone,說明配置正確

 3. 借助post-receive hooks,實現實時同步

$A: sudo -u git -H vi home/git/.gitolite/hooks/common/post-receive 
添加:
repo_name=`pwd`
repo_name=${repo_name#*/home/git/repositories/}
repo_name=${repo_name%.git*}
/home/git/bin/gitolite mirror push hostB $repo_name > /dev/null 2>&1

$B: sudo -u git -H vi home/git/.gitolite/hooks/common/post-receive 
添加:
repo_name=`pwd`
repo_name=${repo_name#*/home/git/repositories/}
repo_name=${repo_name%.git*}
/home/git/bin/gitolite mirror push hostA $repo_name > /dev/null 2>&1

  修改下gitolite的代碼,去除一個權限限制:

$A: sudo -u git /home/git/gitolite/src/commands/mirror 
修改:
sub valid_slave {
    my ( $host, $repo ) = @_; 
    _die "invalid repo '$repo'" unless $repo =~ $REPONAME_PATT;
    #注釋掉下面幾行
    #my $ref = git_config( $repo, "^gitolite-options\\.mirror\\.slaves.*" );
    #my %list = map { $_ => 1 } map { split } values %$ref;

    #_die "'$host' not a valid slave for '$repo'" unless $list{$host};
}

 4. 測試

  在A的環境上創建一個倉庫 root/p1, 然后提交代碼,你會發現B上面也創建了/root/p1倉庫,然后通過B修改倉庫代碼,可以發現A上面的代碼也修改了.

      如果這個測試可以通過,那么恭喜你,gitlab的互備模式已經構建成功了!

 5. 后續

      待解決問題:  

  1. 雖然倉庫可以同步,但是satellites不能同步,這樣的話在線提交的功能就不能用。

         暫時解決方案:在主備切換的時候,需要手動執行下 rake gitlab:enable_automerge RAILS_ENV=production, 重新生成satellites

      2. 主備模式的缺點是資源利用率低,總是有一台服務器處於空閑狀態

         優化方案:在互備模式的基礎上實現分布式部署,在通過VIP做LoadBlance,提供機器利用率和系統性能 。(進行中...)

      3. 數據庫目前是主備模式(master-master),但是沒有實現主備的自動切換,需要手動支持。

 6. 補充問題

      1. 在使用Http協議提交代碼的時候,發現很奇怪的問題,我將錯誤輸出重定向到/tmp/mirror.log

      vi /home/git/.gitolite/hooks/common/post-receive 

      /home/git/bin/gitolite mirror push hostA $repo_name >/tmp/mirror.log 2>&1

      發現錯誤信息:

      FATAL: errors found before logfile could be created

      FATAL:unknown host hostA 

      。。。

      通過跟蹤gitolite的mirror命令執行過程,發現問題所在:

      http協議提交代碼的功能是gilab的web服務器支持的,而gitlab的WEB服務是以gitlab的用戶身份運行的,導致post-receive這個鈎子腳本也是以gitlab的用戶身份調用的,這樣就會以gitlab用戶的上下文環境來執行腳本,所以會觸發很過奇怪的問題

       解決方案:

       vi /home/git/.gitolite/hooks/common/post-receive

       更改:

#強制指定HOME變量
export HOME=/home/git
repo_name=`pwd` repo_name=${repo_name#*/home/git/repositories/} repo_name=${repo_name%.git*}
#這里也明確指定ssh的host地址,不能使用git賬戶的ssh/config配置 /home/git/bin/gitolite mirror push git@hostA's ip $repo_name > /dev/null 2>&1

      vi /home/git/gitolite/src/lib/Gitolite/Common.pm

      更改gitolite源碼,修改日志文件的訪問權限,允許git組賬戶可寫

sub gl_log {
    # the log filename and the timestamp come from the environment.  If we get
    # called even before they are set, we have no choice but to dump to STDERR
    # (and probably call "logger").

    # tab sep if there's more than one field
    my $msg = join( "\t", @_ );
    $msg =~ s/[\n\r]+/<<newline>>/g;

    my $ts = gen_ts();
    my $tid = $ENV{GL_TID} ||= $$; 

    my $fh;
    logger_plus_stderr( "errors found before logging could be setup", "$msg" ) if not $ENV{GL_LOGFILE};
    chmod 0664,$ENV{GL_LOGFILE}; #更改日志訪問屬性
    open my $lfh, ">>", $ENV{GL_LOGFILE}
      or logger_plus_stderr( "errors found before logfile could be created", "$msg" );
    print $lfh "$ts\t$tid\t$msg\n";
    close $lfh;
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM