基于GitLab和docker的CI/CD系統(tǒng)

An engineer, it is said, is someone who can do for a dime what any fool can do for a dollar.

項(xiàng)目在演進(jìn)過(guò)程中死姚,團(tuán)隊(duì)有了一套較為完備的開(kāi)發(fā)pipeline麻诀,這篇文章將講述全棧系統(tǒng)中這個(gè)較為遠(yuǎn)離業(yè)務(wù)的環(huán)節(jié) —— DevOps。

概念淺析

開(kāi)宗明義扭勉,為了讓大家更好的理解工作腌且,我們先來(lái)一波名次的定義摩瞎。

CI: Continuous Integration, 持續(xù)集成乱灵,指的是頻繁的將代碼集成到主干上硫朦,每次集成都通過(guò)自動(dòng)化的構(gòu)建(包括編譯、發(fā)布鹃唯、自動(dòng)化測(cè)試)來(lái)驗(yàn)證爱榕;

CD: Continuous Deliver, 持續(xù)交付瓣喊,指的是在代碼集成坡慌,也就是分支代碼合并到主干之后,能夠被手動(dòng)的觸發(fā)藻三,是否發(fā)布到生產(chǎn)環(huán)境洪橘,直接讓用戶體驗(yàn)最新代碼跪者;

CD: Continuous Deployment, 持續(xù)部署,和持續(xù)交付一樣熄求,只不過(guò)由手動(dòng)觸發(fā)變成自動(dòng)發(fā)布渣玲,不再需要人為干擾。

GitLab CI/CD

如果想更了解CI/CD在業(yè)務(wù)層面的意思弟晚,可以閱讀我的另一篇文章 精益開(kāi)發(fā)忘衍,關(guān)于持續(xù)交付

鏈路重點(diǎn)

項(xiàng)目開(kāi)發(fā)經(jīng)歷了這樣幾個(gè)階段:

  • 每個(gè)sprint的交付日都緊張兮兮卿城,不同分支的代碼都需要往master上合并枚钓,push、merge request瑟押、conflict搀捷、rebase、test多望,如此往復(fù)嫩舟,單單集成開(kāi)發(fā)的代碼都需要一下午的時(shí)間;
  • 為了敢于合并怀偷,大膽上線家厌,團(tuán)隊(duì)寫足了自動(dòng)化測(cè)試,完善了Gitlab的pipeline椎工,隨后在交付日就只需要半個(gè)小時(shí)到兩個(gè)小時(shí)像街;
  • 隨后發(fā)現(xiàn)部署新版本不方便,就用dockerfile來(lái)打包可運(yùn)行的鏡像晋渺,然后在交付日我們只需要點(diǎn)擊部署就OK了镰绎,上線不過(guò)十分鐘。

在奇跡般的變化背后木西,有這樣幾件事值得注意畴栖。

階段一:緊張交付一下午

團(tuán)隊(duì)會(huì)盡可能在上午完成feature的開(kāi)發(fā),一般有三個(gè)分支需要合并八千,每個(gè)分支合并前后都需要手動(dòng)運(yùn)行測(cè)試吗讶,由于測(cè)試都依賴開(kāi)發(fā)環(huán)境數(shù)據(jù)庫(kù)而不能并發(fā)運(yùn)行,上線之后需要持續(xù)監(jiān)控半小時(shí)恋捆,很有可能hotfix改bug照皆。

條件的艱苦,使每一次上線都是團(tuán)隊(duì)的大事件沸停,也讓我學(xué)會(huì)了代碼部署的每一個(gè)小細(xì)節(jié)膜毁,更在之后的日子里讓我感受到計(jì)算機(jī)對(duì)效率的提升之巨。

階段二:輕松部署半小時(shí)

手動(dòng)測(cè)試到自動(dòng)測(cè)試

利用Gitlab的pipeline流程,在配置好runner后瘟滨,就可以很輕松的運(yùn)行自動(dòng)化測(cè)試了候醒。(在剛開(kāi)始自動(dòng)化時(shí),我們選用了gitlab的webhook杂瘸,webhook會(huì)在push和merge事件之后倒淫,觸發(fā)一個(gè)鉤子到特定的機(jī)器上運(yùn)行測(cè)試,然后機(jī)器上會(huì)出現(xiàn)各種耦合败玉,不建議使用)

完善測(cè)試

感受到自動(dòng)化測(cè)試的便利之后敌土,為了讓團(tuán)隊(duì)對(duì)上線有信心,我們編寫了大量的測(cè)試运翼,方方面面測(cè)了個(gè)遍纯赎,終于不再懼怕重構(gòu),敢于上線南蹂。

testStage:
    stage: test
    image:
        name: image  # 使用合適的鏡像犬金,具備測(cè)試運(yùn)行所需要的環(huán)境
    services:
        - name: https://hub.docker.com/_/mongo
          alias: mongo  # 使用官方的mongo鏡像當(dāng)作service,可以隔離集成測(cè)試的環(huán)境六剥,讓測(cè)試并發(fā)運(yùn)行而不互相干擾
    script:
        - python -m unittest tests.test_a.TestA
    only:
        - develop  # 個(gè)性化設(shè)置晚顷,僅在develop分支上運(yùn)行,讓集成測(cè)試更快更方便

Advantages:

  • 并行的測(cè)試大大提高了集成的效率疗疟;
  • 每次提交都會(huì)運(yùn)行的測(cè)試该默,杜絕了忘記測(cè)試的隱患;
  • 測(cè)試覆蓋率很高策彤,代碼上線很放心栓袖;
  • yml文件中的注釋都有一些痛的經(jīng)歷:
    • 在runner上準(zhǔn)備python的虛擬環(huán)境非常困難,下文中將說(shuō)到鏡像的由來(lái)店诗;
    • 為解決共享耦合的測(cè)試環(huán)境裹刮,我依次選用了mock mongo代碼技術(shù),local mongod本地mongo方案庞瘸,和最終確定的mongo service階段捧弃;
    • 測(cè)試的數(shù)量很大,只運(yùn)行合適的測(cè)試可以有效加快效率擦囊;

Disadvantages:

  • 測(cè)試急劇增多违霞,測(cè)試時(shí)間變得夸張的長(zhǎng),導(dǎo)致團(tuán)隊(duì)害怕push瞬场,害怕觸發(fā)測(cè)試买鸽;
  • 測(cè)試不穩(wěn)定,漫長(zhǎng)的測(cè)試中一點(diǎn)出錯(cuò)贯被,全部測(cè)試都必須重跑眼五;

階段三:持續(xù)交付真方便

在“痛苦”的自動(dòng)化測(cè)試半小時(shí)之后妆艘,我們終于有了可交付的master代碼庫(kù),然后就是重啟服務(wù)弹砚,也就是重啟一下機(jī)器双仍,這很簡(jiǎn)單枢希。但是桌吃,如果想要增加一臺(tái)機(jī)器、刪除一臺(tái)機(jī)器就比較麻煩了苞轿。為了實(shí)現(xiàn)灰度發(fā)布茅诱,藍(lán)綠發(fā)布,我緊接著開(kāi)發(fā)了以docker為核心的部署系統(tǒng)搬卒。

deliverStage:
    stage: deliver
    script:
        # 把舊的鏡像拉下來(lái)瑟俭,如果是第一次運(yùn)行(會(huì)拉不到就報(bào)錯(cuò))就直接true跳過(guò)
        - docker pull ${OLD_IMAGE} || true
        # 獲得sh文件的執(zhí)行權(quán)限,以便運(yùn)行鏡像是容器有權(quán)限執(zhí)行
        - chmod a+x *.sh
        # 打包可運(yùn)行鏡像
        - docker build --pull --cache-from ${OLD_IMAGE} -t ${NEW_IMAGE} -f Dockerfile .
        # 將鏡像推送至遠(yuǎn)端倉(cāng)庫(kù)
        - docker push ${NEW_IMAGE}
    only:
        - master
    tags:
        - docker
# Dockerfile —— 打包可運(yùn)行服務(wù)的dockerfile
# 使用這個(gè)緩存鏡像作為源鏡像
FROM ${my-image-repo-url}/gitlab-ci-cache/my-project:cache

# 用gitlab runner上的最新代碼契邀,直接覆蓋摆寄,這樣鏡像就得到了最新代碼
COPY . $APP_HOME
# 覆蓋鏡像中的run.sh,鏡像將在啟動(dòng)最后運(yùn)行此文件
COPY run.sh /run.sh

無(wú)論是重啟還是新增坯门,都只需要new一個(gè)新的容器微饥,然后拉取可運(yùn)行的鏡像就可以了。

在學(xué)會(huì)了docker和gitlab CI/CD的流程之后古戴,我重構(gòu)了系統(tǒng)中的部分環(huán)節(jié)欠橘。

  1. 使用docker緩存python虛擬環(huán)境

docker系統(tǒng)的緩存層做的很棒,每執(zhí)行一條新的語(yǔ)句就會(huì)生成一個(gè)新的鏡像層现恼,如果語(yǔ)句沒(méi)有變化肃续,則會(huì)直接使用已有的緩存層來(lái)繼續(xù)執(zhí)行下一條語(yǔ)句。

這樣的話叉袍,如果我的Pipfile和Pipfile.lock(pipenv的依賴管理文件)沒(méi)有發(fā)生變動(dòng)始锚,就直接使用現(xiàn)有的虛擬環(huán)境包文件,可以極大的優(yōu)化pipeline的流程喳逛,極大的縮短pipeline的時(shí)長(zhǎng)疼蛾。

# Dockerfile.cache
# 環(huán)境緩存層的鏡像dockerfile
FROM ${my-image-repo-url}/centos_py3:latest

ENV APP_HOME /home/my-project/

# 這里將最新的Pipfile復(fù)制到鏡像中
COPY Pipfile $APP_HOME
COPY Pipfile.lock $APP_HOME

# 如果文件Pip依賴沒(méi)有變更,這里的RUN語(yǔ)句將直接用鏡像層艺配,不會(huì)重新運(yùn)行察郁,可以節(jié)省大量的時(shí)間
RUN cd $APP_HOME && \
    pipenv install -d --skip-lock
  1. 提前打包鏡像,使用待發(fā)布的鏡像做測(cè)試

有了虛擬環(huán)境的緩存鏡像转唉,幾乎消除了為自動(dòng)化測(cè)試準(zhǔn)備環(huán)境的時(shí)間皮钠,這樣我就可以把測(cè)試分成很多小的runner job,就一舉解決了測(cè)試運(yùn)行時(shí)間過(guò)長(zhǎng)赠法、測(cè)試不穩(wěn)定的問(wèn)題麦轰。

cacheStage:
    stage: cache
    script:
        - do cache with centos_py3 image
    tags:
        - docker

buildStage:
    stage: build
    script:
        - do build with cache image
    tags:
        - docker

testStage-1:
    stage: test
    image:
        name: ${BUILD_IMAGE}
    services:
        - name: mongo
          alias: mongo
    script:
        - do test
    tags:
        - docker

testStage-2:
    stage: test
    image:
        name: ${BUILD_IMAGE}
    services:
        - name: mongo
          alias: mongo
    script:
        - do test
    tags:
        - docker

deliverStage:
    stage: deliver
    script:
        - push build image to prod environment
    tags:
        - docker

做個(gè)小結(jié)

今年寫了幾篇文章乔夯,個(gè)人感覺(jué)是更偏技術(shù)了,但是閱讀者了了款侵,甚至投稿審核都難以通過(guò)末荐,還是比較令人受挫的。(可能我并非科班出身新锈,無(wú)論是技術(shù)重點(diǎn)和寫作重點(diǎn)甲脏,都需要更多的學(xué)習(xí)。)

這篇文章也只是一個(gè)方向的探索妹笆、總結(jié)和分享块请,具體要落地,需要有完備的容器化和docker技術(shù)拳缠,需要深入了解gitlab.yml和dockerfile的語(yǔ)法知識(shí)墩新,需要團(tuán)隊(duì)的支持和時(shí)間的投入,當(dāng)然結(jié)果也是顯而易見(jiàn)的窟坐,會(huì)極大的優(yōu)化團(tuán)隊(duì)開(kāi)發(fā)效率海渊,加快敏捷團(tuán)隊(duì)的迭代速度。

最后鼓勵(lì)一下自己哲鸳,哪怕看官不多臣疑,但是學(xué)習(xí)和總結(jié)的過(guò)程已經(jīng)令人愉悅了,下面幾期講講數(shù)據(jù)結(jié)構(gòu)和基礎(chǔ)算法的學(xué)習(xí)吧帕胆。

既然這可能是全棧的最后一篇文章朝捆,那么我也做個(gè)鏈接吧。

歡迎大家關(guān)注驮樊、點(diǎn)贊,也非常希望讀者能說(shuō)出自己關(guān)心的內(nèi)容片酝,共同進(jìn)步囚衔,共同成長(zhǎng)!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末雕沿,一起剝皮案震驚了整個(gè)濱河市练湿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌审轮,老刑警劉巖肥哎,帶你破解...
    沈念sama閱讀 211,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辽俗,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡篡诽,警方通過(guò)查閱死者的電腦和手機(jī)崖飘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)杈女,“玉大人朱浴,你說(shuō)我怎么就攤上這事”绦牛” “怎么了赊琳?”我有些...
    開(kāi)封第一講書人閱讀 157,435評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵街夭,是天一觀的道長(zhǎng)砰碴。 經(jīng)常有香客問(wèn)我,道長(zhǎng)板丽,這世上最難降的妖魔是什么呈枉? 我笑而不...
    開(kāi)封第一講書人閱讀 56,509評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮埃碱,結(jié)果婚禮上猖辫,老公的妹妹穿的比我還像新娘。我一直安慰自己砚殿,他們只是感情好啃憎,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著似炎,像睡著了一般辛萍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上羡藐,一...
    開(kāi)封第一講書人閱讀 49,837評(píng)論 1 290
  • 那天贩毕,我揣著相機(jī)與錄音,去河邊找鬼仆嗦。 笑死辉阶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瘩扼。 我是一名探鬼主播谆甜,決...
    沈念sama閱讀 38,987評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼集绰!你這毒婦竟也來(lái)了规辱?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,730評(píng)論 0 267
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤倒慧,失蹤者是張志新(化名)和其女友劉穎按摘,沒(méi)想到半個(gè)月后包券,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,194評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡炫贤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評(píng)論 2 327
  • 正文 我和宋清朗相戀三年溅固,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兰珍。...
    茶點(diǎn)故事閱讀 38,664評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡侍郭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出掠河,到底是詐尸還是另有隱情亮元,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評(píng)論 4 330
  • 正文 年R本政府宣布唠摹,位于F島的核電站爆捞,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏勾拉。R本人自食惡果不足惜煮甥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望藕赞。 院中可真熱鬧成肘,春花似錦、人聲如沸斧蜕。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,764評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)批销。三九已至洒闸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間风钻,已是汗流浹背顷蟀。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,997評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留骡技,地道東北人鸣个。 一個(gè)月前我還...
    沈念sama閱讀 46,389評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像布朦,于是被迫代替她去往敵國(guó)和親囤萤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評(píng)論 2 349