GitLab+Jenkins+Rsync+PM2實現(xiàn)Node項目的持續(xù)集成與自動部署

前言

最原始的軟件開發(fā)流程是,在本地搭建好環(huán)境,進行開發(fā)測試,然后去服務(wù)器上搭建環(huán)境,手動上傳代碼,運行測試,然后啟動服務(wù)。實際上,近些年來出現(xiàn)了很多的工具,使得這些步驟可以自動化,大大降低人工出錯的概率,提高生產(chǎn)效率。下面,我就把GitLab+Jenkins+Rsync+PM2實現(xiàn)的Node項目的持續(xù)集成以及自動部署的實驗過程記錄下來。

搭建環(huán)境

需要兩臺服務(wù)器作為演示,A主要進行代碼管理、構(gòu)建和分發(fā),B主要運行實際應(yīng)用。我這邊系統(tǒng)使用的是Debian系的。

服務(wù)器A

GitLab

準(zhǔn)備工作:

apt-get update
apt-get install curl openssh-server ca-certificates postfix

安裝postfix的時候,選internet site,之后的 system mail name 填寫你的服務(wù)器的IP地址。

準(zhǔn)備好后開始安裝:

curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash
apt-get install gitlab-ee

如果 apt 下載很慢可以手動下載 https://packages.gitlab.com/gitlab/gitlab-ee/packages/ubuntu/trusty/gitlab-ee_10.2.2-ee.0_amd64.deb 然后用 dpkg -i 的方式安裝。裝了這個過后 NGINX, Postgres, Redis 就都裝好了。

配置:

GitLab默認(rèn)會占用80、8080和9090端口,Jenkins默認(rèn)也會使用8080端口,所以將GitLab的默認(rèn)端口為60200、60201、60202(你可以隨意定制)

vim /etc/gitlab/gitlab.rb 修改

external_url 'http://<你的服務(wù)器ip>:60200'
unicorn['port'] = 60201
prometheus['listen_address'] = 'localhost:60202'

注意不能有多余空格。gitlab-ctl reconfigure生效配置,gitlab-ctl start啟動。
如果要想發(fā)郵件的話還要配置第三方郵件 vim /etc/gitlab/gitlab.rb

gitlab_rails['smtp_enable'] = true 
gitlab_rails['smtp_address'] = "smtp.exmail.qq.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "***#**"
gitlab_rails['smtp_password'] = "**************"
gitlab_rails['smtp_domain'] = "qq.com"
gitlab_rails['smtp_authentication'] = :login 
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = true
gitlab_rails['gitlab_email_from'] = "***#**"
user["git_user_email"] = "***#**"

然后生效重啟,打開http://<你的服務(wù)器IP>:60200訪問,

Jenkins

準(zhǔn)備工作:

wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u151-b12/e758a0de34e24606bca991d704f6dcbf/jdk-8u151-linux-x64.tar.gz"
tar xzvf jdk-8u151-linux-x64.tar.gz -C /usr/local/  
vim /etc/profile #(加入環(huán)境變量)
    export JAVA_HOME=/usr/local/jdk1.8.0_151
    export PATH=$JAVA_HOME/bin:$PATH

退出,source /etc/profile 生效,用 java -version 驗證是否裝好java。

開始安裝:

curl -O http://mirrors.jenkins.io/war-stable/latest/jenkins.war 下載Jenkins,
nohup java -jar jenkins.war --httpPort=60203 & 后臺啟動并指定端口。
至此,Jenkins安裝成功,可以用瀏覽器打開 http://<你的服務(wù)器ip>:60203
然后安裝必要的插件(會提示你),依次點擊 “系統(tǒng)管理” “管理插件”。
切換到“可選插件”,分別搜索“GitLab Plugin”和“Git Plugin”,然后點擊“直接安裝”。如果在“可選插件”里沒有搜到,可能自帶安裝了

Node

apt-get update
apt-get install -y build-essential curl
curl -sL https://deb.nodesource.com/setup_8.x | bash 
apt-get install -y nodejs
node -v
v8.9.2
npm -v
5.5.1

Rsync

這個服務(wù)器主要使用Rsync來發(fā)布文件,所以不需要特殊配置,一般Linux都默認(rèn)安裝了,如果沒有,則使用 apt-get install rsync。然后配置Rsync密碼

echo "123" >> /etc/rsync.password
chmod -R 600 /etc/rsync.password

服務(wù)器B

Node

如A

PM2

npm install -g pm2
pm2 -v
2.8.0

Rsync

為了安全性不要直接使用ssh賬號密碼或者公鑰私鑰,而是構(gòu)建Rsync服務(wù)。vim /etc/rsyncd.conf,修改配置,下面的配置只是一個示例,生產(chǎn)環(huán)境還要更安全的策略。

##rsyncd.conf start##
uid = root
gid = root
use chroot = yes
max connections = 200
timeout = 300
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsyncd.log
ignore errors
read only = false
list = false
hosts allow = * 
hosts deny =10.0.8.9
auth users = backuser
secrets file = /etc/rsync.password
[webapp]
path = /var/webapp/

上面的的路徑path不存在則需要創(chuàng)建 mkdir /var/webapp
echo "backuser:123" >> /etc/rsync.password 添加賬號和密碼,密碼要與客戶端(A)一直
chmod -R 600 /etc/rsync.password 修改權(quán)限
rsync --daemon 以守護進程方式來啟動rsync服務(wù)
chkconfig rsync on將此服務(wù)設(shè)置成為開機自啟動

應(yīng)用開發(fā)

用express開發(fā)一個 hello world 作為演示,在本地工程目錄

npm init #(按照提示輸入?yún)?shù))
npm install express --save  #(安裝express)

然后創(chuàng)建app.js

var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;

  console.log('Example app listening at http://%s:%s', host, port);
});

node app.js 運行,然后http://localhost:3000/ 會得到 hello world

新建app.json

{
    "apps" : [
        {
            "name"        : "app",
            "script"      : "app.js",
            "log_date_format"  : "YYYY-MM-DD HH:mm:SS",
            "env": {
                "NODE_ENV": "production"
            },
            "watch" : [
                "app.js",
                "router",
                "util"
            ],
            "ignore_watch" : [
                "logs",
                "node_modules",
                "test"
            ]
        }
    ]
}

將代碼上傳至服務(wù)器B,然后 pm2 start app.json 運行 即可在瀏覽器訪問 http://B-ip:3000 得到 hello world

持續(xù)集成和自動部署

配置 Gitlab

首次登陸的密碼是會提示你去服務(wù)器找,用戶是root,然后修改你的用戶賬號信息,添加你自己常用的電腦上的git公鑰。
創(chuàng)建一個新項目 webapp ,創(chuàng)建好過后項目會顯示該項目對應(yīng)的用戶信息(會提示你修改)

Git global setup

git config --global user.name "MageekChiu"
git config --global user.email "mageekchiu@mail.**.cn"

在本地項目目錄下,新建 .gitignore 文件(window 要用 命令行 rename才可以)

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

node_modules/

然后執(zhí)行

git init
git remote add origin git@A-ip:root/webapp.git
git add .
git commit -m "Initial commit"
git push -u origin master

即可提交服務(wù)器倉庫,以后每次修改都要

git add .
git commit -m "修改備注"

配置 jenkins

首先配置GitLab插件:
打開GitLab,點擊“setting”——“Account”,復(fù)制“Private token”,或者應(yīng)該首先生成personal access token。
打開Jenkins,點擊“系統(tǒng)管理”——“系統(tǒng)設(shè)置”,點擊“配置”下拉框,點擊“Gitlab”選項配置GitLab
Connection Name 隨便,如 gitlab,“Git Host URL”填GitLab的訪問地址,
然后Credentials點“Add”——“jenkins”,在彈出框里,“kind”選擇“GitLab API Token”,將先前復(fù)制的“Private token”粘貼到“API token”輸入框中,然后點擊“Add”,添加后,Credentials選擇剛剛新建的gitlab,
最后點擊“test connection”,看到“Success”就成功了。然后點擊頁面底下的“apply”,再點擊“save”

然后配置Git插件:
需要注意的是裝Jenkins的機器上一定要裝git: apt-get install git 這樣Jenkins才能去 gitlab 拉取文件。
打開Jenkins,點擊“系統(tǒng)管理”——“系統(tǒng)設(shè)置”,點擊“配置”下拉框,選擇“Git plugin”選項,設(shè)置Git插件的全局配置,填入上面的 global setting 如 global user.name等,然后點擊“apply”——“save”

生成訪問Gitlab的ssh秘鑰:
打開GitLab,點擊右上角的“setting”—— SSH Keys,就可以進入到添加界面。
在jenkins所在服務(wù)器上生成密鑰
ssh-keygen -t rsa -C "root@<你服務(wù)器的ip地址>" -b 4096
ssh-keygen -t rsa -C "root@" -b 4096
全部按 Enter 使用默認(rèn)值,這會生成一對公鑰和私鑰。打開公鑰復(fù)制到gitlab的添加界面,然后點擊“add key”,并記住私鑰的存放路徑。

創(chuàng)建一個Jenkins Job:
直接點新建,“item name”可以隨便起,然后點擊“構(gòu)建一個自由風(fēng)格的軟件項目”,點擊“OK”,至此,創(chuàng)建一個Job成功了。然后配置這個job,選擇“源碼管理”,選擇“Git”,然后去GitLab中復(fù)制項目地址,粘貼到“Repository URL”,然后點擊“credentials”后面的“Add”按鈕
在彈出頁面里面:
● Kind 選擇 SSH Username with private key
● Username 填 root
● PrivateKey 選擇 From a file on jenkins master ,然后將服務(wù)器的 私鑰的存放路徑(/root/.ssh/id_rsa ) 粘貼進去
然后點擊“Add”,在“credentials”里選擇我們剛剛創(chuàng)建的認(rèn)證方式。如果沒報錯,說明成功了,點擊頁面底部的“apply”。如果出錯了,會在“Repository URL”和“Credentials”之間顯示紅色的錯誤信息。

選擇 構(gòu)建觸發(fā)器:
選擇 Build when a change is pushed to GitLab. 記住這個 GitLab CI Service URL ,點擊高級
Secret token 那一行下面 點擊 generate。記住這個token
選擇 構(gòu)建:
選擇 execute shell

npm install 
WEB_SERVER_IP=B的ip
PROJECT=webapp/
rsync -arqz --delete-before $WORKSPACE/ $WEB_SERVER_IP::$PROJECT --exclude ".git" --password-file=/etc/rsync.password 

這一段代碼的主要目的是構(gòu)建,并分發(fā)代碼,如果有多個應(yīng)用服務(wù)器就要分發(fā)到多個服務(wù)器上。

配置gitab的webhook:
點擊webapp 項目下面的setting的integrations 輸入剛才的 GitLab CI Service URL 和 Secret Token
然后點擊add webhook ,再測試一下選擇 push events 如果顯示Hook executed successfully: HTTP 200 即成功,然后在jenkins里面查看是有一次構(gòu)建記錄的。

這樣jenkins就會在代碼發(fā)生變化時自動拉取代碼到本地,構(gòu)建,然后用rsync分發(fā)給各個應(yīng)用服務(wù)器,結(jié)合PM2的watch功能實現(xiàn)自動發(fā)現(xiàn)代碼更新并重啟的功能,達到自動部署的目的

最終效果測試

修改代碼,把hello world改為hello gitlab+enkins然后 add、commit、push 。在A上面gitlab有提交記錄,jenkins有構(gòu)建記錄,在B上面用 pm2 ls 發(fā)現(xiàn)項目是restart了,瀏覽器查看也變成hello gitlab+enkins 了。
嘗試成功!
雖然這個配置比較麻煩,但是持續(xù)集成和自動部署的帶來的好處是更大的:代碼有版本管理,可以快速迭代、快速回滾,同時保持高質(zhì)量、自動多機部署防止人工錯誤,每次構(gòu)建都有記錄,構(gòu)建冪等......

參考

http://blog.csdn.net/ruangong1203/article/details/73065410

原文

后記

這個過程已經(jīng)比較自動化了,但是還是有太多的環(huán)境搭建過程,比如webapp一般都會用到mysql、redis、MongoDB等等,一個更自動化的過程應(yīng)該引入docker,這方面以后有機會再嘗試。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容