流水線即代碼

2016年11月份的技術(shù)雷達(dá)中給出了一個(gè)簡(jiǎn)明的定義:流水線即代碼 (Pipeline as Code) 通過(guò)編碼而非配置持續(xù)集成/持續(xù)交付 (CI/CD) 運(yùn)行工具的方式定義部署流水線碗暗。
其實(shí)早在2015年11月份的技術(shù)雷達(dá)當(dāng)中就已經(jīng)有了類似的概念:

The way to avoid programming in your CI/CD tool is to extract the complexities of the build process from the guts of the tool and into a simple script which can be invoked by a single command. This script can then be executed on any developer workstation and therefore eliminates the privileged/singular status of the build environment
大意是將復(fù)雜的構(gòu)建流程納入一個(gè)簡(jiǎn)單的腳本文件膀藐,然后用一條命令調(diào)用。這樣,任意的開(kāi)發(fā)者都能在自己的工作區(qū)中執(zhí)行腳本重建一套一模一樣的構(gòu)建環(huán)境新症,從而消除 CI/CD 環(huán)境由于散亂配置腐化而成的特異性齐帚。這么做的原因很好理解速客,使用 CI/CD 工具是為了暴露產(chǎn)品代碼中的問(wèn)題的盈滴,如果它們自身已經(jīng)復(fù)雜到不穩(wěn)定的地步,我們還使用它就是自找麻煩撒汉。

從某種程度上看沟优,實(shí)施流水線即代碼是不證自明的。在 CI/CD 的時(shí)間過(guò)程中睬辐,凡是可以被編碼的東西都已經(jīng)被代碼化了挠阁,比如:構(gòu)建、測(cè)試溯饵、數(shù)據(jù)庫(kù)遷移侵俗、部署和基礎(chǔ)設(shè)施/環(huán)境配置 (Infrastruture as Code) 等。說(shuō)得爛俗點(diǎn)丰刊,流水線已經(jīng)是 CI/CD 實(shí)踐過(guò)程中的“最后一公里”隘谣,讓流水線變成軟件開(kāi)發(fā)中的“一等公民”(即代碼)是大勢(shì)所趨、民心所向啄巧。不過(guò)寻歧,這種論斷畢竟欠缺說(shuō)服力,我們接著從實(shí)踐的痛點(diǎn)出發(fā)總結(jié)當(dāng)前流水線遇到的問(wèn)題棵帽。

實(shí)踐中的痛點(diǎn)

我給客戶搭建和配置過(guò)不少 CI/CD 流水線(被同事戲謔地稱為“CI/CD搭建獸”),最大的痛苦莫過(guò)于每次都得從頭來(lái)過(guò)渣玲,即便大部分情況下所用的工具和配置都大同小異逗概。其次是手工操作產(chǎn)生的配置漂移 (configuration drift) 。以 Jenkins 為例忘衍,先不談 1.0 版本不支持流水線這一概念的問(wèn)題逾苫,我們?yōu)榱私鉀Q遇到的構(gòu)建卿城、測(cè)試和部署等問(wèn)題,一般會(huì)在多個(gè)文本框中粘貼大量 shell/batch 腳本铅搓;甚至?xí)ㄟ^(guò)這些文本框安裝各種插件或者依賴包瑟押、設(shè)置環(huán)境變量等等。久而久之(實(shí)際上不需要多久)星掰,這臺(tái) Jenkins 服務(wù)器就變得不可替代(特異化)了多望,因?yàn)闆](méi)人清楚到底對(duì)它做了哪些更改以及這些更改對(duì)承載它的系統(tǒng)產(chǎn)生哪些影響,這時(shí) Jenkins 服務(wù)器儼然腐化成了老馬所說(shuō)的雪花服務(wù)器 (snowflake server)氢烘。雪花服務(wù)器有兩點(diǎn)顯著的特征:

  1. 特別難以復(fù)現(xiàn)
  2. 幾乎無(wú)法理解

第一點(diǎn)是由于以往所做的更改并沒(méi)有被記錄下來(lái)怀偷,所以做過(guò)的操作都是七零八落的,沒(méi)有辦法復(fù)現(xiàn)同樣的操作播玖,也無(wú)法復(fù)制一個(gè)同樣的系統(tǒng)椎工。
第二點(diǎn)則是由于絕大部分情況下散亂的配置是沒(méi)有文檔描述的,哪部分是重要的已經(jīng)無(wú)從知曉蜀踏,改動(dòng)的風(fēng)險(xiǎn)很大维蒙。

這些問(wèn)題會(huì)在流水線的演化過(guò)程中惡化得越來(lái)越嚴(yán)重。一般來(lái)講果覆,除非不再使用颅痊,否則流水線不會(huì)保持一成不變。具體實(shí)施過(guò)程中随静,考慮到項(xiàng)目八千,尤其是遺留項(xiàng)目當(dāng)前的特點(diǎn)和團(tuán)隊(duì)成員的“產(chǎn)能”,我們會(huì)先將構(gòu)建和部署自動(dòng)化燎猛;部署節(jié)奏穩(wěn)定后恋捆,開(kāi)始將單元測(cè)試和代碼分析自動(dòng)化;接著可以指導(dǎo)測(cè)試人員將驗(yàn)收測(cè)試自動(dòng)化重绷;然后嘗試將發(fā)布自動(dòng)化沸停。在這之后,就要開(kāi)始持續(xù)優(yōu)化流水線昭卓,包括 CI 的速度和穩(wěn)定性等愤钾。換句話說(shuō),流水線的演化其實(shí)是和項(xiàng)目的當(dāng)前進(jìn)展密切相關(guān)的候醒,保證這樣的對(duì)應(yīng)關(guān)系有時(shí)是有必要的能颁,比如:在版本控制下,多發(fā)布分支所需流水線和主干分支會(huì)存在不同倒淫。發(fā)布分支是主干分支某個(gè)時(shí)刻分出去的伙菊,它需要在那時(shí)的流水線上才能正常工作。由于前面所說(shuō)雪花服務(wù)器的特征,重建這樣一條流水線并不是一件容易的事情镜硕。

演進(jìn)式的持續(xù)集成

如何解決

其實(shí)运翼,流水線即代碼本身已經(jīng)回答這個(gè)問(wèn)題了。當(dāng)前實(shí)現(xiàn)了這一概念的工具大體遵循了兩種模式:

  1. 版本控制
  2. DSL(領(lǐng)域特定語(yǔ)言)

對(duì)于特別難以復(fù)現(xiàn)兴枯、沒(méi)有保證對(duì)應(yīng)關(guān)系的痛點(diǎn)血淌,我們就把流水線寫成代碼放到版本控制工具中管理起來(lái)。這樣一來(lái)财剖,每一次更改都能被記錄下來(lái)悠夯,而且它會(huì)始終和此時(shí)的項(xiàng)目進(jìn)展保持同步。

對(duì)于幾乎無(wú)法理解峰伙、沒(méi)有文檔支持的痛點(diǎn)疗疟,我們就選用領(lǐng)域特定語(yǔ)言描述整條流水線。舉個(gè) Jenkins 2.0 例子瞳氓,它允許我們?cè)陧?xiàng)目的特定目錄下放置一個(gè) Jenkinsfile 的文件策彤,內(nèi)容大致如下:

node('master') {
    stage('Checkout') {…}
    stage('Code Analysis') {…}
    stage('Unit Test') {…}
    stage('Packing') {…}
    stage('Archive') {…}
    stage('DEV') {…}
}
stage('SIT') {
    timeout(time:4, unit:'HOURS') {
        input "Deploy to SIT?"
    }
    node('master') {…}
}
stage('Acceptance Test') {
    node('slave') {…}
}

Jenkins 2.0 使用Groovy實(shí)現(xiàn)了一套描述流水線的DSL,即便不了解Groovy語(yǔ)言匣摘,只要對(duì)流水線稍微熟悉店诗,就能按照例子和文檔編寫出符合要求的代碼。

類似的工具還有Concourse.ci音榜、λCD (LambdaCD) 等庞瘸。
Concourse.ci 使用了 yaml 實(shí)現(xiàn)了DSL,獨(dú)立抽象出Resource(外部依賴赠叼,如:git repo)擦囊、Job(函數(shù), get 和 put Resource )和 Task(純函數(shù)嘴办,必須明確定義 Input 和 Output )模型瞬场。

Concousre.ci

而 λCD 則使用 Clojure 語(yǔ)言實(shí)現(xiàn)了 DSL,抽象出 Pipeline 和 Step 模型涧郊,使用了Lisp特有的宏 (macro) 和普通函數(shù)贯被,編寫起來(lái)簡(jiǎn)單明了。

λCD
(def pipeline-def
  `(
    (either
     manualtrigger/wait-for-manual-trigger
     wait-for-repo)

    (with-workspace
      clone
      (in-parallel
       run-some-tests
       run-smokeing-tests)

      run-package
      deploy)))

上述的pipeline-def就是這條流水線的定義妆艘,極為優(yōu)雅得是彤灶,它的代碼和UI事實(shí)上構(gòu)成了一一映射的關(guān)系,簡(jiǎn)單到極致批旺。

值得一提的是幌陕,λCD 有別于其它同類型的工具,它本身就是一份用 Clojure 寫就的微服務(wù)汽煮。換句話說(shuō)搏熄,其它的工具可能需要借助基礎(chǔ)設(shè)施即代碼完成自身的安裝茅诱,但λCD不用,它完全可以采用其它微服務(wù)的部署方式搬卒,比如用 λCD 部署它自己,類似于編譯器的自舉 (bootstraping)翎卓。這個(gè)時(shí)候契邀,我們就需要兩套 λCD 服務(wù),一套用于部署自身失暴,另一套部署開(kāi)發(fā)中的工程坯门。

流水線自舉

小結(jié)

流水線即代碼是個(gè)新概念,也就意味著我們還需要花時(shí)間去探索與之相關(guān)的實(shí)踐逗扒,比如古戴,調(diào)試和測(cè)試(既然是代碼就需要測(cè)試)。一旦有了這些實(shí)踐矩肩,我們就可以把流水線本身作為產(chǎn)品放到流水線上運(yùn)作起來(lái)现恼,那時(shí)將會(huì)看到一種很好玩的現(xiàn)象——舊的流水線會(huì)構(gòu)建并部署新流水線,完成流水線的自舉 (pipeline bootstrap) 黍檩。此外叉袍,當(dāng)流水線成為代碼,它在最終的交付物中必然占據(jù)一席之地刽酱,其潛在的價(jià)值還等待我們挖掘喳逛,至少?gòu)木娴慕嵌龋魉€能做的事情還有很多棵里。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末润文,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子殿怜,更是在濱河造成了極大的恐慌典蝌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稳捆,死亡現(xiàn)場(chǎng)離奇詭異赠法,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)乔夯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門砖织,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人末荐,你說(shuō)我怎么就攤上這事侧纯。” “怎么了甲脏?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵眶熬,是天一觀的道長(zhǎng)妹笆。 經(jīng)常有香客問(wèn)我,道長(zhǎng)娜氏,這世上最難降的妖魔是什么拳缠? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮贸弥,結(jié)果婚禮上窟坐,老公的妹妹穿的比我還像新娘。我一直安慰自己绵疲,他們只是感情好哲鸳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著盔憨,像睡著了一般徙菠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上郁岩,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天婿奔,我揣著相機(jī)與錄音,去河邊找鬼问慎。 笑死脸秽,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蝴乔。 我是一名探鬼主播记餐,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼薇正!你這毒婦竟也來(lái)了片酝?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤挖腰,失蹤者是張志新(化名)和其女友劉穎雕沿,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體猴仑,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡审轮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辽俗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疾渣。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖崖飘,靈堂內(nèi)的尸體忽然破棺而出榴捡,到底是詐尸還是另有隱情,我是刑警寧澤朱浴,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布吊圾,位于F島的核電站达椰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏项乒。R本人自食惡果不足惜啰劲,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望檀何。 院中可真熱鬧呈枉,春花似錦、人聲如沸埃碱。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)砚殿。三九已至,卻和暖如春芝囤,著一層夾襖步出監(jiān)牢的瞬間似炎,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工悯姊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留羡藐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓悯许,卻偏偏與公主長(zhǎng)得像仆嗦,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子先壕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 文/鄢倩 2016年11月份的技術(shù)雷達(dá)中給出了一個(gè)簡(jiǎn)明的定義:流水線即代碼(Pipeline as Code)通過(guò)...
    ThoughtWorks閱讀 1,322評(píng)論 3 6
  • 本文是2017年3月13日晚9點(diǎn)在“AHA面對(duì)面”線上分享的“單件流的力量-伍斌_Ben面對(duì)面”的操練步驟瘩扼,這里是...
    程序員吾真本閱讀 3,686評(píng)論 3 14
  • <<互聯(lián)網(wǎng)敏捷DevOps和自動(dòng)化之5.持續(xù)集成>>持續(xù)集成的價(jià)值是什么?對(duì)于開(kāi)發(fā)和測(cè)試人員又意味著什么呢垃僚?1.1...
    燕京博士閱讀 2,785評(píng)論 0 5
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理集绰,服務(wù)發(fā)現(xiàn),斷路器谆棺,智...
    卡卡羅2017閱讀 134,654評(píng)論 18 139
  • 微服務(wù)因?yàn)榇『谜{(diào)頭, 可以很方便快速地更新升級(jí), 所以它才會(huì)大行其道 理論篇 從持續(xù)集成到持續(xù)交付, 工程師一直...
    老瓦在霸都閱讀 1,021評(píng)論 0 3