首先,这个题目是不完全正确的,因为经过各种尝试,gitlab的仓库直接备份到远端,拷贝回来后是不能使用的!表现为gitlab中能看到项目,但每个项目的内容都无法读取出来,页面上会有报错提示。所以,最终采用的是实时备份gitlab的备份库!

最初的需求是,gitlab部署在centos7服务器上,然后nas网络存储在另一台windows服务器,因此想把gitlab的代码仓库同步到网络存储服务器上。

下面把本次的整个经过记录下来,以便有类似需求的朋友参考,以免走很多弯路。

最终的成功解决方案,在文章最后。

一、失败方案:挂载网络共享文件夹,让gitlab仓库直接使用这个文件夹

首先把这个贴出来,是想绝了大家的想法,这种方式压根行不通。原因容我细细道来。

在有将gitlab代码仓库实时同步到远端的需求时,第一想法就是:“能不能直接挂载nas网络存储位置到本地,然后让gitlab直接使用它?”。

1.使用winows服务器的文件夹共享

我在windows服务器(备份目的,ip:192.168.0.107,nas服务器,上面多块磁盘做了raid)上,启用了windows的文件夹共享功能,并创建了名为“gitlab”的用户,密码设置为123456。之后在比如F:\shared_repository共享文件夹上,设置gitlab账号的共享权限,把所有访问权限都打开。

然后在Cenos7(备份源,ip:192.168.0.105)上,使用mount命令挂载这个网络地址到本机的“/home/shared_repository”:

mount -t cifs -o username=gitlab,password=123456,uid=git,gid=git,dir_mode=0700,file_mode=0700 //192.168.0.107/shared_repository /home/shared_repository

映射后,测试了在Centos7的挂载目录“/home/shared_repository”中创建文件,对文件做增删改操作,实际上都是在windows服务器上对应的“shared_repository”文件夹中进行的。

这一步成功!

接下来,就是修改gitlab的配置文件,让它的仓库位置,使用这个挂载的网络位置:

vim /etc/gitlab/gitlab.rb

修改仓库路径:

#git_data_dirs({
   "default" => {
     "path" => "/home/shared_repository"  #修改到我们挂载的路径
    }
 })

然后,根据gitlab的教程,需要重新配置一下:

gitlab-ctl reconfigure

这里会报错!提示在上面挂载的路径中创建的文件夹的权限不正确!

然后为了测试,我们手动在挂载的路径/home/shared_repository中创建文件1.txt,使用chmod修改他的权限,发现完全和普通路径中修改权限不一样!

比如,我们chmod 500 1.txt,期望得到:-r-x------的权限,但实际上修改后的权限为:-r-xr-xr-x。

再尝试chmod 400 1.txt,应该修改为:-r--------的权限,但实际上是:-r--r--r--。

结论是:无法正确的按照当前用户权限、组权限和其他用户权限,通过chmod给“挂载的路径中的文件、文件夹授权”!

而gitlab的仓库,会在仓库路径中,创建多个“不同用户权限、不同组权限、不同其他用户权限”的多个文件或文件夹。因此,上面reconfigure时就会报错!

从而,我们无法通过“修改gitlab仓库位置为挂载的网络路径”来实现同步gitlab的代码仓库!

2.更换备份目标服务器的文件系统为ext3

然后,我认为可能是因为“windows下的ntfs文件系统,无法存储文件的权限信息(在inode中)”。

所以,把windows服务器下的共享文件夹所在分区,整个格式化为“ext3”分区,然后通过安装驱动和软件,让windows服务器能够识别这个分区。

接下来,再在windows服务器上安装nfs服务器(hanewin),把共享目录export出来(已经设置umask=000,最大权限)。

然后在Centos7中挂载为“nfs”网络文件系统:

mount -t nfs 192.168.0.107:/shared_repository /home/shared_repository

然后,重复上面的配置gitlab仓库的步骤,发现依旧报错!依旧无法正确修改mount挂载文件夹中的权限!

小结:经过不停尝试,也在国外网站上(比如stackoverflow)找到类似问题,目前结论是,mount的路径中,无法正确修改文件的权限!

二、成功方案:inotify+rsync

经过上面的尝试,最终确认放弃了mount挂载网络共享存储路径的方式。

然后再次搜索网络,最终找到了一种相对复杂但可用的方案:inotify(文件实时监控)+rsync(文件实时同步)的综合解决方案。

先简单介绍一下这两个命令的作用:

inotify:它是一个内核用于通知用户空间程序文件系统变化的机制。通过它我们可以实时的监控到某个文件夹中的所有文件、文件夹的“新增、修改、删除”等操作。

rsync:是可以实现增量备份的工具。配合任务计划,rsync能实现定时或间隔同步,配合inotify或sersync,可以实现触发式的实时同步。

此方案的关键点就在于:通过inotify“实时监控gitlab代码仓库”,在代码仓库发生变化时,“通过rsync实时的将文件同步给远端存储”。

1.半成功方案:通过Inotify+rsync直接同步gitlab生产库

然后,我的初步想法是,把gitlab的代码仓库(Cetnos7上)实时的同步给nas存储(windows服务器上)。

我在windows服务器上安装了rsync的服务器端windows版:cwRsync-server。

然后在windows上把F:\shared_repository文件夹作为同步库进行配置(具体详情见最终成功方案)。

然后在Centos7上,我把gitlab仓库整个目录通过rsync命令,测试全量同步到windows服务器上:
/usr/bin/rsync -avz --password-file=/home/rsync.passwd /home/shared_repository/ SvcCWRSYNC@192.168.0.107::syn_git_repo

上面的rsync.passwd文件中,为客户端鉴权文件,里面是密码。后面是本地需备份的目录“/home/shared_repository/”,和备份目的为192.168.0.107上的“syn_git_repo”库。SvcCWRSYNC为rsync的服务端账户名。

然后上面命令,会把整个gitlab代码仓库的所有内容同步到windows主机上。

之后为了测试恢复功能,我停止了gitlab服务:gitlab-ctl stop

再把gitlab的代码仓库中的所有内容删除掉:rm -rf \home\shared_repository\repositories

之后,再把windows中备份的代码仓库所有内容,一个字节不差的拷贝回Centos7服务器。

最后重启gitlab服务:gitlab-ctl restart

但问题正如我们一开始所说的:“gitlab的仓库直接备份到远端,拷贝回来后是不能使用的!”。

表现为gitlab中能看到项目,但每个项目的内容都无法读取出来,页面上会有报错提示。

所以结论是:不能直接把gitlab的代码仓库同步使用!

2.最终成功方案:通过Inotify+rsync同步gitlab备份库

再参考其他人的方案,比如看了下老外怎么做,最终确认了可行的方案:

让gitlab定时运行它自己的备份任务,他会把库中所有项目信息和权限管理等信息,打包备份成一个压缩包。可以通过gitlab的自带命令导回去(gitlab程序版本必须完全一致)。

然后让inotify实时监控gitlab的备份目录,在备份目录发生变化时,告知rsync,让它以增量方式实时同步到远端存储(nas)上。

rsync除了增量方式,安全起见,再写一个定时任务,比如每2小时就全量备份同步一次。

具体步骤,我完全贴出来,有需要的朋友就可以直接使用了!

1).windows服务器(备份目的,ip:192.168.0.107),安装、配置cwRsync-server同步备份服务端程序

①安装cwRsync-server

从网上搜索到cwRsyncServer_4.1.0_Installer.exe,在windows下进行安装。

我选择的是默认安装位置:C:\Program Files (x86)\ICW

安装时会给windows创建一个账号,默认是SvcCWRSYNC,密码我们设定为123456。

②配置rsync服务端

打开安装目录下的rsyncd.conf文件,编辑同步服务器(同步目的)的配置信息:

use chroot = false
strict modes = false
hosts allow = * #允许所有主机连接
#指定日志文件输出位置,下面地址为:F:\synch_backup_home\rsyncd.log
log file = /cygdrive/f/synch_backup_home/rsyncd.log

uid = 0 # 需要配置此项,不然连接报错
gid = 0 # 需要配置此项,不然连接报错

#新增自己的库配置信息
#自定义库名称,客户端连接时需指定这个名字
[syn_git_repo]
#仓库位置,对应本机为:F:\synch_backup_home\shared_repository
path = /cygdrive/f/synch_backup_home/shared_repository
#可读可写
read only = false
#输出日志
transfer logging = yes
#不允许客户端列出服务端的信息
#list = no
# 对应配置用户名
auth users = SvcCWRSYNC
#指定密码文件的位置,本机为:F:\synch_backup_home\rsync.passwd
secrets file = /cygdrive/f/synch_backup_home/rsync.passwd

[syn_git_repo]为自定义的服务端仓库名称,客户端(Centos7备份源)连接时需指定这个库的名称。

rsync.passwd文件中内容为:SvcCWRSYNC:123456

SvcCWRSYNC为备份时鉴权使用的账号名。123456为密码。

③给备份目的文件夹授权

为了防止客户端向服务器中备份文件时没有权限,按照网上的建议,我们把备份目的文件夹,也就是上面指定的仓库目录“F:\synch_backup_home\shared_repository”进行共享,并赋予SvcCWRSYNC用户所有权限。(有的教程中无此项配置,我为了以防万一还是授权了)

④重启rsync服务

修改完配置文件后,我们打开计算机的服务页面,在里面找到名为“RsyncServer”的服务。

把它设定为开机自动启动,然后重启它。

到此为止,windows服务器(备份目的)端就配置完毕了,剩下的就是Centos7(备份源)的工具安装和配置了!

2).Centos7上(备份源,ip:192.168.0.105),gitlab修改备份位置

①修改gitlab配置文件:

vim /etc/gitlab/gitlab.rb

找到备份相关的两项,进行修改:

#修改备份路径,到我们准备实时监控备份的主目录下(/home/shared_repository是我们准备备份的根目录):

gitlab_rails['backup_path'] = "/home/shared_repository/git_backup"

#备份文件保存时间,单位是秒,默认是7天
gitlab_rails['backup_keep_time'] = 604800

②修改完毕后保存退出,之后让gitlab重新配置一下:

gitlab-ctl reconfigure  #重新配置

gitlab-ctl restart #重启gitlab服务

然后我们可以通过gitlab的备份和导入备份的命令,测试下备份功能有效(请自行搜索验证gitlab的备份和导入功能并验证)。

3).Centos7(备份源),安装inotify和rsync客户端

接下来,该准备安装之前所说的“inotify(文件实时监控)+rsync(文件实时同步)的综合解决方案”所需的这两个命令了。

①在Centos7主机上,安装inotify:

yum -y install inotify-tools

若提示找不到软件,则需先安装Centos7的扩展安装源:

yum install epel-release

②安装成功后,再安装rsync客户端

yum -y install rsync

安装成功后,我们直接使用rsync命令,进行一次全量同步的测试。

在测试前,我们给待备份的源文件夹:“/home/shared_repository”中创建三个空文件:1.txt、2.txt和3.txt。

在Centos7中再创建一个rsync.passwd文件,用于同步时指定密码。

我创建到了“/home/synch_backup_home/rsync.passwd”,文件中的内容为:123456

③rsync全量备份测试

然后运行下面的命令,开始全量同步测试:

rsync -avz --password-file=/home/synch_backup_home/rsync.passwd /home/synch_backup_home/shared_repository/ SvcCWRSYNC@192.168.0.107::syn_git_repo

上面命令中的几个参数说明:

--password-file=/home/synch_backup_home/rsync.passwd”参数指定同步时的连接密码文件位置(里面是123456)。

上面参数紧跟着的“/home/synch_backup_home/shared_repository/”,为备份源文件夹位置,请加上最后的“/”,否则会在目的文件夹根目录中再创建一个名为“shared_repository”的文件夹。

最后的参数“SvcCWRSYNC@192.168.0.107::syn_git_repo”分为3段:第一段“SvcCWRSYNC”为对应服务器端的用户名;第二段“192.168.0.107”为rsync服务器地址(备份目的);第三段“syn_git_repo”为rsync服务器端配置的自定义仓库名称(与上面rsyncd.conf文件的配置对应)。

运行后,稍等一会儿,会有本次一共同步了哪些文件,发送和接收总字节数的提示,就代表成功了!

然后我们在rsync服务端(windows服务器),“F:\synch_backup_home\shared_repository”文件夹中,会发现多了1.txt、2.txt和3.txt文件!测试成功!

4).编辑增量实时同步脚本

为了做到按需实时同步有变化的文件(rsync增量同步),需要配合使用inotify实时监控和rsync的增量同步。

因此,我们需要编写一个sh脚本文件,并在开机时启动它(开机后自动开始监控功能)。

我们在“/home/synch_backup_home/”目录中,编辑增量实时同步脚本“inotify_start.sh”,内容如下(在此感谢第一个编写如下脚本的朋友,我只是做了略微调整):

#!/bin/bash

#先定义脚本中所需各种变量
src=/home/synch_backup_home/shared_repository          # 需要同步的源路径
des=syn_git_repo                             # 目标服务器上 rsync --daemon 发布的名称,rsync --daemon这里就不做介绍了,网上搜一下,比较简单。
rsync_passwd_file=/home/synch_backup_home/rsync.passwd            # rsync验证的密码文件
server_ip=192.168.0.107                 # 目标服务器
user=SvcCWRSYNC                         # rsync --daemon定义的验证用户名
log_file=/home/synch_backup_home/rsync.log  #日志输出文件路径

cd ${src}                               # 此方法中,由于rsync同步的特性,这里必须要先cd到源目录,inotify再监听 ./ 才能rsync同步后目录结构一致,有兴趣的同学可以进行各种尝试观看其效果
/usr/bin/inotifywait -mrq --format  '%Xe %w%f' -e modify,create,delete,attrib,close_write,move ./ | while read file         # 把监控到有发生更改的"文件路径列表"循环
do
        INO_EVENT=$(echo $file | awk '{print $1}')      # 把inotify输出切割 把事件类型部分赋值给INO_EVENT
        INO_FILE=$(echo $file | awk '{print $2}')       # 把inotify输出切割 把文件路径部分赋值给INO_FILE
        echo "-------------------------------$(date)------------------------------------"
        echo $file
        #增加、修改、写入完成、移动进事件
        #增、改放在同一个判断,因为他们都肯定是针对文件的操作,即使是新建目录,要同步的也只是一个空目录,不会影响速度。
        if [[ $INO_EVENT =~ 'CREATE' ]] || [[ $INO_EVENT =~ 'MODIFY' ]] || [[ $INO_EVENT =~ 'CLOSE_WRITE' ]] || [[ $INO_EVENT =~ 'MOVED_TO' ]]         # 判断事件类型
        then
                echo 'CREATE or MODIFY or CLOSE_WRITE or MOVED_TO'
				#INO_FILE变量代表路径哦  -c校验文件内容
                rsync -avzcR --password-file=${rsync_passwd_file} $(dirname ${INO_FILE}) ${user}@${server_ip}::${des}
                 #仔细看 上面的rsync同步命令 源是用了$(dirname ${INO_FILE})变量 即每次只针对性的同步发生改变的文件的目录(只同步目标文件的方法在生产环境的某些极端环境下会漏文件 现在可以在不漏文件下也有不错的速度 做到平衡) 然后用-R参数把源的目录结构递归到目标后面 保证目录结构一致性
        fi
        #删除、移动出事件
        if [[ $INO_EVENT =~ 'DELETE' ]] || [[ $INO_EVENT =~ 'MOVED_FROM' ]]
        then
                echo 'DELETE or MOVED_FROM'
                rsync -avzR --delete --password-file=${rsync_passwd_file} $(dirname ${INO_FILE}) ${user}@${server_ip}::${des}
                #看rsync命令 如果直接同步已删除的路径${INO_FILE}会报no such or directory错误 所以这里同步的源是被删文件或目录的上一级路径,并加上--delete来删除目标上有而源中没有的文件,这里不能做到指定文件删除,如果删除的路径越靠近根,则同步的目录月多,同步删除的操作就越花时间。这里有更好方法的同学,欢迎交流。
        fi
        #修改属性事件 指 touch chgrp chmod chown等操作
        if [[ $INO_EVENT =~ 'ATTRIB' ]]
        then
                echo 'ATTRIB'
                if [ ! -d "$INO_FILE" ]                 # 如果修改属性的是目录 则不同步,因为同步目录会发生递归扫描,等此目录下的文件发生同步时,rsync会顺带更新此目录。
                then
                        rsync -avzcR --password-file=${rsync_passwd_file} $(dirname ${INO_FILE}) ${user}@${server_ip}::${des}
                fi
        fi
		
		#记录日志
		echo "${file} was rsynced at $(date "+%Y%m%d-%H%M%S")" >>${log_file} 2>&1
done

记得给inotify_start.sh添加运行权限:

chmod 500 inotify_start.sh

上面权限设置为,仅对当前用户能够读取和执行(避免被修改)。

5).最后一步:开启定时任务,启动所有功能

到此为止,windows端具备了同步服务的能力,Centos7我们也具备了同步gitlab备份仓库的能力,只差自动运行了。

因此,我们通过Centos7的crontab定时任务,来完成开机启用实时备份、同步的能力。

crontab -e

按“i”进入编辑模式,在其中增加定时任务,我把我整个定时任务全部贴出来,仅供参考:

#在开机后,等待25秒后,开始运行实时同步备份脚本。
@reboot (sleep 25;sh /home/synch_backup_home/inotify_start.sh)

#每2小时运行一次gitlab仓库的全量同步,并在前面添加开始时间、后面添加结束时间:
55 */1 * * * (/usr/bin/date "+\%Y\%m\%d-\%H\%M\%S full backup begin:";/usr/bin/rsync -avz --password-file=/home/synch_backup_home/rsync.passwd /home/synch_backup_home/shared_repository/ SvcCWRSYNC@192.168.0.107::syn_git_repo;/usr/bin/date "+\%Y\%m\%d-\%H\%M\%S full backup end!") >>/home/synch_backup_home/full_backup.log 2>&1

#每天在关机前(比如19点50分,开始运行gitlab的备份功能)
50 19 * * * /usr/bin/gitlab-rake gitlab:backup:create

#每天晚上20点定时关机
0 20 * * * /usr/sbin/shutdown -h now

由于我的设备每天晚上20点自动关机,因此,为了避免备份遗漏,建议还是加上定时全量备份。

增量备份的日志会输出到“/home/synch_backup_home/rsync.log”中。

全量备份的日志会输出到“/home/synch_backup_home/full_backup.log”中。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐