說到CI(持續(xù)集成)也許你腦子里馬上會蹦出一個著名的CI工具,就是我們本篇實(shí)踐記錄中的jenkins眠砾。 沒錯校焦,jenkins能夠幫助我們更容易的做到持續(xù)集成,但是也需要你不斷的提交代碼到主干全谤,從而實(shí)現(xiàn)持續(xù)集成的目的。我經(jīng)常在項目團(tuán)隊協(xié)作中提醒同事需要頻繁的拉取與提交代碼爷贫,但大部分人總習(xí)慣了每日一更认然,甚至幾天一更补憾,這是違背了我們持續(xù)集成的目的,提高了代碼沖突的風(fēng)險卷员。
關(guān)于jenkins的安裝方式可以多樣化盈匾,常見于宿主機(jī)直接war包安裝,這是比較簡單的做法毕骡,但同時依賴于在宿主機(jī)先安裝好JAVA環(huán)境削饵。還有就是通過docker容器化的方式來安裝,也是本篇即將采用的方式未巫。
一窿撬、 部署Jenkins服務(wù)
我們通過 Rancher 部署服務(wù)來完成jenkins的安裝。首先下載鏡像叙凡,當(dāng)然劈伴,從rancher的部署頁中啟動可以自動為我們下載部署的鏡像,但我們這里為了更清晰的使用握爷,采用了手動pull鏡像的方式跛璧,執(zhí)行如下命令:
$ docker pull jenkins/jenkins:alpine
同樣我們可以通過docker inspect 命令查看鏡像的詳細(xì)信息,如下:
$ docker inspect jenkins/jenkins:alpine
當(dāng)然如果你有鏡像提供者的Dockerfile那就更好了新啼,通常公開的常用鏡像都可以在GitHub上找到追城,就比如我們現(xiàn)在使用的jenkins,它的Dockerfile地址是: https://github.com/jenkinsci/docker/blob/master/Dockerfile-alpine
有了Dockerfile燥撞,你可以更為清楚的了解這個鏡像的制作過程座柱,方便后面的使用。
接下來叨吮,在宿主機(jī)創(chuàng)建掛載文件夾
$ mkdir -p /docker_volume/jenkins_home
因為 jenkins user - uid 1000辆布,所以這里我們更改目錄用戶組及用戶(更詳細(xì)的可見:https://github.com/jenkinsci/docker/blob/master/README.md#usage)
$ chown -R 1000:1000 /docker_volume/jenkins_home
在rancher的部署頁中做如下操作:
- 輸入名稱 jenkins瞬矩。
- 輸入鏡像名稱jenkins/jenkins:alpine茶鉴。
- 添加端口映射 30000:8080,30001:50000景用。
- 添加一個路徑映射卷涵叮,卷名為jenkins-home,主機(jī)路徑的話就是填入我們先前創(chuàng)建的/docker_volume/jenkins_home目錄路徑伞插,選擇為現(xiàn)有目錄并映射到容器路徑/var/jenkins_home目錄路徑割粮。
- 點(diǎn)擊啟動按鈕。
這幾個步驟其實(shí)反應(yīng)到我們docker容器中就如同下面的命令:
$ docker run -d --restart unless-stopped --name jenkins \
-p 30000:8080 -p 30001:50000 \
-v /docker_volume/jenkins_home:/var/jenkins_home \
jenkins/jenkins:alpine
點(diǎn)擊啟動后媚污,會跳轉(zhuǎn)到如下界面:
直到等到服務(wù)狀態(tài)為Active后說明服務(wù)部署成功舀瓢,你可以點(diǎn)擊如下圖中標(biāo)紅的連接,即:http://192.168.225.129:30000耗美,就是我們先前對8080映射到了主機(jī)30000端口京髓。
二航缀、 初始化Jenkins
當(dāng)jenkns服務(wù)部署成功后,我們需要對jenkins進(jìn)行簡單配置后才能使用堰怨。點(diǎn)擊上面jenkins的訪問地址 http://192.168.225.129:30000 后芥玉,就來到了jenkins的web頁面,如下:
在頁面中輸入jenkins的初始密碼备图,值得一提的是灿巧,頁面中提示給我們的密碼位置是jenkins容器內(nèi)部的目錄地址,因為我們在上一節(jié)中部署jenkins服務(wù)時揽涮,在數(shù)據(jù)卷選項欄中采用了主機(jī)目錄映射到容器內(nèi)目錄抠藕,所以其實(shí)應(yīng)該到我們的主機(jī)映射目錄去查看,如果你是和我先前部署jenkins服務(wù)時輸入一樣的值話蒋困,那么執(zhí)行如下命令得到密碼:
$ cat /docker_volume/jenkins_home/secrets/initialAdminPassword
當(dāng)然你也可以在rancher中工作負(fù)載里操作執(zhí)行命令行
在這個里面操作命令就是基于容器內(nèi)部文件路徑了幢痘,你就可以使用/var/jenkins_home目錄,使用和上面相同的方式得到j(luò)enkins初始密碼家破。 實(shí)際上你可以發(fā)現(xiàn)颜说,點(diǎn)擊[執(zhí)行命令行]這個操作跟 docker exec命令進(jìn)入容器內(nèi)部實(shí)現(xiàn)了幾乎相同的功能,這也體現(xiàn)出我們在實(shí)際使用中更好的去理解rancher作為一款產(chǎn)品其背后的運(yùn)作原理(當(dāng)然汰聋,不可能這么簡單)门粪。
我們把密碼填入頁面后點(diǎn)擊下一步按鈕,進(jìn)入如下頁面:
選擇按照系統(tǒng)建議的插件烹困,一直等到插件安裝完成玄妈,這可能需要幾分鐘時間,這兒比較關(guān)注一下這幾款插件:Git髓梅、Gradle拟蜻、Ant,非常遺憾默認(rèn)的插件里沒有我們用到的maven枯饿,后面需要自己配置插件酝锅,從這里我們也要思考一下以后在做項目中,能夠考慮用Gradle來替代maven奢方,這也許是一個流行趨勢
完成后會跳轉(zhuǎn)到引導(dǎo)頁面搔扁,輸入我們管理員用戶名及密碼,然后下一步即可:
到此為止蟋字,我們已經(jīng)完成了jenkins的初始化稿蹲,實(shí)際使用中,還需要進(jìn)行更多的配置鹊奖,比如管理用戶苛聘、憑據(jù)配置、全局工具配置以及插件管理等,這些都可以在主面板的左側(cè)菜單欄中的系統(tǒng)管理中找到设哗,當(dāng)然璧尸,你也許已經(jīng)對jenkins的使用非常熟悉了。
三熬拒、 安裝maven
由于我們的宿主機(jī)中是沒有直接安裝maven軟件的爷光,我們可以在全局工具配置中安裝maven, 選擇一個合適的版本澎粟,勾選自動安裝蛀序,之后直接保存,需注意的是活烙,現(xiàn)在jenkins并不會立即給你安裝maven軟件
接下來我們在插件管理中查找maven插件徐裸,你可以在瀏覽器中使用ctrl+f快捷鍵來快速定位插件,如下圖所示啸盏,我們選擇好maven integration插件重贺,然后點(diǎn)擊直接安裝
稍作等待,到插件安裝完成后即可使用插件
四回懦、 創(chuàng)建一個新任務(wù)
現(xiàn)在我們來創(chuàng)建一個新任務(wù)气笙,輸入任務(wù)的名稱(通常是項目名),因為我們的項目是一個maven項目怯晕,所以我們需要選擇構(gòu)建一個maven項目潜圃,利用maven來編譯打包我們的源代碼,如下圖所示:
在源碼管理中輸入項目git倉庫地址舟茶,這兒使用的我在GitHub上的基于springBoot編寫的一個RESTFul API示例公開項目谭期,你可以不添加任何憑證即可使用。
示例項目GitHub地址:https://github.com/wendell-dev/restful-api-demo吧凉,歡迎大家star
接著在Build里填寫Root POM與Goals and options隧出,你可以點(diǎn)擊輸入框右邊的問號圖標(biāo)來獲得輸入幫助,這里分別填入pom.xml與clean package -DskipTests=true阀捅,點(diǎn)擊保存
點(diǎn)擊保存后將會跳轉(zhuǎn)到如下界面中胀瞪,可以選擇控制臺輸出來查看本次構(gòu)建信息
我們可以詳細(xì)的分析一下控制臺的輸出日志,可以看見這里為我們安裝了maven軟件也搓,還記得前面我們安裝maven時所說嗎赏廓,當(dāng)時并沒有立即為我們安裝maven涵紊“剩回到現(xiàn)在控制臺中,可以看見在本次構(gòu)建中為我們安裝了maven軟件在/var/jenkins_home/tools目錄下摸柄,你可能從文件夾路徑已經(jīng)看出颤练,這個跟路徑在我們部署jenkins時已經(jīng)進(jìn)行了主機(jī)路徑映射,相當(dāng)于已經(jīng)進(jìn)行了持久化驱负,好處不言而喻! 然后執(zhí)行了代碼從Git倉庫克隆到j(luò)enkins工作空間中嗦玖,并且執(zhí)行了我們先前配置的clean package -DskipTests=true命令:
最后患雇,很遺憾的告訴你,本次構(gòu)建失敗了宇挫,因為網(wǎng)絡(luò)或其它原因造成最終未能成功構(gòu)建項目苛吱,我們將通過配置maven來解決這個問題
五、 配置maven
在宿主機(jī)執(zhí)行如下命令進(jìn)入jenkins-in-maven目錄(先前安裝的默認(rèn)目錄) 并通過ls查看目錄下清單列表
$ cd /docker_volume/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/jenkins-in-maven
熟悉maven軟件目錄結(jié)構(gòu)的應(yīng)該可以看出來器瘪,這其實(shí)就是一個maven軟件的安裝后目錄翠储,那么接下來我們肯定就是對maven進(jìn)行配置,如指定Repository目錄和mirror等配置橡疼。
編輯配置文件
$ sudo vi conf/settings.xml
在相應(yīng)位置加入如下配置援所,并保存退出vi模式
<localRepository>
/var/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/jenkins-in-maven/repository
</localRepository>
與
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
接著重新構(gòu)建一下我們上一節(jié)中創(chuàng)建的項目,可以看見本次構(gòu)建成功了欣除,從日志中很明顯看出我們的jar包都是從http://maven.aliyun.com倉庫中拉取了住拭,說明我們的配置生效,而且先前構(gòu)建不成功很大原因就是因為沒有配置鏡像倉庫導(dǎo)致的網(wǎng)絡(luò)問題
六历帚、 運(yùn)行maven項目
6.1 傳統(tǒng)方式運(yùn)行
如果按照傳統(tǒng)做法的話滔岳,可能會直接在構(gòu)建成功后執(zhí)行 java –jar命令啟動程序,如下面這樣的寫法:
#!/bin/bash
pid=`ps -ef | grep restful-api-demo-0.0.1-SNAPSHOT.jar | grep -v grep | awk '{print $2}'`
if [ -n "$pid" ]
then
kill -9 $pid
fi
cp $WORKSPACE/target/restful-api-demo-0.0.1-SNAPSHOT.jar /home/restful-api-demo-0.0.1-SNAPSHOT.jar
BUILD_ID=dontKillMe nohup java -jar /home/restful-api-demo-0.0.1-SNAPSHOT.jar &
但是不要忘了挽牢,在這里我們的jenkins是通過rancher運(yùn)行在容器里面的澈蟆,按照上面的方式你是很難訪問到你的服務(wù)的,而且不能通過容器化工具對服務(wù)進(jìn)行管理卓研。那么趴俘,我們就需要maven編譯打包完成后,把可交付的jar包制作成鏡像上傳到鏡像倉庫奏赘,然后通過類似Webhooks的東西讓rancher部署該服務(wù)寥闪,后續(xù)對服務(wù)的管理工作就直接交由rancher來負(fù)責(zé),比如服務(wù)升級磨淌、Pod伸縮等疲憋,我們開發(fā)人員只需要把代碼提交到Git倉庫,后續(xù)的所有功能都可以自動化完成梁只,這看起來可能有點(diǎn)驚訝缚柳,但是容器化就是給我們帶來了這樣的好處。
6.2 容器中運(yùn)行
6.2.1 制作鏡像
要讓服務(wù)在容器中運(yùn)行搪锣,就像我們先前說的那樣秋忙,首先你得把服務(wù)制作成鏡像,這跟標(biāo)準(zhǔn)的docker鏡像制作流程并沒有什么出入构舟,首先編寫我們應(yīng)用的Dockerfile灰追,還是拿我們先前的示例項目來說,我已經(jīng)參考springBoot官網(wǎng)文檔編寫好了一份Dockerfile文件,地址如下:
https://github.com/wendell-dev/restful-api-demo/blob/master/Dockerfile
然后需要通過 docker daemon 制作鏡像弹澎,這里我們將采用在rancher中修改jenkins部署配置朴下,然后在jenkins中安裝docker插件來進(jìn)行鏡像的制作。
在rancher中對jenkins服務(wù)進(jìn)行升級苦蒿,在數(shù)據(jù)卷中加入如下圖所示配置殴胧,就是把宿主機(jī)的docker.sock文件共享給jenkins容器內(nèi)部使用,這樣jenkins容器內(nèi)部相當(dāng)于作為docker客戶端在與宿主機(jī)的docker服務(wù)端進(jìn)行通信佩迟,同時在高級選項里命令中的用戶UID設(shè)置為0溃肪,就是root權(quán)限運(yùn)行,不然使用docker時會提示沒有權(quán)限
在jenkins中安裝docker插件音五,在插件管理里找到并安裝如下插件(Docker plugin):
如果成功安裝插件惫撰,你會在你的系統(tǒng)管理菜單里看見Docker菜單:
然后在系統(tǒng)管理-系統(tǒng)設(shè)置中的最下面你會看到新增一個Docker云:
把前面掛載的docker.sock 文件寫入Docker Host URI 中:unix:///var/run/docker.sock,可以點(diǎn)擊 右中位置的TestConnection按鈕進(jìn)行測試是否連接成功
連接成功后躺涝,可以在系統(tǒng)管理菜單里進(jìn)入Docker菜單厨钻,看到如下界面,點(diǎn)擊docker進(jìn)入后坚嗜,里面會向你展示你宿主機(jī)上的所有鏡像以及容器
接下來配置我們創(chuàng)建的restful-api-demo服務(wù)夯膀,在Post Steps里添加一個Build/Publish Docker Image選項,Directory for Dockerfile填寫. (就一個點(diǎn))苍蔬,Cloud選擇先前添加docker云配置的名稱诱建,然后輸入鏡像名wendell/restful-api-demo,這里我們暫時不推送鏡像到鏡像倉庫中碟绑,因為目前就一個docker daemon俺猿,推送與拉取鏡像都會造成網(wǎng)絡(luò)開銷,我們這里相當(dāng)于鏡像構(gòu)建成功后格仲,直接會出現(xiàn)在我們宿主機(jī)的docker環(huán)境中
這里我們配置好后直接保存押袍,然后對服務(wù)進(jìn)行構(gòu)建,來看看構(gòu)建日志:
從日志中可以看出凯肋,我們maven編譯打包成功后谊惭,直接進(jìn)行的Docker Build,而且都成功了侮东,其實(shí)就相當(dāng)于在宿主機(jī)中的項目根目錄里執(zhí)行了如下構(gòu)建鏡像命令:
$ docker build -t wendell/restful-api-demo .
我們可以在宿主機(jī)執(zhí)行docker image ls命令查看鏡像是否正在存在圈盔,顯然,我們已經(jīng)成功制作了鏡像
6.2.2 運(yùn)行容器
你可以在宿主機(jī)中通過docker run 命令來啟動容器
$ docker run -p 8081:8081 -d --name restful-api-demo wendell/restful-api-demo
然后在瀏覽器中輸入http://192.168.225.129:8081/swagger-ui.html來試一試我們的示例項目是否啟動成功悄雅,不出意外的話驱敲,你將會看到如下界面:
通過 docker container ls 來查看我們剛才啟動的容器
現(xiàn)在我們來刪除容器,使用 docker container rm 3e4d6bf8d213 -f 命令煤伟,3e4d6是容器ID癌佩,-f代表強(qiáng)制刪除木缝,接下來我們將在rancher管理界面中部署服務(wù)便锨。
和先前部署jenkins服務(wù)一樣围辙,我們在部署頁中填入服務(wù)名稱與剛才構(gòu)建的鏡像wendell/restful-api-demo,然后映射8081端口到主機(jī)30002端口放案,在高級選項中的安全主機(jī)設(shè)置中把拉取鏡像設(shè)為從不(鏡像在宿主機(jī)):
直接點(diǎn)擊啟動按鈕姚建,進(jìn)入如下界面:
一直等到狀態(tài)為Active后,訪問http://192.168.225.129:30002/swagger-ui.html吱殉,出現(xiàn)如下界面說明我們服務(wù)已經(jīng)通過rancher部署成功:
七掸冤、 使用小結(jié)
經(jīng)過上面的一些工具安裝及使用流程的演示,相信你已經(jīng)能夠腦補(bǔ)出一個服務(wù)從開發(fā)到部署的流程圖友雳。作為一個開發(fā)人員稿湿,也許你最關(guān)心的是提交代碼之前的工作,但是押赊,多了解一些背后支持服務(wù)運(yùn)轉(zhuǎn)的整個流程饺藤,各個組件是怎么支撐我們高效工作的,這對我們來說無疑是很大的一個加分項流礁,而且也能為我們以后在軟件開發(fā)設(shè)計上能夠提供更多的思路涕俗。
接下來我可能會對一些更加自動化的東西進(jìn)行實(shí)戰(zhàn)記錄,加深容器化組件的使用神帅,同時更好的為我們的DevOps建設(shè)快速落地再姑。
好了,本篇實(shí)踐記錄差不多就這么多了找御,文中所有的操作都是基于前面幾篇創(chuàng)建的環(huán)境上下文而實(shí)現(xiàn)的元镀,如果你有興趣可以了解了解:
Docker決戰(zhàn)到底(一) 虛擬機(jī)中安裝ubuntu系統(tǒng)
Docker決戰(zhàn)到底(二) Docker環(huán)境搭建
Docker決戰(zhàn)到底(三) Rancher2.x的安裝與使用