七、公司的开发代码提交处理流程
PM(项目主管/项目经理)在gitlab创建任务,分配给开发人员
开发人员领取任务后,在本地使用git clone拉取代码库
开发人员创建开发分支(git checkout -b dev),并进行开发
开发人员完成之后,提交到本地仓库(git commit )
开发人员在gitlab界面上申请分支合并请求(Merge request)
PM在gitlab上查看提交和代码修改情况,确认无误后,确认将开发人员的分支合并到主分支(master)
开发人员在gitlab上Mark done确认开发完成,并关闭issue。这一步在提交合并请求时可以通过描述中填写"close #1"等字样,可以直接关闭issue
创建项目管理用户Tompson如下所示:

同样的方法,再创建Eric 、Hellen 用户。用户添加完毕后,gitlab会给用户发一封修改密码的邮件,各用户需要登录自己的邮箱,并点击相关的链接,设置新密码。
将用户添加到组中,指定Tompson为本组的owner:

同样的方法将用户Eric、Hellen也添加到组中,并指定他们为Developer:

使用 Tompson 用户的身份与密码登录到 gitlab 界面中,并创建项目 Project ,如下所示:

指定项目的存储路径和项目名称,如下所示


为项目创建Dev分支,如下所示:


在 client 上添加Tompson的用户:
[root@vm2 ~]# useradd tom
[root@vm2 ~]# useradd eric
[root@vm2 ~]# useradd test
[root@vm2 ~]# su - Tompson
[Tompson@vm2 ~]$ ssh-keygen -C 222@qq.com
Generating public/private rsa key pair.
Enter file in which to save the key (/home/Tompson/.ssh/id_rsa):
Created directory '/home/Tompson/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/Tompson/.ssh/id_rsa.
Your public key has been saved in /home/Tompson/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:SAoAH2zSxqEJqVgKKrxM5XMi6tKe61JMRdwMhwBNIrE Tompson@domain.cn
The key's randomart image is:
+---[RSA 2048]----+
|XX==o=. |
|*BOo+.o |
|E*=. . |
|*+.= + . |
|=oo = . S |
|.oo |
|.o |
|o... |
|.+=. |
+----[SHA256]-----+
[Tompson@vm2 ~]$ cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZ8cRGHej+sZzlmK36W5MUXMLOGdTwFI9Jj44mGuabZCrlYW4GDpL6ppezN+Sur0wHtnKonYJzm8ntqS0S0UHyaPPQPl9Mrs/6Z4VrXZ/4RlqHdWeSrmOwCBQld0l8HvrmP4TyGHrOreO8uZqimd/Z+OiMqnYRZzENX11Pti/Px5g1MtJcoCi9uLtF42QYrt1X/fzAyPU9C5/5ZUq4Jln3EF20bzcA52oAzZIl0jrhI0TeTeW6zYq+KxdHGshL+qG7+Ne+akPOe4Ma5BQjcMZ2dQ2kbGuozXmLT8RDcj9YRKceQsUdTI71lJpwrWKGn8Vhra0EaK3hgoTuvMYaGfOF Tompson@domain.cn
将Tompson的公钥复制到gitlab中: 使用Tompson用户的身份与密码登录到gitlab界面中,然后在ssh-key中添加 相关的key ,如下所示:


为Tompson用户配置git ,如下所示:
[Tompson@vm2 ~]$ git config --global user.email "222@qq.com"
[Tompson@vm2 ~]$ git config --global user.name "tom"
[Tompson@vm2 ~]$ git clone git@192.168.60.119:plat-sp/chathall.git
Cloning into 'chathall'...
The authenticity of host '192.168.60.119 (192.168.60.119)' can't be established.
ECDSA key fingerprint is SHA256:CDxAQmj6gUkIxB6XUofbZ853GuPM5LS2QO4a5dD7jRo.
ECDSA key fingerprint is MD5:4e:20:72:a7:46:c6:d7:5d:bb:9d:ce:c3:f3:da:43:f9.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.60.119' (ECDSA) to the list of known hosts.
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.
[Tompson@vm2 ~]$
[Tompson@vm2 ~]$ cd chathall/
[Tompson@vm2 chathall]$ ls
Readme.txt
[Tompson@vm2 chathall]$
创建一下新文件,添加内容,并提交到master分支:
[Tompson@vm2 chathall]$ vim test.sh
[Tompson@vm2 chathall]$ cat test.sh
#!/bin/bash
echo "gitlab test"
[Tompson@vm2 chathall]$ git add .
[Tompson@vm2 chathall]$ git commit -m '201805101649'
[master 80edf6b] 201805101649
1 file changed, 2 insertions(+)
create mode 100644 test.sh
[Tompson@vm2 chathall]$
[Tompson@vm2 chathall]$ git push -u origin master
Counting objects: 4, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 305 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@192.168.60.119:plat-sp/chathall.git
4611654..80edf6b master -> master
Branch master set up to track remote branch master from origin.
[Tompson@vm2 chathall]$
使用Eric用户登录,并clone 项目,如下所示:
[root@vm2 ~]# su - Eric
[Eric@vm2 ~]$ ssh-keygen -C Eric@domain.cn
Generating public/private rsa key pair.
Enter file in which to save the key (/home/Eric/.ssh/id_rsa):
Created directory '/home/Eric/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/Eric/.ssh/id_rsa.
Your public key has been saved in /home/Eric/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:VZaJvjA5SJZEB+yuRpDBNHCECCZ5R8X0DYcNE0f1B6E Eric@domain.cn
The key's randomart image is:
+---[RSA 2048]----+
|*O=..B*o**+o+oo. |
|*.+.. *o.*oooo . |
| . + + ..oo E . .|
| o o =.. . |
| . . S+ . |
| . . . |
| . . |
| o |
| . |
+----[SHA256]-----+
[Eric@vm2 ~]$ cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDxQcn4UjRW/5PT5witeV9+S2w8WK5ouawHxEF7s9wuWsT4pqhcu5BN74NG3CPaq1jJZnkV+aQsTw+60BAd1gOK0FBbKWxmohmE61n9vfpUT5igJ72t2jpXjfKwLIHw+Iq5yM4yUhkwSsoBuZkxYSEltnj8OvXaOlCDYnXuGBa9+xO8f5yVIcOtiwRvv+Y1PRRzSIcazPVZax9FLK26t1R4NPiY4xWkIJyK2OrKMeiaBBzyMfWzHdmsCWa51oSrYSmz3PDBXpzIBs3OdKxcaJs9Lc5u87YCV5RMUjLrPcA7nPK6crOabLXhz3d5GSYggMTOByQkyKOo7WlYpARCHOt/ Eric@domain.cn
[Eric@vm2 ~]$
同样需要使用Eric用户登录gitlab web 界面,并添加相应的ssh-key。然后设置git ,并clone项目:
[Eric@vm2 ~]$ git config --global user.email "Eric@domain.cn"
[Eric@vm2 ~]$ git config --global user.name "Eric"
[Eric@vm2 ~]$ git clone git@192.168.60.119:plat-sp/chathall.git
Cloning into 'chathall'...
The authenticity of host '192.168.60.119 (192.168.60.119)' can't be established.
ECDSA key fingerprint is SHA256:CDxAQmj6gUkIxB6XUofbZ853GuPM5LS2QO4a5dD7jRo.
ECDSA key fingerprint is MD5:4e:20:72:a7:46:c6:d7:5d:bb:9d:ce:c3:f3:da:43:f9.
Are you sure you want to continue connecting (yes/no)? yes
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (6/6), done.
[Eric@vm2 ~]$
切换到dev分支,修改文件内容,并将新code提交到dev分支(Developer角色默认并没有提交master的权限):
[Eric@vm2 chathall]$ git checkout dev
Branch dev set up to track remote branch dev from origin.
Switched to a new branch 'dev'
[Eric@vm2 chathall]$ ls
Readme.txt test.sh
[Eric@vm2 chathall]$ vim test.sh
[Eric@vm2 chathall]$ cat test.sh
#!/bin/bash
echo "gitlab test"
echo "brahch test"
[Eric@vm2 chathall]$ git add .
[Eric@vm2 chathall]$ git commit -m '201805101658'
[dev 6687039] 201805101658
1 file changed, 1 insertion(+)
[Eric@vm2 chathall]$ git push -u origin dev
Counting objects: 5, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 306 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote:
remote: To create a merge request for dev, visit:
remote: http://192.168.60.119/plat-sp/chathall/merge_requests/new?merge_request%5Bsource_branch%5D=dev
remote:
To git@192.168.60.119:plat-sp/chathall.git
80edf6b..6687039 dev -> dev
Branch dev set up to track remote branch dev from origin.
[Eric@vm2 chathall]$
[Eric@vm2 chathall]$ git checkout master
Switched to branch 'master'
[Eric@vm2 chathall]$ git branch
dev
* master
[Eric@vm2 chathall]$
使用Eric 用户登录gitlab web,在界面中 创建一个合并请求:

提交合并请求:

然后使用Tompson用户登录 gitlab web ,找到“合并请求” ,然后将dev分支合并到master分支,如下所示:


八、Gitlab 备份与恢复
1、查看系统版本和软件版本
[root@localhost gitlab]# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
[root@localhost gitlab]# cat /opt/gitlab/embedded/service/gitlab-rails/VERSION
8.15.4
2、数据备份
打开/etc/gitlab/gitlab.rb配置文件,查看一个和备份相关的配置项:
gitlab_rails['manage_backup_path'] = true
gitlab_rails['backup_path'] = "/data/gitlab/backups"
该项定义了默认备份出文件的路径,可以通过修改该配置,并执行 gitlab-ctl reconfigure 或者 gitlab-ctl restart 重启服务生效。
执行备份命令进行备份
/opt/gitlab/bin/gitlab-rake gitlab:backup:create
也可以添加到 crontab 中定时执行:
crontab -e
0 2 * * * bash /opt/gitlab/bin/gitlab-rake gitlab:backup:create
可以到/data/gitlab/backups找到备份包,解压查看,会发现备份的还是比较全面的,数据库、repositories、build、upload等分类还是比较清晰的。
设置备份保留时常,防止每天执行备份,肯定有目录被爆满的风险,打开/etc/gitlab/gitlab.rb配置文件,找到如下配置:
gitlab_rails['backup_keep_time'] = 604800
设置备份保留7天(7360024=604800),秒为单位,如果想增大或减小,可以直接在该处配置,并通过gitlab-ctl restart 重启服务生效。
备份完成,会在备份目录中生成一个当天日期的tar包。
3、数据恢复
1、安装部署 gitlab server
具体步骤参见上面:gitlab server 搭建过程
2、恢复 gitlab
打开/etc/gitlab/gitlab.rb配置文件,查看一个和备份相关的配置项:
gitlab_rails['backup_path'] = "/data/gitlab/backups"
修改该配置,定义了默认备份出文件的路径,并执行 gitlab-ctl reconfigure 或者 gitlab-ctl restart 重启服务生效。
恢复前需要先停掉数据连接服务:
gitlab-ctl stop unicorn
gitlab-ctl stop sidekiq
如果是台新搭建的主机,不需要操作,理论上不停这两个服务也可以。停这两个服务是为了保证数据一致性。将老服务器/data/gitlab/backups目录下的备份文件拷贝到新服务器上的/data/gitlab/backups
[root@localhost gitlab]# rsync -avz 1530773117_2019_03_05_gitlab_backup.tar 192.168.95.135:/data/gitlab/backups/
注意权限:600权限是无权恢复的。 实验环境可改成了777,生产环境建议修改属主属组
[root@yunwei-test backups]# pwd
/data/gitlab/backups
[root@yunwei-test backups]# chmod 777 1530773117_2019_03_05_gitlab_backup.tar
[root@yunwei-test backups]# ll
total 17328900
-rwxrwxrwx 1 git git 17744793600 Jul 5 14:47 1530773117_2018_07_05_gitlab_backup.tar
执行下面的命令进行恢复:后面再输入两次yes就完成恢复了。
gitlab-rake gitlab:backup:restore
注意:backups 目录下保留一个备份文件可直接执行
BACKUP=1530773117_2018_07_05_gitlab_backup.tar
恢复完成后,启动刚刚的两个服务,或者重启所有服务,再打开浏览器进行访问,发现数据和之前的一致:
gitlab-ctl start unicorn
gitlab-ctl start sidekiq
或
gitlab-ctl restart
注意:通过备份文件恢复gitlab必须保证两台主机的gitlab版本一致,否则会提示版本不匹配
九、平滑发布与灰度发布
什么叫平滑:在发布的过程中不影响用户的使用,系统不会因发布而暂停对外服务,不会造成用户短暂性无法访问;
什么叫灰度:发布后让部分用户使用新版本,其它用户使用旧版本,逐步扩大影响范围,最终达到全部更新的发布方式 ;
灰度发布与平滑发布其实是关联的。当服务器的数量只有一台的时候,不存在灰度发布,一旦发布了就是所有用户都更新了,
所以这个时候只有平滑发布。当服务器数量大于一台的时候,只要每台服务器都能达到平滑发布的方式,然后设定好需要发布的服务器占比数量,就可以实现灰度发布了。
单台服务器的平滑发布模式:
单机状态下,应用的持续服务主要依靠Nginx的负载均衡及自动切换功能;
为了能够切换应用,需要在服务器中创建两个相同的独立应用,分配两个不同的端口,
例如:app1,端口801; app2,端口802;
在Nginx中,将app1,app2作为负载均衡加载:
upstream myapp{
server 127.0.0.1:801; //app1
server 127.0.0.1:802; //app2
}
然后设置代理超时为1秒,以便在某个应用停止时及时切换到另一个应用:
server {
listen 80;
server_name localhost;
location /{
proxy_pass http://myapp;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 1;
proxy_read_timeout 1;
proxy_send_timeout 1;
}
}
以上内容写在单独的配置文件中:/vhost/pub/pub_app.conf
在nginx.conf里包含进去:
include /vhost/*.conf;
现在系统会均衡地分配用户访问app1与app2。
接下来我们进行平滑发布,我们先把app1停止,然后将新版本发布到app1中:
步骤1: 准备发布app1配置文件
新做一个配置文件 pub_app1_down.conf,内容中把app1停止掉:
upstream myapp{
server 127.0.0.1:801 down; //app1
server 127.0.0.1:802; //app2
}
将这个文件内容覆盖掉在原有的pub_app.conf
cp -f /vhost/pub/pub_app1_down.conf /vhost/pub_app.conf
步骤2:停止app1应用
平滑重新加载一下nginx:
service nginx reload
或者:
/usr/local/nginx/sbin/nginx -s reload
此时所有的请求都转到了app2了;
步骤3:更新app1
现在可以通过各种方式来更新应用了,例如:压缩包方式:
wget http://version.my.com/appudate/myapp/myapp-v3.2.32.tar
unzip -o -d /home/wwwroot/app1/ myapp-v3.2.32.tar
其中:-o:不提示的情况下覆盖文件;-d:指定解压目录
步骤3.5 内部测试
如果需要的话,可以在这一步对app1进行内部测试,以确保应用的正确性;
步骤4:准备发布app2配置文件;
此时app1已经是最新版本的文件了,可以切换到app1来对外,
创建一个新的nginx配置文件:pub_app2_down.conf,设置为app1对外,app2停止即可:
upstream myapp{
server 127.0.0.1:801; //app1
server 127.0.0.1:802 down; //app2
}
将这个文件内容覆盖掉在原有的pub_app.conf
cp -f /vhost/pub/pub_app2_down.conf /vhost/pub_app.conf
步骤5:切换到app1新版本应用
平滑重新一下nginx:
service nginx reload
或者:
/usr/local/nginx/sbin/nginx -s reload
此时所有的请求都转到了app1了,新版本开始运行;
步骤6:更新app2
与第3步一样,解压就可以了,这里可以省去下载过程
unzip -o -d /home/wwwroot/app2/ myapp-v3.2.32.tar
步骤7:恢复app1,app2同时对外:
cp -f /vhost/pub/pub_app.conf /vhost/pub_app.conf
平滑重新一下nginx:
service nginx reload
或者:
/usr/local/nginx/sbin/nginx -s reload
至此,整个应用都已经更新。
将各步骤中的脚本汇总一下:
[pub.sh]
#============ 平滑发布 v1.0 ===============
#step 1
cp -f /vhost/pub/pub_app1_down.conf /vhost/pub_app.conf
#step 2
service nginx reload
#step 3
wget http://version.my.com/appudate/myapp/myapp-v3.2.32.tar
unzip -o -d /home/wwwroot/app1/ myapp-v3.2.32.tar
#step 4
cp -f /vhost/pub/pub_app2_down.conf /vhost/pub_app.conf
#step 5
service nginx reload
#step 6
unzip -o -d /home/wwwroot/app2/ myapp-v3.2.32.tar
#step 7
cp -f /vhost/pub/pub_app.conf /vhost/pub_app.conf
service nginx reload
#============ 平滑发布 v1.0 ===============
备注:也可以充分利用nginx的宕机检测,省去步骤1,2,4,5,7;
简化后的脚本如下:
[pub_mini.sh]
#======== 简化版脚本 =============
wget http://version.my.com/appudate/myapp/myapp-v3.2.32.tar
unzip -o -d /home/wwwroot/app1/ myapp-v3.2.32.tar
unzip -o -d /home/wwwroot/app2/ myapp-v3.2.32.tar
#========= over ===========
# 实验 nginx 配置文件 (按要求创建网站根目录及修改 index.html 文件)
upstream myapp{
server 192.168.11.128:801;
server 192.168.11.128:802;
}
server {
listen 80;
server_name myapp;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://myapp;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 1;
proxy_read_timeout 1;
proxy_send_timeout 1;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
server {
listen 801;
server_name app2;
root /usr/share/nginx/app1-html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
index index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
server {
listen 802;
server_name app2;
root /usr/share/nginx/app2-html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
index index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
多台服务器平滑发布模式:
有了单台平滑发布模式的基础,多台服务器就简单了。
每台服务器当作应用进行发布就可以了,由于nginx有宕机自动检测功能,
只需要在每台服务器上先停止发布,然后更新文件,再启动就可以了;
如果选择部分的服务器进行更新,那就是灰度了。
root /usr/share/nginx/app2-html;
Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
index index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
多台服务器平滑发布模式:
有了单台平滑发布模式的基础,多台服务器就简单了。
每台服务器当作应用进行发布就可以了,由于nginx有宕机自动检测功能,
只需要在每台服务器上先停止发布,然后更新文件,再启动就可以了;
如果选择部分的服务器进行更新,那就是灰度了。
浙公网安备 33010602011771号