0 前言
記錄 jenkins 基于 docker 的前后端項(xiàng)目的構(gòu)建及部署全流程塌鸯。后端項(xiàng)目案例使用 SpringBoot+Gradle,前端項(xiàng)目案例框架不限
1 部署 jenkins
1.1 獲取鏡像
前往 https://hub.docker.com/r/jenkins/jenkins/tags 獲取鏡像:jenkins/jenkins:2.232-slim
。也可以直接獲取支持 jdk11 的鏡像:jenkins/jenkins:2.232-jdk11
鼠锈,但該鏡像體積較大岭粤,不選擇。三種官方鏡像信息如下:
[root@54s9uer src]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jenkins/jenkins 2.232-centos a355678ccb95 41 hours ago 782MB
jenkins/jenkins 2.232-jdk11 3ea7fe8adf57 41 hours ago 766MB
jenkins/jenkins 2.232-slim 803c6c58592b 41 hours ago 470MB
注: jenkins 有關(guān) jdk11 兼容性的文檔詳見(jiàn):jenkins-on-java-11
1.2 創(chuàng)建宿主機(jī)掛載目錄
/usr/src/jenkins_home
1.2.1 掛載目錄權(quán)限問(wèn)題
若直接掛載上述目錄派昧,會(huì)因權(quán)限問(wèn)題而無(wú)法啟動(dòng)容器黔姜。失敗信息可使用 docker logs <容器ID>
命令查看容器日志:
touch: cannot touch '/var/jenkins_home/copy_reference_file.log': Permission denied
Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?
此時(shí),先不進(jìn)行掛載蒂萎,使用 docker run -it --rm jenkins/jenkins:jdk11 /bin/bash
建立一個(gè)測(cè)試容器秆吵,執(zhí)行 whoami && id
命令獲取當(dāng)前用戶信息
jenkins@8dced799c01c:/$ whoami && id
jenkins
uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins)
默認(rèn)情況下,容器用戶是 jenkins五慈。進(jìn)一步查看容器的 jenkins_home 目錄權(quán)限纳寂,發(fā)現(xiàn)所有者也是 jenkins,如下所示:
jenkins@8dced799c01c:/$ ls -la /var/jenkins_home
total 20
drwxr-xr-x 2 jenkins jenkins 4096 Apr 12 00:54 .
drwxr-xr-x 1 root root 4096 Apr 6 09:01 ..
-rw-r--r-- 1 jenkins jenkins 50 Apr 12 00:54 copy_reference_file.log
-rw-rw-r-- 1 root root 7152 Apr 6 08:55 tini_pub.gpg
注:即使添加 -u root
參數(shù)進(jìn)入容器泻拦,jenkins_home 的所有者依然是 jenkins
回到宿主機(jī)毙芜,查看 /usr/src/jenkins_home 權(quán)限,所有者是 root争拐。因此當(dāng)容器的 jenkins 用戶進(jìn)程訪問(wèn)宿主機(jī)的 /usr/src/jenkins_home 目錄時(shí)腋粥,就出現(xiàn) Permission denied 的問(wèn)題。
1.2.2 解決方案
根據(jù)測(cè)試容器用戶 uid 的結(jié)果架曹,修改宿主機(jī) /usr/src/jenkins_home 的所有者隘冲,執(zhí)行 chown -R 1000 /usr/src/jenkins_home
注:該解決方案參考了 https://yq.aliyun.com/articles/53990
1.3 啟動(dòng)容器
docker run --name jenkins \
-p 8080:8080 \
--mount type=bind,src=/usr/src/jenkins_home,dst=/var/jenkins_home \
-d \
jenkins/jenkins:jdk11
1.4 添加項(xiàng)目構(gòu)建依賴
用 root 身份進(jìn)入容器
docker exec -it -u root <容器ID> /bin/bash
1.4.1 安裝 git
(1)由于 jenkins/jenkins:2.232-slim
基礎(chǔ)鏡像為 Debian,因此使用 apt 工具安裝
apt-get update
apt-get install git
注:通過(guò)該方法安裝的版本不是最新
(2)查看執(zhí)行路徑
root@832c29984d24:/usr/bin# git --exec-path
/usr/lib/git-core
因此在 jenkins 的 全局工具配置
中需要的 Path to Git executable
就是 /usr/lib/git-core/git
附加內(nèi)容:查看容器的系統(tǒng)版本绑雄。以 jenkins/jenkins:2.232-slim
鏡像為例展辞,進(jìn)入容器后可執(zhí)行如下命令查看
root@832c29984d24:/# cat /etc/issue
Debian GNU/Linux 10 \n \l
注:不可用 cat /proc/version
或 uname -a
,得到的結(jié)果是是宿主機(jī)的系統(tǒng)信息万牺。
附加內(nèi)容:Debian 應(yīng)用的安裝路徑通常在 /usr/share
罗珍,可執(zhí)行文件路徑通常在 /usr/bin
,配置文件路徑通常在 /etc
1.4.2 安裝 Amazon Corretto 11
后端項(xiàng)目案例使用 Amazon Corretto 11杏愤。jenkins 構(gòu)建項(xiàng)目時(shí)也需要使用靡砌,與容器的自帶 openJDK 不沖突,可以不在 /etc/profile 中設(shè)置 JAVA_HOME珊楼,只在 jenkins 的 全局工具配置
中指定即可通殃。
注:若使用 jenkins/jenkins:2.232-jdk11
鏡像,并且使用自帶 openJDK,可使用 echo $JAVA_HOME
查看路徑画舌,直接復(fù)制到 jenkins 的 全局工具配置
中對(duì)應(yīng)位置堕担。
(1)在 下載頁(yè)面 獲取壓縮包地址,下載到 /usr/src/ 目錄下
wget -c https://d3pxv6yz143wms.cloudfront.net/11.0.3.7.1/amazon-corretto-11.0.3.7.1-linux-x64.tar.gz
注:若需要安裝 wget 命令曲聂,執(zhí)行 apt-get install wget
即可
(2)解壓到 /usr/src/jdk11 目錄
tar zxvf amazon-corretto-11.0.3.7.1-linux-x64.tar.gz -C /usr/src/jdk11/
因此在 jenkins 的 全局工具配置
中需要的 JAVA_HOME 就是 /usr/src/jdk11/amazon-corretto-11.0.3.7.1-linux-x64/
1.4.3 安裝 NodeJs 插件
為構(gòu)建前端項(xiàng)目霹购,需安裝 NodeJs 插件。
(1)前往 jenkins 的插件管理界面搜索安裝
(2)進(jìn)入 全局工具配置
中配置 nodejs 的版本和別名
附加內(nèi)容:jenkins 插件及應(yīng)用路徑
- 插件路徑:
$JENKINS_HOME/plugins
朋腋,其中$JENKINS_HOME
默認(rèn)值為/var/jenkins_home
- nodejs 路徑:
$JENKINS_HOME/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation
1.4.4 安裝 Gradle
需要安裝 Gradle Plugin 插件齐疙。進(jìn)入 全局工具配置
選擇自動(dòng)安裝,版本按需選擇旭咽。
3 手動(dòng)構(gòu)建后端項(xiàng)目
新建 Freestyle project
贞奋,輸入任務(wù)名稱后進(jìn)入詳細(xì)配置。
(1)General
填寫項(xiàng)目地址穷绵,不帶 tree/master 或 tree/branch 部分轿塔,如 https://github.com/username/repositoryname.git
(2)源碼管理
選擇 Git,在 Repository URL 欄填寫 GitHub 倉(cāng)庫(kù)的 https 鏈接(如 https://github.com/username/repositoryname.git
)仲墨,Branchs to build 填寫要被構(gòu)建的分支勾缭,如 */master
,源碼庫(kù)瀏覽器選擇自動(dòng)目养。
(3)構(gòu)建
新增 Invoke Gradle
構(gòu)建步驟俩由,選擇對(duì)應(yīng)別名;點(diǎn)擊高級(jí)癌蚁,設(shè)置要執(zhí)行的 Tasks 為 bootJar采驻,其余欄位保持默認(rèn)或空白。
4 手動(dòng)構(gòu)建前端項(xiàng)目
新建 Freestyle project
匈勋,輸入任務(wù)名稱后進(jìn)入詳細(xì)配置。
(1)General
填寫項(xiàng)目地址膳叨,不帶 tree/master 或 tree/branch 部分洽洁,如 https://github.com/username/repositoryname.git
(2)源碼管理
選擇 Git,在 Repository URL 欄填寫 GitHub 倉(cāng)庫(kù)的 https 鏈接(如 https://github.com/username/repositoryname.git
)菲嘴,Branchs to build 填寫要被構(gòu)建的分支饿自,如 */master
,源碼庫(kù)瀏覽器選擇自動(dòng)龄坪。
(3)構(gòu)建
新增 Executes a NodeJS script
構(gòu)建步驟昭雌,選擇 NodeJs 插件對(duì)應(yīng)的別名;再新增 執(zhí)行 shell
構(gòu)建步驟健田,添加命令 node -v && npm -v && npm install --registry=http://registry.npm.taobao.org && npm run build
5 其他配置案例
5.1 GitHub 倉(cāng)庫(kù)分支有變動(dòng)時(shí)(提交或合并到該分支)自動(dòng)構(gòu)建
5.1.1 配置 GitHub
(1)進(jìn)入倉(cāng)庫(kù)的 Settings烛卧,側(cè)邊欄找到 Webhooks 并新建。輸入 Payload URL妓局,該地址默認(rèn)為 http://<宿主機(jī)IP>:8080/github-webhook/
总放,其余選項(xiàng)保持默認(rèn)即可生成
注:webhook 是通知 Jenkins 的請(qǐng)求地址呈宇,GitHub 通過(guò)該地址通知 Jenkins 發(fā)生的事件
(2)配置 Personal access tokens,開放 admin:repo_hook
(包含 write:repo_hook 和 read:repo_hook)即可
5.1.2 配置 jenkins
(1)主界面進(jìn)入 Manager Jenkins
局雄,找到 Github 服務(wù)器
項(xiàng)
注:該配置項(xiàng)需安裝 GitHub Plugin 插件
(2)名稱
可任意輸入甥啄,能辨識(shí)即可
(3)API URL
保持默認(rèn) https://api.github.com
即可
(4)添加憑據(jù),類型選擇 Secret text
炬搭,在 Secret
欄填入在 GitHub 生成的 Personal access tokens蜈漓;描述
欄可任意輸入,能辨識(shí)即可
(5)憑據(jù)
下拉菜單選擇新添加的憑據(jù)名稱后宫盔,點(diǎn)擊 連接測(cè)試
融虽,若成功則配置完成
注:憑據(jù)不能使用 Username with password
類型
附加內(nèi)容:修改 jenkins 默認(rèn)的 Webhooks 地址可在 Github 服務(wù)器
項(xiàng)右下角點(diǎn)擊 高級(jí)
,出現(xiàn)的 覆蓋 Hook URL
即可重新指定飘言。
5.1.3 任務(wù)詳細(xì)配置
在 手動(dòng)構(gòu)建
基礎(chǔ)上增加如下配置:
(1)在 構(gòu)建觸發(fā)器
項(xiàng)中勾選 GitHub hook trigger for GiTScm polling
(2)在 構(gòu)建環(huán)境
項(xiàng)中勾選 Use secret text(s) or file(s)
衣形,彈出菜單選擇 指定憑據(jù)
,選擇之前步驟設(shè)定的憑據(jù)別名姿鸿,變量欄
可空
完成上述設(shè)置后即可實(shí)現(xiàn)當(dāng) GitHub 庫(kù)分支有變動(dòng)時(shí)谆吴,如直接提交或從其他分支合并到該分支,就觸發(fā)構(gòu)建苛预。
5.2 前端及后端項(xiàng)目構(gòu)建成功后自動(dòng)部署到遠(yuǎn)端容器
5.2.1 公共配置部分
5.2.1.1 開啟 ssh 服務(wù)
(1)基礎(chǔ)鏡像 debian 默認(rèn)不帶 ssh句狼,執(zhí)行 apt-get install openssh-server
安裝
(2)service ssh start
啟動(dòng)服務(wù)
(3)ps -e | grep ssh
驗(yàn)證安裝
root@aa751ea246b2:/# ps -e | grep ssh
2777 ? 00:00:00 sshd
注:若需要安裝 ps 命令,執(zhí)行 apt-get install procps
即可
5.2.1.2 root 賬號(hào)密碼設(shè)置
(1)開啟允許 root 登陸热某,執(zhí)行 vim /etc/ssh/sshd_config
修改配置文件腻菇,將 PermitRootLogin
項(xiàng)改為 yes
(默認(rèn)值 prohibit-password
阻止密碼登陸;另有值 without-password
可不需密碼登陸)
(2)執(zhí)行 /etc/init.d/ssh restart
更新設(shè)置
(3)執(zhí)行 passwd root
修改 root 密碼
附加內(nèi)容:安裝 ssh 后添加普通權(quán)限用戶并設(shè)置密碼
useradd user
passwd user
5.2.1.3 root 免密登陸設(shè)置
(1)暫缺
備用:將 PasswordAuthentication
項(xiàng)改為 no
(默認(rèn) yes
開啟密碼身份驗(yàn)證)
5.2.1.4 Publish over SSH 插件賬號(hào)+密碼連接設(shè)置
(1)進(jìn)入 系統(tǒng)配置
找到 Publish over SSH 的配置項(xiàng)昔馋,前幾項(xiàng)配置留空筹吐,直接展開高級(jí)設(shè)置,勾選Use password authentication, or use a different key
秘遏,讓每個(gè)連接使用獨(dú)立設(shè)置的賬戶和密碼丘薛。
(2)填寫以下主要配置項(xiàng),其余可留空或保持默認(rèn)值
-
Name
邦危,隨意填寫 -
Hostname
洋侨,遠(yuǎn)端容器的 IP 地址 -
Username
,填入 root -
Remote Directoty
倦蚪,遠(yuǎn)端容器接收傳輸文件的目錄路徑 -
Passphrase / Password
希坚,填入賬戶對(duì)應(yīng)密碼
(2)測(cè)試設(shè)置,提示 Success 說(shuō)明連接正常
附加內(nèi)容:查看容器 IP 地址
- 方式一:在宿主機(jī)執(zhí)行
docker inspect <容器ID>
陵且,找到 IPAddress 即可 - 方式二:進(jìn)入容器裁僧,執(zhí)行
ifconfig
即可
附加內(nèi)容:debian 安裝網(wǎng)絡(luò)命令
- 安裝 ifconfig:
apt-get install net-tools
- 安裝 ping:
apt-get install iputils-ping
- 安裝 ip:
apt-get install iproute2
5.2.1.5 Publish over SSH 插件免密連接設(shè)置
(1)暫缺
5.2.3 前端項(xiàng)目自動(dòng)部署詳細(xì)配置
當(dāng) master 分支有變動(dòng)時(shí),jenkins 容器負(fù)責(zé)從 github 獲取最新源代碼并執(zhí)行 npm build 構(gòu)建,將構(gòu)建結(jié)果锅知,即 build 目錄下內(nèi)容發(fā)送到遠(yuǎn)端容器接收目錄播急,發(fā)送之前清空接收目錄。主要路徑定義如下:
- 遠(yuǎn)端容器接收目錄為
/usr/src/static
- jenkins 容器從 github 獲得的源碼目錄為
/var/jenkins_home/workspace/testfrontend
- jenkins 容器構(gòu)建后售睹,需要傳輸?shù)哪夸洖?
/var/jenkins_home/workspace/testfrontend/build
(1)進(jìn)入項(xiàng)目配置桩警,在 構(gòu)建
環(huán)節(jié)增加 Send files or execute commands over SSH
(2)填寫以下主要配置項(xiàng),其余可留空或保持默認(rèn)值
-
Name
昌妹,選擇在系統(tǒng)配置
中定義的名稱 -
Source files
捶枢,留空 -
Remove prefix
,留空 -
Remote Directoty
飞崖,留空 -
Exec command
烂叔,填入以下命令:
cd /usr/src/
rm -rf static
mkdir static
(3)在 構(gòu)建后操作
環(huán)節(jié)增加 Send build artifacts over SSH
,并填寫以下主要配置項(xiàng)固歪,其余可留空或保持默認(rèn)值
-
Name
蒜鸡,選擇在系統(tǒng)配置
中定義的名稱 -
Source files
,填入build/**
-
Remove prefix
牢裳,填入build
-
Remote Directoty
逢防,留空 -
Exec command
,留空
附加內(nèi)容:勾選 Send files or execute commands over SSH after the build runs
與在 構(gòu)建后操作
中添加 Send build artifacts over SSH
的區(qū)別:前者無(wú)論構(gòu)建是否成功都執(zhí)行蒲讯,后者需要構(gòu)建成功才執(zhí)行忘朝。
5.2.4 后端項(xiàng)目自動(dòng)部署詳細(xì)配置
5.2.4.1 建立應(yīng)用容器
后端項(xiàng)目案例使用 Amazon Corretto 11,但官方鏡像選擇的基礎(chǔ)鏡像使用上多有不便判帮,因此選用 debian 自行創(chuàng)建局嘁。
(1)基礎(chǔ)鏡像選擇 debian:stable-20200414
(2)按照 官方文檔 的安裝方式
(3)安裝 JDK 之前,請(qǐng)安裝 java-common 軟件包
apt-get update
apt-get install java-common
(4)從 下載 頁(yè)面下載 Linux .deb
文件晦墙。
注:可能需要安裝 wget 命令悦昵,執(zhí)行 apt-get install wget
即可
(5)安裝 .deb 文件。
dpkg --install java-11-amazon-corretto-jdk_11.0.3.7-1_amd64.deb
注:stable-slim 鏡像無(wú)法用該方法安裝 jdk11晌畅,原因暫時(shí)未知
5.2.4.2 配置
當(dāng) master 分支有變動(dòng)時(shí)旱捧,jenkins 容器負(fù)責(zé)從 github 獲取最新源代碼,并使用 gradle 構(gòu)建踩麦,將構(gòu)建結(jié)果,即 build/libs 目錄下 jar 包發(fā)送到遠(yuǎn)端容器接收目錄氓癌,發(fā)送之前清空接收目錄谓谦。主要路徑定義如下:
- 遠(yuǎn)端容器接收目錄為
/usr/src/jdkapp
- jenkins 容器從 github 獲得的源碼目錄為
/var/jenkins_home/workspace/testbackend
- jenkins 容器構(gòu)建后,需要傳輸?shù)奈募?
/var/jenkins_home/workspace/testbackend/build/libs/demo.jar
(1)進(jìn)入項(xiàng)目配置贪婉,在 構(gòu)建
環(huán)節(jié)增加 Send files or execute commands over SSH
(2)填寫以下主要配置項(xiàng)反粥,其余可留空或保持默認(rèn)值
-
Name
,選擇在系統(tǒng)配置
中定義的名稱 -
Source files
,留空 -
Remove prefix
才顿,留空 -
Remote Directoty
莫湘,留空 -
Exec command
,填入以下命令:
cd /usr/src/
rm -rf jdkapp
mkdir jdkapp
(3)在 構(gòu)建后操作
環(huán)節(jié)增加 Send build artifacts over SSH
郑气,并填寫以下主要配置項(xiàng)幅垮,其余可留空或保持默認(rèn)值
-
Name
,選擇在系統(tǒng)配置
中定義的名稱 -
Source files
尾组,填入build/libs/*.jar
-
Remove prefix
忙芒,填入build/libs
-
Remote Directoty
,留空 -
Exec in pty
讳侨,勾選該項(xiàng)復(fù)選框呵萨,開啟偽終端 -
Exec command
,填入以下命令:
cd /usr/src/
cat /dev/null > nohup.out
nohup sh runjdkapp.sh
對(duì)應(yīng)的 runjdkapp.sh
文件參考內(nèi)容如下:
#!/bin/bash
port=3006
filter=$(netstat -ntlp | grep $port | awk '{print $7}' | awk -F '/' '{print $1}')
for var in $filter
do
kill -9 $var
done
nohup java -jar /usr/src/jdkapp/demo.jar &
注:可能需要安裝 netstat 命令跨跨,執(zhí)行 apt-get install net-tools
即可
5.2.5 主要配置項(xiàng)釋義
以前端項(xiàng)目為例:
Flatten files潮峦,扁平化文件。只上傳文件勇婴,不上傳文件所屬文件夾忱嘹。
Source files,需要傳輸?shù)奈募毓ⅰH粢獋鬏斈夸浀铝拢聪喈?dāng)于傳輸其下所有文件,例如:
build/**
萨螺,可參看 規(guī)則窄做。注意,構(gòu)建后所在路徑位置默認(rèn)指向工作空間慰技,即/var/jenkins_home/workspace/testfrontend
椭盏,因此該配置項(xiàng)直接用目錄名build
即可,不用寫長(zhǎng)串內(nèi)容吻商。Remove prefix掏颊,移除傳輸文件路徑前綴。該配置項(xiàng)可結(jié)合以上 Source files 的例子來(lái)看艾帐。若留空乌叶,則遠(yuǎn)端最終結(jié)果是
/usr/src/static
目錄下還有一層build
目錄,不符合需求柒爸,因此需要把「前綴」移除准浴,則所需文件路徑不帶build/
前綴,就直接放到/usr/src/static
目錄下捎稚。Remote directoty乐横,在目標(biāo)目錄下創(chuàng)建一個(gè)新目錄求橄。該項(xiàng)若留空,則直接將文件放到本案例中的
/usr/src/static
下葡公,假設(shè)填寫var
罐农,將文件放到本案例中的/usr/src/static/var
下。
以 index.html 路徑為例催什,上述配置效果可見(jiàn)下表:
Remote Directoty(系統(tǒng)配置) | Source files | Remove prefix | Remote Directoty(項(xiàng)目配置) | 結(jié)果 | |
---|---|---|---|---|---|
1 | /usr/src/static | build/** | build | /usr/src/static/index.html | |
2 | /usr/src/static | build/** | /usr/src/static/build/index.html | ||
3 | /usr/src/static | build/** | var | /usr/src/static/var/build/index.html | |
4 | /usr/src/static | build/** | build | var | /usr/src/static/var/index.html |
6 其他問(wèn)題
6.1 提示內(nèi)存不足涵亏,構(gòu)建失敗
進(jìn)入 jenkins 查看失敗的控制臺(tái)輸出,其中有如下信息:
OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000e0000000, 89456640, 0) failed; error='Not enough space' (errno=12)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 89456640 bytes for committing reserved memory.
# An error report file with more information is saved as:
# /var/jenkins_home/.gradle/daemon/5.6.2/hs_err_pid2363.log
進(jìn)一步查看上述 gradle 的日志文件蛆楞,其中有如下內(nèi)容:
root@832c29984d24:/var/jenkins_home/.gradle/daemon/5.6.2# cat hs_err_pid2363.log
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 89456640 bytes for committing reserved memory.
# Possible reasons:
# The system is out of physical RAM or swap space
# The process is running with CompressedOops enabled, and the Java Heap may be blocking the growth of the native heap
# Possible solutions:
# Reduce memory load on the system
# Increase physical memory or swap space
# Check if swap backing store is full
# Decrease Java heap size (-Xmx/-Xms)
# Decrease number of Java threads
# Decrease Java thread stack sizes (-Xss)
# Set larger code cache with -XX:ReservedCodeCacheSize=
# This output file may be truncated or incomplete.
#
# Out of Memory Error (os_linux.cpp:2718), pid=2363, tid=2364
#
# JRE version: (11.0.3+7) (build )
# Java VM: OpenJDK 64-Bit Server VM (11.0.3+7-LTS, mixed mode, aot, sharing, tiered, compressed oops, serial gc, linux-amd64)
# Core dump will be written. Default location: /var/jenkins_home/.gradle/daemon/5.6.2/core.2363
根據(jù)可能的原因進(jìn)行排查溯乒,首先執(zhí)行 free
,發(fā)現(xiàn) swap 大小為 0
total used free shared buff/cache available
Mem: 1014728 570788 216884 6372 227056 297800
swap: 0 0 0
6.1.1 Linux swap 交換分區(qū)的配置
6.1.1.1 swap 交換分區(qū)的作用
Linux swap 交換分區(qū)豹爹,即為虛擬內(nèi)存裆悄。當(dāng) Linux 系統(tǒng)的物理內(nèi)存不夠用的時(shí)候,就需要將物理內(nèi)存中的一部分空間釋放出來(lái)臂聋,以供當(dāng)前運(yùn)行的程序使用光稼。那些被釋放的空間可能來(lái)自一些很長(zhǎng)時(shí)間沒(méi)有什么操作的程序,這些被釋放的空間被臨時(shí)保存到 swap 空間中孩等,等到那些程序要運(yùn)行時(shí)艾君,再?gòu)?swap 中恢復(fù)保存的數(shù)據(jù)到內(nèi)存中。這樣肄方,系統(tǒng)總是在物理內(nèi)存不夠時(shí)冰垄,才進(jìn)行 swap 交換。避免應(yīng)用程序內(nèi)存不足錯(cuò)誤的最簡(jiǎn)單方法之一是為服務(wù)器添加一些 swap 空間权她。
注:雖然建議對(duì)使用傳統(tǒng)機(jī)械硬盤驅(qū)動(dòng)器的系統(tǒng)進(jìn)行交換虹茶,但對(duì)于 SSD 來(lái)說(shuō),使用 swap 可能會(huì)導(dǎo)致硬件隨著時(shí)間的推移而出現(xiàn)問(wèn)題隅要。出于這種考慮蝴罪,不建議在任何其他使用 SSD 存儲(chǔ)上啟用 swap。這樣做會(huì)影響底層硬件的可靠性步清。
6.1.1.2 查看信息
可執(zhí)行 swapon --show
要门,若沒(méi)有任何信息輸出,說(shuō)明沒(méi)有可用的 swap 空間廓啊。也可以使用 free
查看活動(dòng)的 swap
6.1.1.3 大小
一般來(lái)說(shuō)可以按照如下規(guī)則設(shè)置大谢端选:
- 4G 以內(nèi)的物理內(nèi)存,swap 設(shè)置為內(nèi)存的 2 倍谴轮。
- 4-8G 的物理內(nèi)存狂巢,swap 等于內(nèi)存大小。
- 8-64G 的物理內(nèi)存书聚,swap 設(shè)置為 8G唧领。
- 64-256G 物理內(nèi)存,swap 設(shè)置為 16G雌续。
實(shí)際上斩个,系統(tǒng)中交換分區(qū)的大小并不取決于物理內(nèi)存的量,而是取決于系統(tǒng)中內(nèi)存的負(fù)荷驯杜,所以在安裝系統(tǒng)時(shí)要根據(jù)具體的業(yè)務(wù)來(lái)設(shè)置 swap 的值受啥。
6.1.1.4 設(shè)置
系統(tǒng)并不是等所有的物理內(nèi)存都消耗完畢之后,才去使用 swap 的空間鸽心,什么時(shí)候使用是由 swappiness 參數(shù)值控制滚局。
cat /proc/sys/vm/swappiness
60
該值默認(rèn)值是 60
swappiness=0 的時(shí)候表示最大限度使用物理內(nèi)存,然后才是 swap 空間顽频,
swappiness = 100 的時(shí)候表示積極的使用 swap 分區(qū)藤肢,并且把內(nèi)存上的數(shù)據(jù)及時(shí)的搬運(yùn)到 swap 空間里面。
注:可以把這個(gè)參數(shù)值設(shè)置的低一些糯景,讓操作系統(tǒng)盡可能的使用物理內(nèi)存嘁圈,降低系統(tǒng)對(duì) swap 的使用,從而提高系統(tǒng)的性能蟀淮。與 swap 文件的交互是費(fèi)時(shí)的最住,因?yàn)樗鼈儽扰c RAM 的交互花費(fèi)更長(zhǎng)的時(shí)間,并且它們可能導(dǎo)致性能的顯著降低怠惶。
- 臨時(shí)性修改:
sysctl vm.swappiness=10
vm.swappiness = 10
cat /proc/sys/vm/swappiness
10
這里我們的修改已經(jīng)生效涨缚,但是如果我們重啟了系統(tǒng),又會(huì)變成 60.
- 永久修改:
在 /etc/sysctl.conf 文件里添加如下參數(shù):
vm.swappiness=10
然后重啟系統(tǒng)
6.1.1.5 配置
(1)查看目前磁盤使用情況策治,執(zhí)行 df -h
[root@54s9uer src]# df -h
文件系統(tǒng) 容量 已用 可用 已用% 掛載點(diǎn)
devtmpfs 486M 0 486M 0% /dev
tmpfs 496M 0 496M 0% /dev/shm
tmpfs 496M 57M 440M 12% /run
tmpfs 496M 0 496M 0% /sys/fs/cgroup
/dev/vda1 32G 7.8G 23G 26% /
tmpfs 100M 0 100M 0% /run/user/0
overlay 32G 7.8G 23G 26% /var/lib/docker/overlay2/c2b2dedef134be83b420347470f5bc0cf9ff0f/merged
overlay 32G 7.8G 23G 26% /var/lib/docker/overlay2/3bbd16437dc11ff7ed36ca4c6e60642ef8dbfa/merged
/dev/vda1 是實(shí)際使用的磁盤脓魏,swap 即可從這里設(shè)置容量
注:設(shè)置 swap 分區(qū)應(yīng)在宿主機(jī)進(jìn)行
注:通常,等于或雙倍于系統(tǒng)內(nèi)存的量是一個(gè)很好的選擇览妖。如果只是將其用作 RAM 后備轧拄,那么 swap 分區(qū)盡可能不要超過(guò) 4G。
(2)在根目錄創(chuàng)建 swap 文件
fallocate -l 1G /swapfile
(3)查看是否分配了正確的大小
[root@54s9uer src]# ls -lh /swapfile
-rw------- 1 root root 1.0G 4 月 11 23:32 /swapfile
(4)設(shè)置權(quán)限讽膏。執(zhí)行 chmod 600 /swapfile
(4)標(biāo)記 swap 分區(qū)檩电。執(zhí)行 mkswap /swapfile
(5)啟動(dòng) swap 分區(qū)。執(zhí)行 swapon /swapfile
注:執(zhí)行上述命令后可能出現(xiàn)以下提示府树,但是使用 swapon --show
或 free -m
命令俐末,可見(jiàn) swap 分區(qū)已經(jīng)配置成功:
swapon: /swapfile:swapon 失敗: 設(shè)備或資源忙
附加內(nèi)容:關(guān)閉 swap
swapoff /swapfile
6.1.1.6 保持配置
上述配置在服務(wù)器重新啟動(dòng)后,將不會(huì)自動(dòng)保留奄侠∽矿铮可將交換文件添加到 /etc/fstab 來(lái)進(jìn)行保留
(1)為了避免出現(xiàn)任何問(wèn)題,先備份 /etc/fstab 文件
cp /etc/fstab /etc/fstab.bak
(2)將下列 swap 文件信息添加到 /etc/fstab 文件末尾
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
6.2 自動(dòng)部署后端項(xiàng)目時(shí)的問(wèn)題
若將 runjdkapp.sh
代碼直接填入 Exec command
垄潮,會(huì)產(chǎn)生構(gòu)建成功后能夠運(yùn)行但無(wú)法自行退出烹卒,最終超時(shí)的問(wèn)題闷盔,jenkins 會(huì)判斷構(gòu)建失敗。部分相關(guān)日志如下:
ERROR: Exception when publishing, exception message [Exec timed out or was interrupted after 120,000 ms]
Build step 'Send build artifacts over SSH' changed build result to UNSTABLE
Finished: UNSTABLE
必須勾選 Exec in pty
復(fù)選框旅急,并將代碼形成 sh 文件后再添加一個(gè) nohup 才能夠正常構(gòu)建(參見(jiàn)前文步驟)逢勾。
有關(guān)討論可詳見(jiàn):
- https://blog.csdn.net/u013066244/article/details/52788407
- https://stackoverflow.com/questions/11290540/jenkins-text-finder-unable-to-success-my-build/22011893#22011893
進(jìn)行上述設(shè)置后,項(xiàng)目可正常構(gòu)建和部署藐吮,會(huì)出現(xiàn)以下信息:
nohup: ignoring input and appending output to 'nohup.out'
SSH: EXEC: completed after 200 ms
因此可在運(yùn)行項(xiàng)目之前使用 cat /dev/null > nohup.out
清空該文件
附加內(nèi)容:清空文件
- 方式一:
cat /dev/null > nohup.out
- 方式二:
echo "" > nohup.out
- 方式三:
> nohup.out