
企业CI / CD架构

项目一:生产环境 SVN数据迁移到GitLab
1、Git与SVN对比
|--------------|-------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 版本工具 | SVN | Git |
| 系统特点 | 1. 集中式版本控制系统(文档管理很方便) 2. 企业内部并行集中开发 3. Windows系统上开发推荐使用 4. 克隆一个拥有将近一万个提交(Commit),五个分支,每个分支有大约1500个文件,用时将近1个小时 | 1. 分布式系统(代码管理很方便) 2. 开源项目开发 3. Mac、linux系统上开发推荐使用 4. 克隆一个拥有将近一万个提交(Commit),五个分支,每个分支有大约1500个文件,用时1分钟 |
| 灵活性 | 1. svn服务器出现故障,无法与之交互 2. 所有的svn操作都需要中央仓库交互(例如:拉分支,看日志等) | 1. 可以单机操作,git服务器故障也可以在本地git仓库工作 2. 除了push和pull或fetch操作,其他都可以在本地操作 3. 根据自己开发任务任意在本地创建分支 4. 日志都是在本地查看,效率较高 |
| 安全性 | 较差,定期备份,并且是整个svn都要备份 | 较高,每个开发者的本地就是一套完整版本库,记录着版本库的所有信息(gitlab集成了备份功能) |
| 分支方面 | 1. 拉分支更像copy一个路径 2. 可针对任何子目录进行branch 3. 拉分支的时间较慢,因为拉分支相当于copy 4. 创建完分支后,影响全部成员,每个人都会拥有这个分支 5. 多分支进行开发较重(工作较多而且繁琐) | 1. 可以在git的任意一个提交点(commit point)开启分支 2. 拉分支时间较快,因为拉分支知识创建文件的指针和HEAD 3. 自己本地创建的分支不会影响其他人 4. 比较适合多分支并行开发 5. git checkout hash值(切回之前的版本,无需版本回退) 6. 强大的cherry-pick |
| 版本控制 | 1. 保存前后变化的差异数据,作为版本控制 2. 版本号进行控制,每次操作都会产生一个高版本号(svn的全局版本号,这是svn一个比较大的特点,git是hash值) | 1. git只关心文件数据的整体发生变化,更像是把文件做快照,文件没有改变时,分支只想这个文件的指针不会改变,文件发生改变,指针指向新版本 2. 40位长的哈希值作为版本号,没有先后之分 3. git rebase操作可以更好的保持提交记录的整洁 |
| 工作流程 | 1. 每次更改文件之前都得update操作,有的时候修改过程中这个文件有更新,commit不会成功 2. 有冲突,会打断提交操作(冲突解决是一个提交速度的竞赛:手快者先提交,平安无事。手慢者后提交,可能遇到麻烦的冲突解决) | 1. 开始工作前进行fetch操作,完成开发工作后push操作,有冲突解决冲突 2. Git的提交过程不会被打断,有冲突会标记冲突文件 3. gitflow流程(经典) |
| 内容管理 | svn对中文支持好,操作简单,适用于大众 | 对程序的源代码管理方便,代码库占用的空间少,易于分支化管理 |
| 学习成本 | 使用起来更方便,svn对中文支持好,操作简单,适用于大众 | 更在乎效率而不是易用性,成本较高(有很多独有的命令,rebase,远程仓库交互的命令等) |
| 权限管理 | Svn的权限管理严格,可以按组,个人针对某个子目录的权限控制(每个目录下都会有个.svn的隐藏文件) | Git没有严格的权限管理机制,只有账号角色划分(在项目的home文件下有且只有一个.git目录) |
| 管理平台 | 不确定 | Gtilab(建议使用,集成的功能较多,API开发)gerrit,github等 |
1、项目环境
|------------------|-----------------|-------------|--------------|
| 主机名 | IP地址 | 角色 | 特殊要求 |
| svn | 192.168.200.111 | SVN服务器 | 无 |
| git | 192.168.200.112 | Git客户端 | 无 |
| gitlab01 | 192.168.200.113 | GitLab测试服务器 | 内存2G |
2、主机初始化
所有主机关闭防火墙与selinux
bash
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# iptables -F
[root@localhost ~]# setenforce 0
3、部署SVN服务器
bash
[root@localhost ~]# hostname svn
[root@localhost ~]# bash
[root@svn ~]#
[root@svn ~]# yum -y install subversion
[root@svn ~]# mkdir -p /application/svndata/crushlinux
[root@svn ~]# mkdir -p /application/svnpasswd
创建crushlinux项目主分支,开发分支,测试分支
bash
[root@svn ~]# svnadmin create /application/svndata/crushlinux/master
[root@svn ~]# svnadmin create /application/svndata/crushlinux/dev
[root@svn ~]# svnadmin create /application/svndata/crushlinux/test
[root@svn ~]# cd /application/svndata/crushlinux/master/conf/
[root@svn conf]# cp svnserve.conf svnserve.conf-$(date +%F)
[root@svn conf]# vim svnserve.conf
[root@svn conf]# sed -n '19p;20p;27p;34p' svnserve.conf
19 anon-access = none
20 auth-access = write
27 password-db = /application/svnpasswd/passwd
34 authz-db = /application/svnpasswd/authz
将配置文件覆盖另外两个分支
bash
[root@svn conf]# /bin/cp svnserve.conf /application/svndata/crushlinux/dev/conf/
[root@svn conf]# /bin/cp svnserve.conf /application/svndata/crushlinux/test/conf/
[root@svn conf]# cp /application/svndata/crushlinux/master/conf/authz /application/svnpasswd/
[root@svn conf]# cp /application/svndata/crushlinux/master/conf/passwd /application/svnpasswd/
[root@svn conf]# vim /application/svnpasswd/passwd
[users]
manager=123456
dev=123456
tom=123456
bob=123456
[root@svn conf]# vim /application/svnpasswd/authz
[groups]
testgroup = tom,bob
[crushlinux/master:/]
manager = rw #master主分支代码提交者---开发经理
dev = r
[crushlinux/dev:/]
dev = rw #dev开发分支代码提交者---普通程序员
manager = rw #dev开发分支代码下载者---开发经理
[crushlinux/test:/]
@testgroup = r #test测试分支代码下载者----测试人员
manager = rw #test测试分支代码提交者---开发经理
[root@svn conf]# cd
[root@svn ~]# svnserve -d -r /application/svndata/
[root@svn ~]# ps -ef | grep svn
root 63535 1 0 23:45 ? 00:00:00 svnserve -d -r /application/svndata/
root 63537 1352 0 23:45 pts/0 00:00:00 grep --color=auto svn
在svn客户主机创建svn目录checkout代码






4、利用git-svn克隆svn代码
提示:yum安装的git没有git-svn功能,要编译安装较新版本的git
Git下载地址: https://github.com/git/git/releases

安装依赖关系
bash
[root@git ~]# yum -y install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
# 编译安装
[root@git ~]# wget https://github.com/git/git/archive/v2.22.0.tar.gz
[root@git ~]# tar xf git-2.22.0.tar.gz -C /usr/src/
[root@git ~]# cd /usr/src/git-2.22.0/
[root@git git-2.22.0]# make configure
[root@git git-2.22.0]# ./configure --prefix=/usr/local/git && make && make install
[root@git git-2.22.0]# ln -sf /usr/local/git/bin/git /usr/bin/
[root@git git-2.22.0]# git --version
git version 2.22.0
安装git-svn支持程序(没有这两个包git-svn报错)
bash
[root@git ~]# cd /etc/yum.repos.d/
[root@git yum.repos.d]# mv backup/CentOS-Base.repo ./
[root@git yum.repos.d]# cd
[root@git ~]# yum -y install subversion-perl perl-Digest-MD5
创建Git工作目录并克隆SVN分支代码到本地
bash
[root@git ~]# mkdir /backup
[root@git ~]# cd /backup
将SVN服务器master分支代码克隆到本地Git工作目录
bash
[root@git backup]# git svn clone --no-metadata svn://192.168.200.111/crushlinux/master/ /backup/master/
已初始化空的 Git 仓库于 /backup/master/.git/
Authentication realm: <svn://192.168.200.111:3690> dafac862-41c8-4d4e-a12a-e18eac93880c
Password for 'root': #输入root登陆密码
Authentication realm: <svn://192.168.200.111:3690> dafac862-41c8-4d4e-a12a-e18eac93880c
Username: manager #输入svn的master分支的授权账户名
Password for 'manager': #输入svn的master分支的授权账户密码
已初始化空的 Git 仓库于 /backup/master/.git/
A 123.txt
A shell.txt
r1 = df8316fb48f1d641d6f22c78a3e00c5302dbdb88 (refs/remotes/git-svn)
Checked out HEAD:
svn://192.168.200.111/crushlinux/master r1
将SVN服务器dev分支代码克隆到本地Git工作目录
bash
[root@git backup]# git svn clone --no-metadata svn://192.168.200.111/crushlinux/dev/ /backup/dev/
已初始化空的 Git 仓库于 /backup/dev/.git/
Authentication realm: <svn://192.168.200.111:3690> 5b422da6-805d-4d99-b11f-ee04f504c323
Password for 'root': #输入root登陆密码
Authentication realm: <svn://192.168.200.111:3690> 5b422da6-805d-4d99-b11f-ee04f504c323
Username: dev #输入svn的dev分支的授权账户名
Password for 'dev': #输入svn的dev分支的授权账户密码
A kaifa.txt
r1 = 5fe6d6dfe61c1070512ba0c7065fc2845aed0ea9 (refs/remotes/git-svn)
Checked out HEAD:
svn://192.168.200.111/crushlinux/dev r1
将SVN服务器test分支代码克隆到本地Git工作目录
bash
[root@git backup]# git svn clone --no-metadata svn://192.168.200.111/crushlinux/test/ /backup/test/
已初始化空的 Git 仓库于 /backup/test/.git/
Authentication realm: <svn://192.168.200.111:3690> e221ef88-dd05-4a5e-aa71-b3953e1dfdea
Password for 'root': #输入root登陆密码
Authentication realm: <svn://192.168.200.111:3690> e221ef88-dd05-4a5e-aa71-b3953e1dfdea
Username: manager #输入svn的test分支的授权账户名
Password for 'manager': #输入svn的test分支的授权账户密码
A ceshi.txt
r1 = 74a515b2dbc4c3e11d8d275419db2cf5974198be (refs/remotes/git-svn)
Checked out HEAD:
svn://192.168.200.111/crushlinux/test r1
显示克隆数据
bash
[root@git backup]# tree
.
├── dev
│ └── kaifa.txt
├── master
│ ├── 123.txt
│ └── shell.txt
└── test
└── ceshi.txt
3 directories, 4 files
5 、Gitlab环境部署
bash
[root@localhost ~]# hostname gitlab01
[root@localhost ~]# bash
[root@gitlab01 ~]#
安装依赖包
bash
[root@gitlab01 ~]# yum -y install curl openssh-server openssh-clients postfix cronie policycoreutils-python
启动postfix,并设置开机自启
bash
[root@gitlab01 ~]# systemctl start postfix
[root@gitlab01 ~]# systemctl enable postfix
下载安装gitlab rpm包
清华开源镜像站:https://mirrors.tuna.tsinghua.edu.cn/
bash
[root@gitlab01 ~]# wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-11.11.3-ce.0.el7.x86_64.rpm
[root@gitlab01 ~]# rpm -ivh gitlab-ce-11.11.3-ce.0.el7.x86_64.rpm
修改配置文件/etc/gitlab/gitlab.rb,生产环境下可以跟据需求修改
bash
[root@gitlab01 ~]# vim /etc/gitlab/gitlab.rb
13 external_url 'http://192.168.200.113'
重新加载配置文件
bash
[root@gitlab01 ~]# gitlab-ctl reconfigure
[root@gitlab01 ~]# gitlab-ctl restart
[root@gitlab01 ~]# netstat -lnpt | grep :80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4291/nginx: master
- 启动:gitlib-ctl start
- 关闭:gitlab-ctl stop
- 重启:gitlab-ctl restart
- 重载配置:gitlab-ctl reconfigure
- 查看状态:gitlab-ctl status
查看gitlab版本
bash
[root@gitlab01 ~]# head -1 /opt/gitlab/version-manifest.txt
gitlab-ce 11.11.3
浏览器登录 GitLab,输入 http://服务器 IP 地址



6、创建项目推送代码
创建一个项目叫做pro将从SVN克隆下来的master,dev,test的代码推送到pro项目里。分支名称分别为linux,dev,test。


bash
[root@git ~]# git config --global user.email "crushlinux@163.com"
[root@git ~]# git config --global user.name "crushlinux"
[root@git ~]# git config --list
user.name=crushlinux
user.email=crushlinux@163.com
将master目录代码推送到GitLab仓库的pro项目里
bash
[root@git master]# cd /backup/master/
[root@git master]# git branch
* master
[root@git master]# git branch linux
[root@git master]# git checkout linux
切换到分支 'linux'
[root@git master]# git branch
* linux
master
[root@git master]# git add *
[root@git master]# git commit -m "master分支代码提交"
位于分支 linux
无文件要提交,干净的工作区
[root@git master]# git remote rm origin
[root@git master]# git remote add origin http://192.168.200.113/root/pro.git
[root@git master]# git push -u origin linux
Username for 'http://192.168.200.113': root
Password for 'http://root@192.168.200.113':
枚举对象: 4, 完成.
对象计数中: 100% (4/4), 完成.
压缩对象中: 100% (2/2), 完成.
写入对象中: 100% (4/4), 262 bytes | 262.00 KiB/s, 完成.
总共 4 (差异 0),复用 0 (差异 0)
remote:
remote: To create a merge request for linux, visit:
remote: http://192.168.200.113/root/pro/merge_requests/new?merge_request%5Bsource_branch%5D=linux
remote:
To http://192.168.200.113/root/pro.git
* [new branch] linux -> linux
分支 'linux' 设置为跟踪来自 'origin' 的远程分支 'linux'。
将dev目录代码推送到GitLab仓库的pro项目里
bash
[root@git ~]# cd /backup/dev/
[root@git dev]# git branch
* master
[root@git dev]# git branch dev
[root@git dev]# git checkout dev
切换到分支 'dev'
[root@git dev]# git branch
* dev
master
[root@git dev]# ls
kaifa.txt
[root@git dev]# git add *
[root@git dev]# git commit -m "开发分支代码提交"
位于分支 dev
无文件要提交,干净的工作区
[root@git dev]# git remote rm origin
[root@git dev]# git remote add origin http://192.168.200.113/root/pro.git
[root@git dev]# git push -u origin dev
Username for 'http://192.168.200.113': root
Password for 'http://root@192.168.200.113':
枚举对象: 3, 完成.
对象计数中: 100% (3/3), 完成.
写入对象中: 100% (3/3), 210 bytes | 210.00 KiB/s, 完成.
总共 3 (差异 0),复用 0 (差异 0)
remote:
remote: To create a merge request for dev, visit:
remote: http://192.168.200.113/root/pro/merge_requests/new?merge_request%5Bsource_branch%5D=dev
remote:
To http://192.168.200.113/root/pro.git
* [new branch] dev -> dev
分支 'dev' 设置为跟踪来自 'origin' 的远程分支 'dev'。
将test目录代码推送到GitLab仓库的pro项目里
bash
[root@git ~]# cd /backup/test/
[root@git test]# git branch
* master
[root@git test]# git branch test
[root@git test]# git checkout test
切换到分支 'test'
[root@git test]# git add *
[root@git test]# git commit -m "测试分支代码提交"
位于分支 test
无文件要提交,干净的工作区
[root@git test]# git remote add origin http://192.168.200.113/root/pro.git
[root@git test]# git push -u origin test
Username for 'http://192.168.200.113': root
Password for 'http://root@192.168.200.113':
枚举对象: 3, 完成.
对象计数中: 100% (3/3), 完成.
写入对象中: 100% (3/3), 212 bytes | 212.00 KiB/s, 完成.
总共 3 (差异 0),复用 0 (差异 0)
remote:
remote: To create a merge request for test, visit:
remote: http://192.168.200.113/root/pro/merge_requests/new?merge_request%5Bsource_branch%5D=test
remote:
To http://192.168.200.113/root/pro.git
* [new branch] test -> test
分支 'test' 设置为跟踪来自 'origin' 的远程分支 'test'。

项目二: 测试环境迁移到生产环境GitLab
1、项目 背景
公司为了更换版本软件搭建了GitLab环境,并且开发组的同事都陆陆续续把代码从svn迁移到了GitLab上,但是之前的服务器并不是搭建在公司的生产环境,而是搭建在办公室的某台闲置的电脑上,因此为了保证数据安全性及Gitlab服务的性能,领导要求将之前的GitLab数据全部重新迁移到公司生产的服务器上去。
2 、项目环境
|------------------|-----------------|-------------|--------------|
| 主机名 | IP地址 | 角色 | 特殊要求 |
| gitlab01 | 192.168.200.113 | GitLab测试服务器 | 内存2G |
| gitlab02 | 192.168.200.114 | GitLab生产服务器 | 内存2G |
3 、 GitLab的数据备份
首先,我们得把老服务器上的Gitlab整体备份,使用Gitlab一键安装包安装Gitlab非常简单,同样的备份恢复与迁移数据也非常简单。使用一条命令即可创建完整的Gitlab备份。
gitlab-rake gitlab:backup:create
使用以上命令会在/var/opt/gitlab/backups目录下创建一个名称类似为1562305744_2019_07_05_11.11.3_gitlab_backup.tar的压缩包,这个压缩包就是Gitlab整个的完整部分,其中开头1562305744_2019_07_05是备份创建的日期,11.11.3是Gitlab的版本号。
创建服务配置文件备份
- /etc/gitlab/gitlab.rb // gitlab配置文件
- /var/opt/gitlab/nginx/conf //nginx配置文件
- /etc/postfix/main.cf //postfix配置文件
bash
[root@gitlab01 ~]# cp /etc/gitlab/gitlab.rb{,.bak}
[root@gitlab01 ~]# cp /var/opt/gitlab/nginx/conf/nginx.conf{,.bak}
[root@gitlab01 ~]# cp /etc/postfix/main.cf{,.bak}
执行命令生成备份压缩包
bash
[root@gitlab01 ~]# cd /var/opt/gitlab/backups/
[root@gitlab01 backups]# gitlab-rake gitlab:backup:create
查看备份包
[root@gitlab01 backups]# ls
1562305744_2019_07_05_11.11.3_gitlab_backup.tar
[root@gitlab01 backups]# ll
总用量 112
-rw------- 1 git git 112640 7月 5 13:49 1562305744_2019_07_05_11.11.3_gitlab_backup.tar
4、 更改GitLab备份目录
修改/etc/gitlab/gitlab.rb配置文件并重新加载
bash
[root@gitlab01 ~]# mkdir /backup
[root@gitlab01 ~]# vim +334 /etc/gitlab/gitlab.rb
334 gitlab_rails['backup_path'] = "/backup"
[root@gitlab01 ~]# gitlab-ctl reconfigure
[root@gitlab01 backup]# cd /backup/
[root@gitlab01 backup]# gitlab-rake gitlab:backup:create
[root@gitlab01 backup]# ls
1562306284_2019_07_05_11.11.3_gitlab_backup.tar
5 、 GitLab的自动备份
将命令写成定时任务,每天凌晨两点执行一次备份操作
bash
[root@gitlab01 ~]# crontab -e
* 2 * * * cd /backup && gitlab-rake gitlab:backup:create
[root@gitlab01 ~]# systemctl restart crond
设置备份过期时间
设置只保存最近7天的备份,编辑/etc/gitlab/gitlab.rb配置文件,找到如下配置并修改
bash
[root@gitlab01 ~]# vim /etc/gitlab/gitlab.rb
342 gitlab_rails['backup_keep_time'] = 604800
[root@gitlab01 ~]# gitlab-ctl reconfigure
6 、将 备份文件 上传到 新服务器
确保新GitLab服务器和老GitLab服务器版本相同
bash
[root@gitlab01 ~]# scp /backup/1562306284_2019_07_05_11.11.3_gitlab_backup.tar 192.168.200.114:/root
7 、 从备份数据中恢复GitLab 数据
将拷贝过来的备份文件移动到新GitLab的备份目录下
bash
[root@gitlab02 ~]# mv 1562306284_2019_07_05_11.11.3_gitlab_backup.tar /var/opt/gitlab/backups/
[root@gitlab02 ~]# cd /var/opt/gitlab/backups/
[root@gitlab02 backups]# ls
1562306284_2019_07_05_11.11.3_gitlab_backup.tar
给备份文件增加777权限,不然可能恢复的时候会出现权限不够,不能解压的问题。
bash
[root@gitlab02 backups]# chmod 777 1562306284_2019_07_05_11.11.3_gitlab_backup.tar
[root@gitlab02 backups]# ls -l 1562306284_2019_07_05_11.11.3_gitlab_backup.tar
-rwxrwxrwx 1 root root 112640 7月 5 14:02 1562306284_2019_07_05_11.11.3_gitlab_backup.tar
停止相关数据连接服务
bash
[root@gitlab02 backups]# gitlab-ctl stop unicorn
ok: down: unicorn: 0s, normally up
[root@gitlab02 backups]# gitlab-ctl stop sidekiq
ok: down: sidekiq: 0s, normally up
执行命令从备份文件中恢复GitLab
bash
gitlab-rake gitlab:backup:restore BACKUP=备份文件编号
[root@gitlab02 backups]# gitlab-rake gitlab:backup:restore BACKUP=1562306284_2019_07_05_11.11.3
说明:恢复过程中出现两个(yes/no),输入两个yes即可。
重新启动GitLab
bash
[root@gitlab02 backups]# gitlab-ctl start
8、通过浏览器访问进行检查


两台GitLab除了IP不同外,项目内容完全一致。