1.1 前言
Jenkins是一個用Java編寫的開源的持續集成工具。在與Oracle發生爭執后,項目從Hudson項目獨立。
Jenkins提供了軟件開發的持續集成服務。它運行在Servlet容器中(例如Apache Tomcat)。它支持軟件配置管理(SCM)工具(包括AccuRev SCM、CVS、Subversion、Git、Perforce、Clearcase和RTC),可以執行基於Apache Ant和Apache Maven的項目,以及任意的Shell腳本和Windows批處理命令。Jenkins的主要開發者是川口耕介。Jenkins是在MIT許可證下發布的自由軟件。
1.1.1 Jenkins功能
1、持續的軟件版本發布/測試項目。
2、監控外部調用執行的工作。
1.2 怎么理解持續集成、持續交付、持續部署呢?
1.2.1 持續集成
持續集成(英語:Continuous integration,縮寫為 CI),一種軟件工程流程,將所有工程師對於軟件的工作復本,每天集成數次到共用主線(mainline)上。
這個名稱最早由葛來迪·布區(Grady Booch)在他的布區方法中提出,但是他並沒有提到要每天集成數次。之后成為極限編程(extreme programming,縮寫為XP)的一部分。在測試驅動開發(TDD)的作法中,通常還會搭配自動單元測試。
持續集成的提出,主要是為了解決軟件進行系統集成時面臨的各項問題,極限編程稱這些問題為集成地獄(integration hell)。
持續集成主要是強調開發人員提交了新代碼之后,立刻進行構建、(單元)測試。根據測試結果,我們可以確定新代碼和原有代碼能否正確地集成在一起。簡單來講就是:頻繁地(一天多次)將代碼集成到主干。
持續集成目的在產生以下效益如:
ü 及早發現集成錯誤且由於修訂的內容較小所以易於追蹤,這可以節省項目的時間與成本。
ü 避免發布日期的前一分鍾發生混亂,當每個人都會嘗試為他們所造成的那一點點不兼容的版本做檢查。
ü 當單元測試失敗或發生錯誤,若開發人員需要在不除錯的情況下還原代碼庫到一個沒有問題的狀態,只需要放棄一小部分的更改 (因為集成的次數頻繁)。
ü 讓 "最新" 的程序可保持可用的狀態供測試、展示或發布用。
ü 頻繁的提交代碼會促使開發人員創建模塊化,低復雜性的代碼。
ü 防止分支大幅偏離主干。如果不是經常集成,主干又在不斷更新,會導致以后集成的難度變大,甚至難以集成。
1.2.2 持續交付
持續交付(英語:Continuous delivery,縮寫為 CD),是一種軟件工程手法,讓軟件產品的產出過程在一個短周期內完成,以保證軟件可以穩定、持續的保持在隨時可以釋出的狀況。
它的目標在於讓軟件的建置、測試與釋出變得更快以及更頻繁。這種方式可以減少軟件開發的成本與時間,減少風險。
持續交付在持續集成的基礎上,將集成后的代碼部署到更貼近真實運行環境的「類生產環境」(production-like environments)中。比如,我們完成單元測試后,可以把代碼部署到連接數據庫的 Staging 環境中更多的測試。如果代碼沒有問題,可以繼續手動部署到生產環境中。
1.2.3 持續部署
持續部署(英語:Continuous Deployment,縮寫為 CD),是持續交付的下一步,指的是代碼通過評審以后,自動部署到生產環境。
有時候,持續部署也與持續交付混淆。持續部署意味着所有的變更都會被自動部署到生產環境中。持續交付意味着所有的變更都可以被部署到生產環境中,但是出於業務考慮,可以選擇不部署。如果要實施持續部署,必須先實施持續交付。
持續部署即在持續交付的基礎上,把部署到生產環境的過程自動化。
關鍵字: CI/CD 持續集成/持續交付/持續部署
1.3 安裝配置JENKINS
了解網Jenkins后,現在進行Jenkins的安裝
1.3.1 環境說明
推薦的硬件配置
1 GB的RAM
50 GB的驅動器空間
系統環境
[root@Jenkins ~]# cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core) [root@Jenkins ~]# uname -r 3.10.0-693.el7.x86_64 [root@Jenkins ~]# getenforce Disabled [root@Jenkins ~]# systemctl status firewalld.service ● firewalld.service - firewalld - dynamic firewall daemon Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled) Active: inactive (dead) Docs: man:firewalld(1)
軟件要求
Java 8--無論是Java運行時環境(JRE)還是Java開發工具包(JDK)都可以。
# 可以使用open jdk [root@Jenkins ~]# yum -y install java-1.8.0-openjdk java-1.8.0-openjdk-devel [root@Jenkins ~]# java -version openjdk version "1.8.0_151" OpenJDK Runtime Environment (build 1.8.0_151-b12) OpenJDK 64-Bit Server VM (build 25.151-b12, mixed mode)
1.3.2 安裝Jenkins
軟件下載
官方倉庫 https://pkg.jenkins.io/redhat-stable/
清華大學開源軟件鏡像站 https://mirrors.tuna.tsinghua.edu.cn/jenkins/redhat/
下載相應的數據包即可,我這里使用的是jenkins-2.73.1-1.1.noarch.rpm
安裝jenkins
rpm -ivh jenkins-2.73.1-1.1.noarch.rpm
啟動jenkins
/etc/init.d/jenkins start
檢查端口信息
[root@Jenkins ~]# netstat -lntp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1213/sshd tcp6 0 0 :::8080 :::* LISTEN 1672/java tcp6 0 0 :::22 :::* LISTEN 1213/sshd
RPM包安裝的內容
[root@Jenkins ~]# rpm -ql jenkins /etc/init.d/jenkins # 啟動文件 /etc/logrotate.d/jenkins # 日志分割配置文件 /etc/sysconfig/jenkins # jenkins主配置文件 /usr/lib/jenkins # 存放war包目錄 /usr/lib/jenkins/jenkins.war # war 包 /usr/sbin/rcjenkins # 命令 /var/cache/jenkins # war包解壓目錄 jenkins網頁代碼目錄 /var/lib/jenkins # jenkins 工作目錄 /var/log/jenkins # 日志
配置文件說明
[root@Jenkins ~]# grep "^[a-Z]" /etc/sysconfig/jenkins JENKINS_HOME="/var/lib/jenkins" #jenkins工作目錄 JENKINS_JAVA_CMD="" JENKINS_USER="jenkins" # jenkinx啟動用戶 JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true" JENKINS_PORT="8080" # 端口 JENKINS_LISTEN_ADDRESS="" JENKINS_HTTPS_PORT="" JENKINS_HTTPS_KEYSTORE="" JENKINS_HTTPS_KEYSTORE_PASSWORD="" JENKINS_HTTPS_LISTEN_ADDRESS="" JENKINS_DEBUG_LEVEL="5" JENKINS_ENABLE_ACCESS_LOG="no" JENKINS_HANDLER_MAX="100" # 最大連接 JENKINS_HANDLER_IDLE="20" JENKINS_ARGS=""
1.3.3 web界面安裝
瀏覽器訪問: http://10.0.0.64:8080
解鎖Jenkins,密碼從命令行中獲取
[root@Jenkins ~]# cat /var/lib/jenkins/secrets/initialAdminPassword 3afe5ad49a794ac2b1a72811f5eb3c9b
輸入授權密碼,然后點擊下一步
稍等一會來導安裝插件選擇的頁面,將此頁面關閉,在安裝完成Jenkins后安裝插件。
關閉安裝插件選擇后,選擇開始使用Jenkins
安裝完成,顯示界面
安裝Jenkins插件
系統管理 >> 管理插件
選擇自己需要的插件進行安裝即可,也可選擇全部安裝。

1 [root@Jenkins ~]# # 插件安裝完成后插件安裝目錄的內容 2 [root@Jenkins ~]# ls /var/lib/jenkins/plugins/ 3 ace-editor credentials.jpi github-branch-source jquery-detached.jpi pam-auth pipeline-model-extensions.jpi ssh-credentials.jpi workflow-basic-steps.jpi 4 ace-editor.jpi display-url-api github-branch-source.jpi jsch pam-auth.jpi pipeline-rest-api ssh.jpi workflow-cps 5 ant display-url-api.jpi github.jpi jsch.jpi pipeline-build-step pipeline-rest-api.jpi ssh-slaves workflow-cps-global-lib 6 antisamy-markup-formatter docker-commons git.jpi junit pipeline-build-step.jpi pipeline-stage-step ssh-slaves.jpi workflow-cps-global-lib.jpi 7 antisamy-markup-formatter.jpi docker-commons.jpi gitlab-plugin junit.jpi pipeline-github-lib pipeline-stage-step.jpi structs workflow-cps.jpi 8 ant.jpi docker-workflow gitlab-plugin.jpi ldap pipeline-github-lib.jpi pipeline-stage-tags-metadata structs.jpi workflow-durable-task-step 9 authentication-tokens docker-workflow.jpi git-server ldap.jpi pipeline-graph-analysis pipeline-stage-tags-metadata.jpi subversion workflow-durable-task-step.jpi 10 authentication-tokens.jpi durable-task git-server.jpi mailer pipeline-graph-analysis.jpi pipeline-stage-view subversion.jpi workflow-job 11 bouncycastle-api durable-task.jpi gradle mailer.jpi pipeline-input-step pipeline-stage-view.jpi timestamper workflow-job.jpi 12 bouncycastle-api.jpi email-ext gradle.jpi mapdb-api pipeline-input-step.jpi plain-credentials timestamper.jpi workflow-multibranch 13 branch-api email-ext.jpi handlebars mapdb-api.jpi pipeline-milestone-step plain-credentials.jpi token-macro workflow-multibranch.jpi 14 branch-api.jpi external-monitor-job handlebars.jpi matrix-auth pipeline-milestone-step.jpi resource-disposer token-macro.jpi workflow-scm-step 15 build-timeout external-monitor-job.jpi icon-shim matrix-auth.jpi pipeline-model-api resource-disposer.jpi windows-slaves workflow-scm-step.jpi 16 build-timeout.jpi git icon-shim.jpi matrix-project pipeline-model-api.jpi scm-api windows-slaves.jpi workflow-step-api 17 cloudbees-folder git-client jackson2-api matrix-project.jpi pipeline-model-declarative-agent scm-api.jpi workflow-aggregator workflow-step-api.jpi 18 cloudbees-folder.jpi git-client.jpi jackson2-api.jpi maven-plugin pipeline-model-declarative-agent.jpi script-security workflow-aggregator.jpi workflow-support 19 credentials github javadoc maven-plugin.jpi pipeline-model-definition script-security.jpi workflow-api workflow-support.jpi 20 credentials-binding github-api javadoc.jpi momentjs pipeline-model-definition.jpi ssh workflow-api.jpi ws-cleanup 21 credentials-binding.jpi github-api.jpi jquery-detached momentjs.jpi pipeline-model-extensions ssh-credentials workflow-basic-steps ws-cleanup.jpi
至此Jenkins安裝完成
1.3.4 Jenkins配置
1. 配置jenkins並發執行數量,提高執行效率
系統管理 >> 系統設置 >> Maven項目配置
2. 設置郵件,能夠在測試完成后,主動發郵件告知測試情況
系統管理 >> 系統設置 >> Jenkins Location
向下拉,找到郵件通知,配置郵件的smtp信息
配置完成后點擊 Test configuration 進行測試,測試成功后,點擊保存
1.4 Jenkins使用
1.4.1 創建一個新的任務
創建一個新的任務
輸入項目的名稱,選擇構建只有分風格的軟件
1.4.2 將Jenkins與gitlab聯合
gitlab的詳細安裝方法參照: http://www.cnblogs.com/clsn/p/7929958.html
創建公鑰和私鑰
[root@Jenkins ~]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: SHA256:5SGYye8oxCKFJjddb4W8JC0RAQhBWCvuG8aZL8eMJs4 root@Jenkins The key's randomart image is: +---[RSA 2048]----+ |==....=* .. | |...o oo==. | |+.= . =++.o | |++ o o.+ . | |... o S . | |o.oo o | | B+ . . . | |++++ . | |+Eo. | +----[SHA256]-----+ [root@Jenkins ~]# cat .ssh/id_rsa.pub [root@Jenkins ~]# cat .ssh/id_rsa
在gitlab中添加公鑰id_rsa.pub
在jenkins中添加私鑰id_rsa
在首頁中,點擊項目名稱的下拉監聽
選擇源碼管理,先將gitlab的項目地址復制過來
選擇SSH密鑰和證書,然后選擇直接輸入,將私鑰復制到下框中即可
添加完成后,點擊保存
選擇剛才創建的證書,完成后,選擇構建
選擇構建
拉到最底部,選擇使用shell腳本
腳本內容
創建測試環境
[root@Jenkins ~]# mkdir -p /data/www [root@Jenkins ~]# chown -R jenkins.jenkins /data/
選擇構建后的操作,讓每次構建完成后都將結果發送給管理員
1.4.3 測試手動集成
回到主頁,點擊右側的按鈕進行測試
部署完成
查看部署日志
查看部署結果
[root@Jenkins ~]# ll /data/www/ 總用量 4 -rw-r--r-- 1 jenkins jenkins 4 11月 30 21:22 flag -rw-r--r-- 1 jenkins jenkins 0 11月 30 21:22 README.md
1.4.4 自動測試(gitlab主動通知Jenkins測試)
該功能會使用到一個插件 gitlab plugin
配置gitlab認證
添加一個新的憑證
從gitlab的設置中將 token復制過來
將復制的token粘貼到api token中,點ok
在系統配置中找到Gitlab 將信息進行填寫,Credentials 選擇剛剛創建對的即可
打開項目,編輯項目的構建觸發器
在gitlab上配置連接jenkins ,將Jenkins的Secret token 與Build URL 復制到gitlab中
保存之前先進程測試,測試成功后進行保存
在gitlab進行上傳文件,可以測試。
在日志中顯示是 Started by GitLab push by Administrator 即表示自動集成成功
1.5 代碼上線方案
1.5.1 早期手動部署代碼
純手動scp上傳代碼。
純手動登陸,Git pull 或者SVN update。
純手動xftp上傳代碼。
開發發送壓縮包,rz上傳,解壓部署代碼。
缺點:
全程運維參與,占用大量時間。
如果節點多,上線速度慢。
人為失誤多,目錄管理混亂。
回滾不及時,或者難以回退。
上線方案示意圖:
1.5.2 合理化上線方案
1、開發人員需在個人電腦搭建LAMP環境測試開發好的網站代碼,並且在辦公室或 IDC機房的測試環境測試通過,最好有專職測試人員。
2、程序代碼上線要規定時間,例如:三天上線一次,如網站需經常更新可每天下午 17點上線,這個看網站業務性質而定,原則就是影響用戶體驗最小。
3、代碼上線之前需備份,網站程序出了問題方便回退,另外,從上線技巧上講,上傳代碼時盡可能先傳到服務器網站臨時目錄,傳完整后一步mv過去,或者通過In做軟鏈接— 線上更新代碼的思路。如果嚴格更新,把應用服務器從集群節點平滑下線,然后更新。
4、盡量由運維人員管理上線,對於代碼的功能性,開發人員更在意,而對於代碼的性 能優化和上線后服務器的穩定,運維更在意服務器的穩定,因此,如果網站宕機問題歸運維管,就要讓運維上線,這樣更規范科學。否則,開發隨意更新,出了問題運維負責,這樣就錯了,運維永遠無法抬頭。
圖·web代碼規范化上線流程圖
1.5.3 大型企業上線制度和流程
JAVA代碼環境,上線時,有數台機器同時需要更新或者分批更新 ↓
1).本地開發人員取svn代碼。當天上線提交到trunk,否則,長期項目單開分支開發,然后在合並主線(trunk) 2).辦公內網開發測試時,由開發人員或配置管理員通過部署平台jenkins實現統一部署,(即在部署平台上控制開發機器從svn取代碼,編譯,打包,發布到開發機,包名如idc_dep.war). 3).開發人員通知或和測試人員一起測試程序,沒有問題后,由配置管理員打上新的tag標記。這里要注意,不同環境的配置文件是隨代碼同時發布的。 4).配置管理員,根據上一步的tag標記,checkout出上線代碼,並配置好IDC測試環境的所有配置,執行編譯,打包(mvn,ant)(php不需要打包),然后發布到IDC內的統一分發服務器。 5).配置管理員或SA上線人員,把分發的程序代碼內容推送到相關測試服務器(包名如idc_test.war),然后通知開發及測試人員進行測試。如果有問題向上回退,繼續修改。 6).如果IDC測試沒有問題,繼續打好tag標記,此時,配置管理員,根據上步的tag標記,checkout出測試好的代碼,並配置好IDC正式環境的所有配置,執行編譯,打包(mvn,ant)(php不需要打包),然后發布到IDC內的統一分發服務器主機,准備批量發布。 7).配置管理員或SA上線人員,把分發的內容推送到相關正式服務器(包名如idc_product.war),然后通知開發及測試人員進行測試。如果有問題直接發布回滾指令。
IDC正式上線的過程對於JAVA程序,可以是AB組分組上線的思路,即平滑下線一半的服務器,然后發布更新代碼,重啟測試,無問題后,掛上更新后的服務器,同時再平滑下線另一半的服務器,然后發布更新代碼測試(或者直接發布后,重啟,掛上線)
1.5.4 php程序代碼上線的具體方案
對於PHP上線方法:發布代碼時(也需要測試流程)可以直接發布到正式線臨時目錄 ,然后mv或更改link的方式發布到正式上線目錄 ,不需要重啟http服務。這是新朗,趕集的上線方案。
1.5.5 JAVA程序代碼上線的具體方案
對於java上線方法:較大公司需要分組平滑上線(如從負載均衡器上摘掉一半的服務器),發布代碼后,重啟服務器測試,沒問題后,掛上上好線的一半,再下另外一半。如果前端有DNS智能解析,上線還可以分地區上線若干服務器,逐漸普及到全國的服務器,這個被稱為“灰度發布”,在后面門戶網站上線的知識里我們在講解。
1.5.6 代碼上線解決方案注意事項
1).上線的流程里,辦公室測試環境-->IDC測試環境-->正式生產環境,所有環境中的所有軟件均應版本統一,其次盡量單一,否則將后患無窮,開發測試成功,IDC測試就可能有問題(如:操作系統,web服務器,jdk,php,tomcat,resin等版本) 2).開發團隊小組辦公內部測試環境測試(該測試環境屬於開發小組維護,或定時自動更新代碼),代碼有問題返回給某開發人員重新開發。 3).有專門的測試工程師,程序有問題直接返回給開發人員(此時返回的一般為程序的BUG,稱為BUG庫),無問題進行IDC測試 4).IDC測試由測試人員和運維人員參與,叫IDCtest,進行程序的壓力測試,有問題直接返回給開發人員,無問題進行線上環境上線。 5).數台服務器代碼分發上線方案舉例(JAVA程序) A:假設同業務服務器有6台,將服務器分為A,B兩組,A組三台,B組三台,先對A組進行從負載均衡器上平滑下線,B組正常提供服務,避免服務器因上線影響業務。 B:下線過程是通過腳本將A組服務器從RS池(LVS,NGINX,HAPROXY,F5等均有平滑方案)中踢出,避免負裁均衡器將請求發送給A組服務器(此時的時間應該為網站流量少時,一般為晚上) C:將代碼分發到A組服務器的站點目錄下,對A組服務器上線並重啟服務,並由專業的測試人員進行訪問測試,測試成功后,掛上A組的服務器,同時下線B組服務器,B組代碼上線操作測試等和A組相同,期間也要觀察上線提供服務的服務器狀況,有問題及時回滾。 6).特別說明:如果是PHP程序,則上線可以簡單化,直接將上線代碼(最好全量)發布到所有上線服務器的特定目錄后,分發完成后,一次性mv或ln到站點目錄,當然測試也是少不了的。測試除了人員測試外,還有各種測試腳本測試各個相關業務接口。 7).大多數門戶公司的前端頁面都已經靜態化或者cache了,因此,動態的部分訪問平時就不會特別多,流量低谷時就更少了。再加上是平滑上下線,因此基本上
1.6 參考文獻
1. https://zh.wikipedia.org/wiki/持續整合
2. https://www.zhihu.com/question/23444990/answer/89426003
3. https://www.mindtheproduct.com/2016/02/what-the-hell-are-ci-cd-and-devops-a-cheatsheet-for-the-rest-of-us/
4. http://t.cn/RYKgMtc 自動化部署
5. http://www.cnblogs.com/can-H/articles/7346724.html
6. https://www.abcdocker.com/abcdocker/2041