共計(jì) 5776 個(gè)字符,預(yù)計(jì)需要花費(fèi) 15 分鐘才能閱讀完成。
本篇內(nèi)容主要講解“docker 如何創(chuàng)建持續(xù)部署流水線(xiàn)”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓丸趣 TV 小編來(lái)帶大家學(xué)習(xí)“docker 如何創(chuàng)建持續(xù)部署流水線(xiàn)”吧!
創(chuàng)建持續(xù)部署流水線(xiàn)
我們已經(jīng)創(chuàng)建好了測(cè)試環(huán)境,在前文中我們也構(gòu)建好了 CI 流水線(xiàn),由它來(lái)創(chuàng)建應(yīng)用、將應(yīng)用打包進(jìn)容器、進(jìn)行集成測(cè)試?,F(xiàn)在我們將來(lái)到本系列文章的最終章,拓展 CI 流水線(xiàn)來(lái)創(chuàng)建一個(gè)持續(xù)部署流水線(xiàn)。
發(fā)布 Docker 鏡像
我們首先將打包的鏡像發(fā)布到 Docker 存儲(chǔ)庫(kù)中。方便起見(jiàn),我們使用了一個(gè)公共 DockerHub 倉(cāng)庫(kù),不過(guò),對(duì)于實(shí)際的開(kāi)發(fā)項(xiàng)目,我們還是建議將 Docker 鏡像 push 到私有庫(kù)中。下面我們?cè)?Jenkins 中創(chuàng)建一個(gè)新的 Free Style Project 任務(wù),點(diǎn)擊 New Item 按鈕,把任務(wù)命名為 push-go-auth-image。完成了這些步驟后,你會(huì)進(jìn)入到 Jenkins 任務(wù)配置頁(yè)面,在這里你可以定義 push 你的 go-auth 鏡像到 Dockerhub 所需要的步驟。
因?yàn)檫@是我們對(duì)前一章中構(gòu)建的流水線(xiàn)的后續(xù),因此該作業(yè)會(huì)有和 go-auth-integration-test 作業(yè)類(lèi)似的配置。你需要首先設(shè)置的是 parameterized build 并且添加 GO_AUTH_VERSION 變量。
要 push 鏡像,我們選擇 Add build step 下拉菜單,然后選擇 Execute shell 選項(xiàng)。在結(jié)果文本框中添加下面的命令。在這些命令中,我們將登陸到 DockerHub,并且 push 我們之前構(gòu)建好的鏡像。這里我們準(zhǔn)備將其 push 到 usman/go-auth 倉(cāng)庫(kù)中,而你則需要把它推送到自己的 DockerHub 庫(kù)中。
上一章提到,我們使用的是 git-flow 分支模型,其所有的功能分支都合并到“開(kāi)發(fā)”分支中。為了能夠不斷地將發(fā)生的變更部署到集成環(huán)境中,我們需要一個(gè)簡(jiǎn)單的機(jī)制來(lái)生成基于開(kāi)發(fā)分支的最新鏡像。在打包過(guò)程中,我們使用 GO_AUTH_VERSION 來(lái)標(biāo)記 docker 容器(例如,docker build -t usman/go-auth:${GO_AUTH_VERSION} ….)。在默認(rèn)情況下,這個(gè)版本將會(huì)成為開(kāi)發(fā)分支,但是本章后面我們將為我們的應(yīng)用程序創(chuàng)建新發(fā)布,使用 CI/CD 流水線(xiàn)來(lái)構(gòu)建、打包、測(cè)試,并把它們部署到我們的集成環(huán)境中。要注意的是,在這個(gè)方案中,我們總會(huì)覆蓋我們開(kāi)發(fā)分支的鏡像(usman/go-auth:develop),這限制了我們引用歷史構(gòu)建以及執(zhí)行回滾。你可以對(duì)流水線(xiàn)做一個(gè)簡(jiǎn)單的更改,把 Jenkins 構(gòu)建編號(hào)添加到自身的版本名稱(chēng)上,比如 usman/go-auth:develop-14。
你需要指定你的 DockerHub 用戶(hù)名、密碼和電子郵件地址。你可以在每次運(yùn)行時(shí)用參數(shù)構(gòu)建的方式指定它們,也可以使用 Jenkins Mask Passwords Plugin 在主要的 Jenkins 配置中安全地定義它們,并將它們添加到構(gòu)建中。要確保 Build Environment 中為你的作業(yè)啟用了“Mask passwords(并且啟用全局密碼)”。
現(xiàn)在我們需要確保這個(gè)作業(yè)是在集成測(cè)試作業(yè)之后才觸發(fā)的。要做到這一點(diǎn),我們需要更新集成測(cè)試作業(yè),以便使用當(dāng)前的構(gòu)建參數(shù)觸發(fā)參數(shù)化構(gòu)建。這意味著在每次成功運(yùn)行集成測(cè)試作業(yè)后,我們會(huì)把測(cè)試好的鏡像 push 到 DockerHub 上。
最后,我們需要在鏡像成功 push 到 DockerHub 之后觸發(fā)部署作業(yè)。就像我們?yōu)槠渌鳂I(yè)所做的一樣,我們可以通過(guò)添加構(gòu)建后操作來(lái)實(shí)現(xiàn)這一點(diǎn)。
部署到集成環(huán)境
我們將使用 Rancher Compose CLI 來(lái)停止運(yùn)行的環(huán)境,從 DockerHub 獲取最新的鏡像,并重新啟動(dòng)環(huán)境(提醒一下,Updates API 還在發(fā)展,可能會(huì)發(fā)生變化。未來(lái)幾周或者幾個(gè)月內(nèi)肯定會(huì)增加新的功能,因此請(qǐng)隨時(shí)查看文檔是否有更新項(xiàng))。在我們創(chuàng)建 Jenkins 作業(yè)來(lái)實(shí)現(xiàn)持續(xù)部署之前,我們先手動(dòng)完成這些步驟。
我們可以使用最簡(jiǎn)單的方法——停止所有服務(wù)(auth 服務(wù)、負(fù)載均衡器以及 mysql),提取最新的鏡像并啟動(dòng)所有服務(wù)。然而,對(duì)于我們來(lái)說(shuō),我們只想更新應(yīng)用程序,而并不想停止長(zhǎng)時(shí)間運(yùn)行的環(huán)境,這樣就不太理想了。要更新我們的應(yīng)用程序,我們首先要停止 auth-service。你可以在 Rancher Compose 使用 stop 命令完成操作。
這會(huì)停止運(yùn)行 goauth 服務(wù)的所有容器,你可以在 Rancher UI 中打開(kāi)堆棧來(lái)驗(yàn)證該服務(wù)的狀態(tài)是否設(shè)置為 Inactive(不活躍)。接下來(lái),我們要讓 Rancher 拉取我們想要部署的鏡像版本?,F(xiàn)在,我們已經(jīng)可以動(dòng)態(tài)指定想要運(yùn)行的版本,而無(wú)需每次都要更新模板了。如果你需要多次 push 相同的鏡像版本,請(qǐng)?zhí)砑?pull 開(kāi)關(guān),確保我們使用的是鏡像版本的最新副本。
我們還可以通過(guò)下面的命令使用升級(jí)功能,零停機(jī)地實(shí)現(xiàn)環(huán)境的滾動(dòng)更新。下一節(jié)中我們將進(jìn)一步討論滾動(dòng)更新。在升級(jí)完成后,你可以使 –rollbach 命令或 –confirm-upgrade 來(lái)確認(rèn)更改或者回滾到預(yù)覽狀態(tài)。
現(xiàn)在我們已經(jīng)知道該如何運(yùn)行我們的更新,我們?cè)诹魉€(xiàn)中創(chuàng)建一個(gè) Jenkins 作業(yè)來(lái)執(zhí)行此操作。和之前一樣,創(chuàng)建一個(gè)新的 freestyle 項(xiàng)目,命名為 deploy-integration。與其他的作業(yè)一樣,它也是一個(gè)參數(shù)化構(gòu)建,用 GO_AUTH_VERSION 作為字符串參數(shù)。接下來(lái),我們要從上游的 build-go-auth 作業(yè)中復(fù)制工件。
最后,我們需要向 Execute Sheell 構(gòu)建步驟中添加 Rancher Compose up 命令,這是我們?cè)谥爸付ê玫?。需要注意,你還需要提前在 Jenkins 上設(shè)置 Rancher CLI,讓它可以用于你在系統(tǒng)路徑上的構(gòu)建。執(zhí)行 shell 步驟的內(nèi)容和下面的代碼片段相似。如果你有多個(gè) Rancher Compose 節(jié)點(diǎn),負(fù)載均衡器容器可能會(huì)在不同的主機(jī)上啟動(dòng),你的 Route 53 記錄集合就可能需要更新。
有了我們兩個(gè)新的 Jenkins 作業(yè),我們從上一章就開(kāi)始構(gòu)建的流水線(xiàn)現(xiàn)在看起來(lái)就像下圖所示。每次對(duì)我們示例應(yīng)用程序的 check-in 都會(huì)被編譯,確保其沒(méi)有出現(xiàn)語(yǔ)法錯(cuò)誤并且能夠通過(guò)自動(dòng)化測(cè)試。然后,將這些變更打包,通過(guò)集成測(cè)試,最后再部署到手動(dòng)測(cè)試中。下面的五個(gè)步驟為構(gòu)建流水線(xiàn)提供了一個(gè)良好的基線(xiàn)模板,并且有助于將代碼從開(kāi)發(fā)階段轉(zhuǎn)移到測(cè)試和部署階段上。擁有一個(gè)連續(xù)的部署流水線(xiàn)確保了代碼不僅可以進(jìn)過(guò)自動(dòng)化系統(tǒng)的測(cè)試,而且還能快速提供給測(cè)試人員使用。除此之外它還能夠作為生產(chǎn)部署自動(dòng)化的模型,測(cè)試操作工具和代碼,持續(xù)部署應(yīng)用程序。
發(fā)布和部署一個(gè)新的版本
在我們將代碼部署到持續(xù)的可測(cè)試環(huán)境中后,我們就會(huì)讓 QA 團(tuán)隊(duì)測(cè)試對(duì)這些變更進(jìn)行一段時(shí)間的測(cè)試。在他們確定代碼已經(jīng)就緒后,我們可以創(chuàng)建一個(gè)發(fā)布,隨后將它部署到生產(chǎn)環(huán)境中。用 git-flow 發(fā)布的方式類(lèi)似于特征分支(我們?cè)谇耙徽掠懻撨^(guò)的工作方式),我們使用 gitflow release start [Release Name] 命令(如下所示)進(jìn)行發(fā)布。這將創(chuàng)建一個(gè)新的名稱(chēng)來(lái)發(fā)布分支。在這個(gè)分支中,我們將執(zhí)行一些內(nèi)部的操作,比如增加版本號(hào),做最后的修改。
完成這些后,我們運(yùn)行 releasefinish 命令將發(fā)布分支合并到主分支中。這樣,主分支總能反映出最新發(fā)布的代碼。另外,每個(gè)發(fā)布都會(huì)加上標(biāo)簽,對(duì)每個(gè)發(fā)布的內(nèi)容都能夠有歷史記錄。如果我們不需要再進(jìn)行其他的更改,我們就可以確定最終的發(fā)布了。
最后一步就是把發(fā)布 push 到遠(yuǎn)端倉(cāng)庫(kù)中
git push origin master git push –tags //pushes the v1 tag to remote repository
如果你使用的是 Github 來(lái)托管 git 庫(kù),現(xiàn)在應(yīng)該會(huì)發(fā)現(xiàn)有一個(gè)新的版本了。我們還可以將與發(fā)布名稱(chēng)相匹配的版本鏡像 push 到 DockerHub,這也是一個(gè)不錯(cuò)的選擇。我們先運(yùn)行第一項(xiàng)作業(yè)來(lái)觸發(fā)我們的 CD 流水線(xiàn)。可能你還記得,我們?yōu)?CI 流水線(xiàn)設(shè)置了 GitParameter 插件,以便能夠從 git 中獲取與過(guò)濾器相匹配的所有標(biāo)記。不過(guò),這是對(duì)于默認(rèn)的開(kāi)發(fā)分支而言,當(dāng)我們手動(dòng)觸發(fā)流水線(xiàn)時(shí),我們可以從 git 標(biāo)簽中進(jìn)行選擇。例如,在下面我們?yōu)閼?yīng)用程序提供了兩個(gè)版本。我們選擇其中一個(gè),啟動(dòng)集成和部署流水線(xiàn)。
然后,經(jīng)過(guò)以下步驟,我們的應(yīng)用程序 1.1 版本將會(huì)被部署到長(zhǎng)時(shí)間運(yùn)行的集成環(huán)境中,只需要點(diǎn)擊幾下就能實(shí)現(xiàn)。
從 git 中獲取所選的發(fā)布
構(gòu)建應(yīng)用程序,運(yùn)行單元測(cè)試
創(chuàng)建一個(gè)帶有標(biāo)簽 v1.1 的新鏡像(比如 usman/go-auth:v1.1)
運(yùn)行集成測(cè)試
Push 鏡像(usman/go-auth:v1.1)到 DockerHub
將該版本部署到我們的集成環(huán)境
部署策略
管理長(zhǎng)時(shí)間運(yùn)行的環(huán)境時(shí)會(huì)遇到很多挑戰(zhàn),其中之一就是盡可能在發(fā)布期間的停機(jī)時(shí)間要降至最短,最好為零。為了讓這個(gè)過(guò)程可預(yù)測(cè)并且安全,需要做相當(dāng)多的工作。自動(dòng)化和質(zhì)量保證確實(shí)可以大大提高發(fā)布的可預(yù)測(cè)性和安全性。不過(guò)即使是這樣,失敗也會(huì)發(fā)生,而且對(duì)任何優(yōu)秀的運(yùn)維團(tuán)隊(duì)來(lái)說(shuō),他們的目標(biāo)都是在最小化影響的同時(shí)快速恢復(fù)。在本節(jié)中,我們將介紹一些部署長(zhǎng)時(shí)間運(yùn)行環(huán)境的策略以及它們的優(yōu)缺點(diǎn)。
就地更新
第一個(gè)策略稱(chēng)為就地更新(In-placeupdates),顧名思義,它的思想就是復(fù)用應(yīng)用程序環(huán)境,并且就地更新應(yīng)用程序。這有時(shí)也稱(chēng)作是滾動(dòng)部署。我們將使用我們目前討論的示例應(yīng)用程序(go-auth)。此外,我們假定你有用 Rancher 運(yùn)行的服務(wù)。如果要就地更新,你可以使用下面的升級(jí)命令:
在用戶(hù)看不到的地方,Rancher agent 會(huì)在每個(gè)運(yùn)行 auth 服務(wù)容器的主機(jī)上獲取新的鏡像(–pull 會(huì)重新下載,盡管鏡像已經(jīng)存在)。之后代理會(huì)停止舊的容器,批量啟動(dòng)新的容器。你可以使用 –batch-size 標(biāo)志來(lái)控制批處理的大小。此外,你還可以指定批更新之間的暫停時(shí)間間隔(–interval),使用足夠大的時(shí)間間隔來(lái)驗(yàn)證新容器的行為是否按照預(yù)期運(yùn)行,并且總體而言,服務(wù)是健康的。在默認(rèn)情況下,舊的容器終止后,新的容器會(huì)在它們的位置上啟動(dòng)?;蛘吣憧梢栽?rancher-compose.yml 中設(shè)置 start_first 標(biāo)志,告訴 Rancher 在啟動(dòng)新容器之前先停止舊容器。
如果對(duì)當(dāng)前的更新不滿(mǎn)意想要回滾,可以使用回滾標(biāo)志來(lái)完成回滾?;蛘吣阆胍^續(xù)進(jìn)行更新,只需告訴 rancher 指定 confirm-update 標(biāo)志完成更新即可。你也可以在原始的 up 命令中指定 confirm-update 標(biāo)志一步完成這些操作。你還可以在 RancherUI 執(zhí)行更新,從服務(wù)菜單(下圖所示)中選擇“upgrade”。
就地更新非常簡(jiǎn)單,不需要額外的資源來(lái)管理多個(gè)堆棧。然而,這種生產(chǎn)方式是存在缺點(diǎn)的。首先,對(duì)回滾更新進(jìn)行細(xì)粒度控制大多很困難,就是說(shuō)在故障發(fā)生的情況下它們往往是難以估計(jì)的。例如,處理部分故障和滾動(dòng)更新會(huì)變得非常混亂。你需要知道在哪些節(jié)點(diǎn)上部署了更改,哪些沒(méi)能部署,還有哪些仍在運(yùn)行之前的版本。其次,你還需要保證所有的更新不僅是向后兼容,還能向前兼容,因?yàn)榕f版本和新版本都是需要在相同的環(huán)境中同時(shí)運(yùn)行的。最后,根據(jù)使用的情況,就地更新可能不實(shí)用。比如,如果老的客戶(hù)端需要繼續(xù)使用舊環(huán)境,而新的客戶(hù)端需要向前滾。在這種情況下,使用我們今天要列出的方法分離客戶(hù)端會(huì)更加容易。
藍(lán)綠部署
就地更新的一個(gè)問(wèn)題是缺少可預(yù)測(cè)性。為了克服這一問(wèn)題,另一個(gè)部署策略是針對(duì)應(yīng)用程序使用兩個(gè)并行堆棧:一個(gè)處于活躍狀態(tài),另一個(gè)處于待機(jī)狀態(tài)。要運(yùn)行新版本,部署應(yīng)用程序的最新版本到待機(jī)堆棧。當(dāng)驗(yàn)證到新版本需要工作,將會(huì)從活動(dòng)堆棧切換流量到備用堆棧上。這時(shí),先前活躍的堆棧稱(chēng)為備用堆棧,反之亦然。該策略允許驗(yàn)證已經(jīng)部署的代碼、快速回滾(切換備用和重新激活),并還可以在需要時(shí)擴(kuò)展兩個(gè)堆棧的并發(fā)操作。這種策略通常被稱(chēng)為藍(lán)綠部署。用我們的示例應(yīng)用程序完成這樣的部署,可以簡(jiǎn)單地在 Rancher 中創(chuàng)建兩個(gè)堆棧:go-auth-blue 和 go-auth-green。此外,我們假設(shè)數(shù)據(jù)庫(kù)不是這些堆棧的一部分,而是獨(dú)立管理的。每個(gè)堆棧都會(huì)運(yùn)行 goauth 和 auth-lb 服務(wù)。如果假設(shè) go-auth-green 堆棧式活躍的,要執(zhí)行更新,我們要做的就是將最新版本部署到藍(lán)色堆棧中,執(zhí)行驗(yàn)證并將流量切換到它這。
流量切換
有兩個(gè)方法可用于執(zhí)行流量切換,更改 DNS 記錄來(lái)指向新堆棧,或者使用代理或負(fù)載均衡器,將流量路由到活動(dòng)堆棧。下面我們會(huì)詳細(xì)介紹這兩個(gè)方法。
記錄更新
一個(gè)簡(jiǎn)單的方法是更新 DNS 記錄指向活動(dòng)堆棧。這種方法的一個(gè)優(yōu)點(diǎn)是,我們可以使用加權(quán) DNS 記錄將流量慢慢轉(zhuǎn)換到新版本中。這也是執(zhí)行 canary releases 的簡(jiǎn)單方法,對(duì)安全地在實(shí)時(shí)環(huán)境中進(jìn)行更新或者做 A / B 測(cè)試非常有用。例如,我們可以將實(shí)驗(yàn)性的功能更部署到自己的功能堆棧(或活動(dòng)堆棧),然后更新 DNS,僅將一小部分流量轉(zhuǎn)發(fā)到新版本。如果新更新出現(xiàn)問(wèn)題,我們可以逆轉(zhuǎn) DNS 記錄回滾回來(lái)。此外,他比將所有流量從一個(gè)堆棧切換到另一個(gè)堆棧要安全得多,因?yàn)檫@樣會(huì)覆蓋掉新的堆棧。雖然簡(jiǎn)單,如果你希望所有流量能一次切換到新版本,DNS 記錄更新就把 u 事最簡(jiǎn)潔的方法。根據(jù) DNS 客戶(hù)端不同,這些更改可能需要很長(zhǎng)時(shí)間才能傳播,從而導(dǎo)致和舊版本之間的大量通信,而不是直接了斷切換。
使用反向代理
使用代理或負(fù)載均衡器,只需要將其更新成指向新堆棧就可以一次切換整個(gè)流量。這種方法在各種場(chǎng)景下都非常有用,例如非向后兼容的更新。要使用 Rancher 完成這一操作,我們首先要?jiǎng)?chuàng)建一個(gè)僅包含負(fù)載均衡器的堆棧。
接著,我們?yōu)樨?fù)載均衡器指定一個(gè)端口,配置 SSL 并從下拉菜單中選擇活動(dòng)堆棧的負(fù)載均衡器作為 target service 來(lái)完成創(chuàng)建。本質(zhì)上來(lái)說(shuō),我們將負(fù)載放到了負(fù)載均衡器上,它會(huì)在之后將流量路由到實(shí)際的服務(wù)節(jié)點(diǎn)。借助外部負(fù)載均衡器,你不需要更新每個(gè)版本的 DNS 記錄。相反,你可以簡(jiǎn)單地更新外部負(fù)載均衡器指向已更新的堆棧。
到此,相信大家對(duì)“docker 如何創(chuàng)建持續(xù)部署流水線(xiàn)”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是丸趣 TV 網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!