華為軟件開發(fā)云:讓軟件研發(fā)變成快樂的事
1173
2022-05-30
前言
本文為《用開源軟件打造企業(yè)級 DevOps 工作流》系列的第三篇文章。接著上一篇版本控制系統(tǒng)篇,本篇文章主要講介紹 DevOps 工作流中另一個(gè)核心模塊 持續(xù)集成(CI),這可以說是 DevOps 中的重中之重,因?yàn)檫@涉及到自動化管理項(xiàng)目的部署過程。有了持續(xù)集成,我們就可以從手動部署中解脫出來,把時(shí)間用在更重要的事情上,例如代碼重構(gòu)、回歸測試、架構(gòu)設(shè)計(jì)等等。
在本篇文章中,我們將介紹持續(xù)集成的基本概念,為什么用持續(xù)集成,以及如何利用開源軟件 Jenkins 來實(shí)現(xiàn)持續(xù)集成。
持續(xù)集成簡介
本系列文章的第一篇概述中我們提到,持續(xù)集成可以類比于工廠中的流水線操作。例如生產(chǎn)一輛汽車,一切從裸車架開始,車架用吊鉤送上傳送帶,經(jīng)過裝配、打磨、測試等一系列復(fù)雜而緊湊的統(tǒng)一化流程,最終產(chǎn)出一輛功能齊全、質(zhì)量卓越的完整汽車。
持續(xù)集成類似軟件開發(fā)中的流水線,只是持續(xù)集成中的流水線通常來說是自動化的,也就是說不需要任何人為干預(yù),一個(gè)軟件程序就可以從源碼開始,經(jīng)過一系列的構(gòu)建步驟,最終形成成熟的產(chǎn)品。什么時(shí)候啟動這個(gè)流水線呢?一般來說,是代碼變更的時(shí)候。其實(shí),這里所說的流水線還包括了部署的過程,一般說持續(xù)集成通常會提到 持續(xù)部署(CD)。嚴(yán)格意義上來說這是兩個(gè)概念:持續(xù)集成(CI)是指不斷將代碼不斷同步到主干,持續(xù)部署是指代碼經(jīng)過評審后自動部署到生產(chǎn)環(huán)境。為了方便起見,我們將這兩個(gè)概念合二為一,統(tǒng)稱為 CI/CD 。
例如上圖這個(gè)持續(xù)集成流水線,當(dāng)持續(xù)集成工具檢測到源代碼有變更的時(shí)候,會啟動這個(gè)流水線:
首先獲取源代碼;
并行構(gòu)建前后端應(yīng)用;
構(gòu)建 Docker 鏡像;
單元測試;
完成部署。
經(jīng)歷了這幾個(gè)步驟之后,一次集成過程就算完成了。整個(gè)流程不需要人為干預(yù),唯一需要開發(fā)者做的,就是提交一次代碼更新代碼倉庫,持續(xù)集成工具會自動將后面的事情(包括部署)一步步幫你做完,全程自動化。
為什么用 CI/CD
其實(shí)我們可以不用 CI/CD 來完成從編碼到部署的過程。那么,為什么我們要用 CI/CD 呢?首先我們看看下面一個(gè)流程圖。
這是一個(gè)從碼代碼到最終部署交付的流程例子:我們花數(shù)小時(shí)碼代碼(Coding),不到 1 分鐘提交代碼(Commit),然后構(gòu)建(Build)這個(gè)應(yīng)用花 1 分鐘到 1 小時(shí)(根據(jù)應(yīng)用復(fù)雜程度),接著花數(shù)分鐘部署(Deploy)這個(gè)應(yīng)用,最后測試(Test)。除開代碼和提交的時(shí)間,后面的構(gòu)建+部署時(shí)間最少也得花幾分鐘,而測試可能會花更久。
我們要知道的是,構(gòu)建和部署一般來說是重復(fù)性的工作,例如運(yùn)行一次 npm run build:prod 打包前端代碼,或者將打包好后的前端靜態(tài)文件拷貝到目標(biāo)地址。如果是人來操作這些流程,非常浪費(fèi)時(shí)間和精力。雖然構(gòu)建部署一次可能花不了多少時(shí)間,但考慮到企業(yè)中通常是多人協(xié)同工作,每個(gè)人都會提交代碼,而且很可能是多次提交,這樣需要執(zhí)行的次數(shù)就是遠(yuǎn)不止一次或幾次了。你簡單做一做乘法,就知道會有多少人工時(shí)間成本會花費(fèi)在上面,而人工成本目前來說是越來越貴的。因此,使用持續(xù)集成將降低時(shí)間成本(Time Expense)。
上面這個(gè)流程圖中紅色部分(編碼和提交)是無法自動化的,需要人工操作;而綠色部分(構(gòu)建和部署)是可以自動化的,也是需要盡可能全部自動化的;黃色部分(測試)是半人工半自動化的,因?yàn)槲覀兛梢酝ㄟ^ 單元測試(Unit Test) 來自動化很多測試工作,但一些復(fù)雜的測試用例(例如頁面的排版是否符合設(shè)計(jì)預(yù)期)則需要人工來完成,因此測試部分是半自動化的。這里多提一下單元測試,固然單元測試是非常有助于提升代碼的工程質(zhì)量,但是編寫單元測試卻相當(dāng)耗費(fèi)時(shí)間,差不多跟寫功能的時(shí)間差不多,因此會將整個(gè)項(xiàng)目時(shí)間加倍,所以需要在時(shí)間與質(zhì)量之間權(quán)衡是否需要采用單元測試。
開源工具 Jenkins
要實(shí)現(xiàn) CI/CD,我們需要一些工具。我們推薦的工具是 Jenkins,這也是企業(yè)環(huán)境中用的比較多的持續(xù)集成開源軟件。下面我們將詳細(xì)介紹一下 Jenkins,包括基本介紹、安裝、基本使用以及如何實(shí)踐應(yīng)用到 DevOps 工作流中。
可能你對 Jenkins 本身并不陌生,這是因?yàn)?Jenkins 從 2011 年開始就已經(jīng)存在,是最早的也是最常用的選擇。它出自 Sun 公司的一個(gè)工程師的業(yè)余項(xiàng)目,不斷改進(jìn)優(yōu)化后逐漸壯大成為最熱門的持續(xù)集成工具(聽起來是不是跟 JavaScript 的經(jīng)歷差不多?)。
關(guān)于 Jenkins 的介紹,我們主要引用其官網(wǎng)上的描述。以下是官方的關(guān)于 Jenkins 的一句話描述:
Jenkins是開源CI&CD軟件領(lǐng)導(dǎo)者, 提供超過1000個(gè)插件來支持構(gòu)建、部署、自動化, 滿足任何項(xiàng)目的需要。
其中,CI 指代持續(xù)集成,CD 指代持續(xù)交付。
以下是其主要特點(diǎn):
持續(xù)集成和持續(xù)交付: 作為一個(gè)可擴(kuò)展的自動化服務(wù)器,Jenkins 可以用作簡單的 CI 服務(wù)器,或者變成任何項(xiàng)目的持續(xù)交付中心;
簡易安裝: Jenkins 是一個(gè)基于 Java 的獨(dú)立程序,可以立即運(yùn)行,包含 Windows、Mac OS X 和其他類 Unix 操作系統(tǒng);
配置簡單: Jenkins 可以通過其網(wǎng)頁界面輕松設(shè)置和配置,其中包括即時(shí)錯誤檢查和內(nèi)置幫助;
插件: 通過更新中心中的 1000 多個(gè)插件,Jenkins 集成了持續(xù)集成和持續(xù)交付工具鏈中幾乎所有的工具;
擴(kuò)展: Jenkins 可以通過其插件架構(gòu)進(jìn)行擴(kuò)展,從而為 Jenkins 可以做的事提供幾乎無限的可能性;
分布式: Jenkins 可以輕松地在多臺機(jī)器上分配工作,幫助更快速地跨多個(gè)平臺推動構(gòu)建、測試和部署。
從介紹總結(jié)來看,Jenkins 的核心功能是持續(xù)集成和持續(xù)交付,另外還有便捷性(安裝簡單)和擴(kuò)展性(插件、分布式)。
跟之前的文章里安裝 GitLab 一樣,我們同樣是用 Docker 來安裝 Jenkins。在確保您已安裝 Docker 、并且能順利運(yùn)行 docker ps 的前提下,執(zhí)行以下命令。
docker?run
-u?root?\??#?以root用戶運(yùn)行
--restart?always?\??#?永遠(yuǎn)設(shè)置為重啟狀態(tài),開機(jī)時(shí)也會啟動
-d?\??#?daemon方式后臺運(yùn)行
-p?8080:8080?-p?50000:50000?\??#?將web端口映射出來,8080為web界面端口
--name?jenkins?\??#?容器名稱
-v?jenkins-data:/var/jenkins_home?\??#?持久化數(shù)據(jù)
-v?/var/run/docker.sock:/var/run/docker.sock?\??#?Docker守護(hù)進(jìn)程默認(rèn)監(jiān)聽的Unix域套接字
-e?JAVA_OPTS=-Duser.timezone=Asia/Shanghai?\??#?調(diào)整時(shí)區(qū)為中國時(shí)區(qū)
jenkinsci/blueocean??#?Jenkins鏡像
以上命令已經(jīng)有注釋了,讀者可以根據(jù)需要更改其中的一些配置,例如映射端口,8080 可以是 9090、80 等等。執(zhí)行上述命令后,Jenkins 需要一定初始化時(shí)間,等待片刻后在瀏覽器中輸入 http://<宿主機(jī)ip>:8080,就可以看到 Jenkins 的初始界面(如下圖),這是 Jenkins 在加載必要數(shù)據(jù)和第三方庫,大概需要幾分鐘。
初始化完畢后,瀏覽器會重新加載,我們會看到如下配置界面。
這個(gè)是告知您,需要輸入初始密碼,而這個(gè)密碼在 Jenkins 容器里的 /var/jenkins_home/secrets/initialAdminPassword 文件里。輸入以下命令來查看初始密碼。
docker?exec?-it?jenkins?bash??#?進(jìn)入容器命令行
cat?/var/jenkins_home/secrets/initialAdminPassword??#?查看初始密碼
將查看到的初始密碼輸入到上述界面中,點(diǎn)擊 Continue 進(jìn)入下一步。加載片刻后,您將看到如下選擇界面。
選擇默認(rèn)的 Install suggested plugins 安裝建議的插件。然后 Jenkins 會安裝一些常用的插件,例如連接 Git 的 Git plugin 、郵件插件、管道插件等等。安裝進(jìn)度如下圖。請耐心等待,這個(gè)過程可能花很長的時(shí)間!
安裝完畢后,輸入第一個(gè)管理員賬戶,點(diǎn)擊 Save and Continue 進(jìn)入到下一步,然后點(diǎn)擊 Save and Finish,最后選擇 Restart,完成重啟。
重啟完畢后,您就可以注冊登陸了,請選擇剛才的管理員賬戶登陸。
你可能最開始使用 Jenkins 的時(shí)候會發(fā)現(xiàn)它樸素的用戶界面一點(diǎn)也不酷炫,總體顯得比較老舊,不像是現(xiàn)代軟件的風(fēng)格,不過我們有 Open Blue Ocean 加強(qiáng)版界面,非常扁平化和現(xiàn)代化,不習(xí)慣 Jenkins 默認(rèn)界面的可以切換過去。下圖是進(jìn)入 Jenkins 的主頁界面,可以看到左側(cè)有一些操作選項(xiàng)以及構(gòu)建隊(duì)列和執(zhí)行器狀態(tài),右側(cè)是自動化項(xiàng)目的列表。
下圖是 Open Blue Ocean 的主頁界面,功能上跟默認(rèn)界面差不多,只是排版和風(fēng)格有所不同。
其實(shí),界面這些都不是特別重要的問題,很快你會被它樸實(shí)但強(qiáng)大的核心功能(持續(xù)集成)所折服。在使用這些強(qiáng)大的功能之前,我們需要做一些配置。
這里簡單介紹一下 Jenkins 的原理,Jenkins 構(gòu)建項(xiàng)目是通過 Jenkins Executor 這個(gè) jar 包來實(shí)現(xiàn)構(gòu)建和部署的。Jenkins 服務(wù)的本地機(jī)器叫做 主機(jī)(master) ,如果告訴主機(jī)其他機(jī)器的 IP 地址和登陸信息,Jenkins 就可以通過 SSH 的方式在該機(jī)器上將 Jenkins Executor 拷貝過去并運(yùn)行,再而與其交互通信,通過 Jenkins Executor 完成遠(yuǎn)程構(gòu)建工作。
下面我們介紹如何配置節(jié)點(diǎn)。
在主頁中點(diǎn)擊 Manage Jenkins (確保您有管理員權(quán)限),進(jìn)入管理頁面;
然后點(diǎn)擊 Manage Nodes ,進(jìn)入到管理節(jié)點(diǎn)頁面;
這里您應(yīng)該能看到 master 節(jié)點(diǎn),這時(shí)候你需要添加節(jié)點(diǎn),點(diǎn)擊左側(cè)的 New Node;
輸入節(jié)點(diǎn)名稱(Node Name),點(diǎn)擊 OK,將看到很多配置信息;
完成配置(配置信息如下圖),點(diǎn)擊 Save 保存設(shè)置。
然后,您應(yīng)該就可以看到下圖節(jié)點(diǎn)列表了,左側(cè) S 列代表的是節(jié)點(diǎn)狀態(tài)(Status),如果節(jié)點(diǎn)在線,會顯示為計(jì)算機(jī)的符號,如果離線,則會顯示一個(gè)計(jì)算機(jī)加紅叉的符號。你可以點(diǎn)擊去看它的日志(Log),如果一直連不上,需要查看日志排查錯誤。
節(jié)點(diǎn)配置好了,您就可以在這些節(jié)點(diǎn)上運(yùn)行構(gòu)建程序了。如果您有多個(gè)機(jī)器需要部署,只要一次性手動將這些信息注冊進(jìn) Jenkins,就可以一勞永逸的在各臺機(jī)器自動化部署應(yīng)用程序了。是不是很酷?
現(xiàn)在,我們介紹在 Jenkins 中如何創(chuàng)建一個(gè)自動化項(xiàng)目。其實(shí)過程很簡單,只是配置方面稍微復(fù)雜一些。
在主頁點(diǎn)擊 New Item 創(chuàng)建新項(xiàng)目;
輸入項(xiàng)目名稱,然后選擇項(xiàng)目類別,強(qiáng)烈建議選擇 Multibranch Pipeline (多分支管道),因?yàn)檫@一個(gè)類別是最方便配置和最容易集成之前介紹的 GitLab 版本控制系統(tǒng)的類別,然后點(diǎn)擊 OK;
配置各種輸入,包括展示名稱、項(xiàng)目來源(來自VCS,例如Git/SVN)、構(gòu)建周期(選擇每分鐘)等等。
點(diǎn)擊 Save 保存項(xiàng)目,就創(chuàng)建好了一個(gè)項(xiàng)目。
讀者可能會問:等等,構(gòu)建過程跑哪兒去了?別著急,我們接下來會將如何配置構(gòu)建過程,也就是用一個(gè)配置文件來定義構(gòu)建過程,而這個(gè)配置文件叫 Jenkinsfile。
讀者可能會問,Jenkinsfile 是不是與 Dockerfile 有異曲同工之妙?沒錯!這兩種配置文件都屬于 Infrastructure as Code(架構(gòu)即代碼) ,僅僅用代碼就可以配置出計(jì)算機(jī)和網(wǎng)絡(luò)架構(gòu),非常易于管理和擴(kuò)展。下面我們會詳細(xì)介紹 Jenkinsfile。
Jenkinsfile 是 Jenkins 2 發(fā)布的一個(gè)實(shí)用功能,這個(gè)功能讓用代碼管理構(gòu)建過程變成可能。它使用 Groovy 語法,很容易配置不同的構(gòu)建階段。下面是一個(gè) Jenkinsfile 的例子。
pipeline?{
agent?{
node?{
label?'docker'??//?要執(zhí)行的節(jié)點(diǎn)名稱
}
}
stages?{
//?配置階段
stage('Configure')?{
steps?{
echo?'Configuring'
script?{
//?根據(jù)?Git?分值名稱選擇不同的?docker-compose?文件
switch?(env.GIT_BRANCH)?{
case?'develop':
//?開發(fā)分支的?docker-compose?文件
env.DOCKER_COMPOSE_FILENAME?=?'docker-compose-dev.yaml'
break
case?'master':
//?主干的?docker-compose?文件
env.DOCKER_COMPOSE_FILENAME?=?'docker-compose-prod.yaml'
break
default:
echo?"Unknown?branch?${env.GIT_BRANCH}"
exit?1
}
}
}
}
//?構(gòu)建階段
stage('Build')?{
steps?{
echo?'Building'
//?用?Docker?不同分支的構(gòu)建鏡像(用?GIT_BRANCH?環(huán)境變量區(qū)分)
sh?"""
docker?build?-t?awesome-image:${ENV:GIT_BRANCH}?-f?Dockerfile-local?.
"""
}
}
//?測試階段
stage('Test')?{
steps?{
echo?'Testing'
}
}
//?部署階段
stage('Deploy')?{
steps?{
//?用?docker-compose?重啟鏡像服務(wù)
sh?"""
docker-compose?-f?${ENV:DOCKER_COMPOSE_FILENAME}?down?|?true
docker-compose?-f?${ENV:DOCKER_COMPOSE_FILENAME}?up?-d
"""
}
}
//?清理階段
stage?('Clean-up')
{
steps
{
//?清理不用的?Docker?鏡像
sh?'''
docker?rmi?$(docker?images?-f?"dangling=true"?-q)?||?true
'''
}
}
}
}
這里,我們用了 Docker 來完成構(gòu)建工作,Docker Compose 來完成部署工作。后面的文章會詳細(xì)介紹 Docker 在 DevOps 中的應(yīng)用。
關(guān)于 Jenkinsfile 的內(nèi)容以及 API 還很多,本文不會全部涵蓋。需要的朋友可以參考官方文檔 https://jenkins.io/zh/doc/book/pipeline/jenkinsfile/。
配置好了 Jenkinsfile,將它放在 Git 項(xiàng)目根目錄下,當(dāng)每次有代碼提交的時(shí)候,Jenkins 就會拉最新代碼,然后開始構(gòu)建過程,如下圖。
用 Pipeline 構(gòu)建的好處在于可以直觀的看到構(gòu)建的過程,包括各階段花了多少時(shí)間等信息。下圖是某個(gè)項(xiàng)目構(gòu)建過程的概覽??梢钥吹?,每一次構(gòu)建都是由 VCS 代碼提交觸發(fā)的。這樣的話,只要我們在某個(gè)分支上提交了代碼,Jenkins 就可以自動幫我們構(gòu)建、部署了。如果構(gòu)建過程中有報(bào)錯,Jenkins 中會有提示信息。
Jenkins 與其他 CI/CD 工具
Jenkins 是一個(gè)強(qiáng)大的工具,不過市面上還有其他很多優(yōu)秀的 CI/CD 工具。如下圖,我們可以看到整個(gè) CI/CD 市場的市場份額。
為什么 Jenkins 這么出名,是因?yàn)樗亲钤绲拈_源 CI/CD 工具,存在市場比較久而已,讀者有權(quán)利選擇任何合適的工具。
下圖是各個(gè) CI/CD 工具的市場競爭矩陣圖。
總結(jié)
本文介紹了持續(xù)集成的基本概念,以及使用 CI/CD 的原因,此外還詳細(xì)介紹了開源 CI/CD 工具 Jenkins,包括 Jenkins 的簡單介紹、如何安裝、如何配置、創(chuàng)建項(xiàng)目以及如何使用 Jenkinsfile 和查看構(gòu)建進(jìn)度。相信仔細(xì)閱讀了本篇文章的讀者,應(yīng)該會基本了解持續(xù)集成的概念和框架,以及在企業(yè)中推廣使用持續(xù)集成的重要性。此外我們還了解了 CI/CD 工具的市場情況,并知道 Jenkins 并不是唯一的選擇,市面上還可以選擇很多其他優(yōu)秀的工具,例如后起之秀 Circle CI。我們選合適的 CI/CD 工具是為了滿足企業(yè)的 DevOps 需求,而不應(yīng)該局限于工具的名聲和自己所掌握的知識,只要做好了前期調(diào)研和需求分析,我相信是可以實(shí)踐好 DevOps 中的持續(xù)集成功能的。最后提一點(diǎn),就是工具并不是全部,如果沒有良好定義的流程與技能儲備,DevOps 是實(shí)踐不通的,應(yīng)用再優(yōu)秀的 CI/CD 工具也會失去意義。因此,我們需要經(jīng)常充實(shí)自己,加強(qiáng) DevOps 的知識了解,擴(kuò)充自己的能力范圍,這樣才能打造出最佳的 DevOps 工作流。
我們之前介紹了 DevOps 概述、VCS,現(xiàn)在又介紹 CI/CD,接下來我們會講容器化,會詳細(xì)介紹 Docker,敬請期待后續(xù)文章。
DevOps Jenkins
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。