GitLab 非 Docker .NET Core CI/CD搭建

公司的 GitLab 服务部署完了,但是领导出于性能方面的考虑,希望测试和生产环境不用 Docker 来部署,遂搭建了一套不基于Docker 的 GitLab CI/CD 负载均衡测试环境。

注册 GitLab-Runner

安装 GitLab-Runner

这里我没有按照官方教程来直接下载对应系统的包安装,而是使用了清华大学开源镜像站的方法:

注册启用 GitLab-Runner

转到搭建好的GitLab的具体项目CICD项目设置页
https://gitlab.xxx/user/project/settings/ci_cd

然后用GitLab提供的令牌和地址对GitLab进行注册:

1
2
3
4
gitlab-runner register
gitlab.xxx
xxxxx
shell

测试机负载均衡和Daemon

负载均衡

负载均衡方面,国际惯例,还用 nginx 来做

直接用 yum 安装

1
yum install -y nginx

配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
worker_connections 1024;
}

http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;

include /etc/nginx/mime.types;
default_type application/octet-stream;

include /etc/nginx/conf.d/*.conf;

# 待选服务器列表
upstream myproject{
# ip_hash;
server Y.Y.Y.Y:4411 weight=7;
server X.X.X.X:4411 weight=3;
}
# HTTP 配置
server {
listen 80;
listen [::]:80;

location / {
proxy_pass http://myproject;
}
}

# Settings for a TLS enabled server.
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;

ssl_certificate "/etc/nginx/ssl/ssl_certificate.pem";
ssl_certificate_key "/etc/nginx/ssl/ssl_certificate_key.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

location / {
proxy_pass http://myproject;
}
}
}

Daemon

Daemon 方面,用过的几个里,个人觉得使用舒适度从低到高是 Systemd < Supervisor < PM2,直接选PM2了,原理一样,可以很方便的更换其他。
在做了负载均衡的两台服务器上做以下相同配置:

  1. 安装 NodeJS
    1
    sudo yum install -y nodejs gcc-c++ make yarn


2. 切换 Registry

1
2
npm install -g nrm
nrm use taobao


3. 安装 PM2

1
npm install -g pm2


4. 配置 PM2 自启

1
pm2 startup


5. 新建 dotnet 守护服务,保存 pm2 守护列表

1
2
pm2 start "dotnet test-ci.dll" --name testCI
pm2 save


GitLab CI/CD

配置变量

在项目源码更目录增加 .gitlab-ci.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
stages:
- build
- deploy_dev
build_job:
stage: build
only:
- master
script:
- cd test-ci
- dotnet restore
- dotnet build
before_script:
- export COMMIT_TIME=$(git show -s --format=%ct $CI_COMMIT_SHA)
- export COMMIT_TIME_STR=$(date -d @$COMMIT_TIME +%Y%m%d%k%M%S)
deploy_master_job:
stage: deploy_dev
environment:
name: development
only:
- master
script:
# 发布程序并部署运行
- cd test-ci
- echo "version:$COMMIT_TIME_STR"
# 发布
- dotnet publish -c Release --output bin/publish
# 压缩
- cd bin/publish
- zip -r $COMMIT_TIME_STR.zip ./
# 备份
- cp $COMMIT_TIME_STR.zip /opt/backup-cd/test-ci/
# 部署服务一
- lftp sftp://$DEV_URL_1 -e "user $DEV_USER $DEV_PASS; cd /root/test-ci; put $COMMIT_TIME_STR.zip; bye"
- sshpass -p "$DEV_PASS" ssh -o StrictHostKeyChecking=no $DEV_USER@$DEV_URL_1 "cd /root/test-ci;unzip -o ./$COMMIT_TIME_STR.zip;rm -Rf ./$COMMIT_TIME_STR.zip;"
- sshpass -p "$DEV_PASS" ssh -o StrictHostKeyChecking=no $DEV_USER@$DEV_URL_1 "pm2 restart testCI;pm2 status;"

# 部署服务二
- lftp sftp://$DEV_URL_2 -e "user $DEV_USER $DEV_PASS; cd /root/test-ci; put $COMMIT_TIME_STR.zip; bye"
- sshpass -p "$DEV_PASS" ssh -o StrictHostKeyChecking=no $DEV_USER@$DEV_URL_2 "cd /root/test-ci;ls;unzip -o ./$COMMIT_TIME_STR.zip;rm -Rf ./$COMMIT_TIME_STR.zip"
- sshpass -p "$DEV_PASS" ssh -o StrictHostKeyChecking=no $DEV_USER@$DEV_URL_2 "pm2 restart testCI;pm2 status;"
# 删除压缩包
- rm -Rf ./$COMMIT_TIME_STR.zipx

一些坑

NodeJS

使用 yum 安装的官方提供的 NodeJS 最新版本为6.X,使用nrm会报错,属于低版本NodeJS本身对coffeescript的兼容问题,想要安装新版的NodeJS可以参考这篇文章,我用的方法是nodesource/distributions