持續集成與持續部署寶典Part 4:建立持續部署流水線

隨着Docker項目及其相關生態系統逐漸成熟,容器已經開始被更多企業用在了更大規模的項目中。所以,咱們須要一套連貫的工做流程和流水線來簡化大規模項目的部署。mysql

Rancher Labs準備了此持續集成與持續部署系列文章,共兩萬餘字,但願能供企業參考如何利用諸如Docker和Rancher這類工具來建立屬於企業的持續集成和持續部署流水線,並根據本身的實際狀況和需求在這CI/CD流水線中也加入自定義的流程。git

本文是此係列文章的最後一篇,咱們將在本文中完成建立持續部署流水線的最後工做。本文內容包括建立持續部署流水線(發佈Docker鏡像、部署到集成環境、發佈和部署一個新的版本)和部署策略(就地更新、藍綠部署)。sql

建立持續部署流水線docker

咱們已經建立好了測試環境,在前文中咱們也構建好了CI流水線,由它來建立應用、將應用打包進容器、進行集成測試。如今咱們未來到本系列文章的最終章,拓展CI流水線來建立一個持續部署流水線。shell

發佈Docker鏡像數據庫

咱們首先將打包的鏡像發佈到Docker存儲庫中。方便起見,咱們使用了一個公共DockerHub倉庫,不過,對於實際的開發項目,咱們仍是建議將Docker鏡像push到私有庫中。下面咱們在Jenkins中建立一個新的Free Style Project任務,點擊New Item按鈕,把任務命名爲push-go-auth-image。完成了這些步驟後,你會進入到Jenkins任務配置頁面,在這裏你能夠定義push你的go-auth鏡像到Dockerhub所須要的步驟。安全

由於這是咱們對前一章中構建的流水線的後續,所以該做業會有和go-auth-integration-test做業相似的配置。你須要首先設置的是parameterized build而且添加GO_AUTH_VERSION變量。併發

要push鏡像,咱們選擇Add build step下拉菜單,而後選擇Execute shell選項。在結果文本框中添加下面的命令。在這些命令中,咱們將登錄到DockerHub,而且push咱們以前構建好的鏡像。這裏咱們準備將其push到usman/go-auth倉庫中,而你則須要把它推送到本身的DockerHub庫中。負載均衡

上一章提到,咱們使用的是git-flow分支模型,其全部的功能分支都合併到「開發」分支中。爲了可以不斷地將發生的變動部署到集成環境中,咱們須要一個簡單的機制來生成基於開發分支的最新鏡像。在打包過程當中,咱們使用GO_AUTH_VERSION來標記docker容器(例如,docker build -t usman/go-auth:${GO_AUTH_VERSION} ....)。在默認狀況下,這個版本將會成爲開發分支,可是本章後面咱們將爲咱們的應用程序建立新發布,使用CI/CD流水線來構建、打包、測試,並把它們部署到咱們的集成環境中。要注意的是,在這個方案中,咱們總會覆蓋咱們開發分支的鏡像(usman/go-auth:develop) ,這限制了咱們引用歷史構建以及執行回滾。你能夠對流水線作一個簡單的更改,把Jenkins構建編號添加到自身的版本名稱上,好比usman/go-auth:develop-14。運維

你須要指定你的DockerHub用戶名、密碼和電子郵件地址。你能夠在每次運行時用參數構建的方式指定它們,也可使用Jenkins Mask Passwords Plugin在主要的Jenkins配置中安全地定義它們,並將它們添加到構建中。要確保Build Environment中爲你的做業啓用了「Mask passwords(而且啓用全局密碼)」。

如今咱們須要確保這個做業是在集成測試做業以後才觸發的。要作到這一點,咱們須要更新集成測試做業,以便使用當前的構建參數觸發參數化構建。這意味着在每次成功運行集成測試做業後,咱們會把測試好的鏡像push到DockerHub上。

最後,咱們須要在鏡像成功push到DockerHub以後觸發部署做業。就像咱們爲其餘做業所作的同樣,咱們能夠經過添加構建後操做來實現這一點。

部署到集成環境

咱們將使用Rancher Compose CLI來中止運行的環境,從DockerHub獲取最新的鏡像,並從新啓動環境(提醒一下,Updates API還在發展,可能會發生變化。將來幾周或者幾個月內確定會增長新的功能,所以請隨時查看文檔是否有更新項)。在咱們建立Jenkins做業來實現持續部署以前,咱們先手動完成這些步驟。

咱們可使用最簡單的方法——中止全部服務(auth服務、負載均衡器以及mysql),提取最新的鏡像並啓動全部服務。然而,對於咱們來講,咱們只想更新應用程序,而並不想中止長時間運行的環境,這樣就不太理想了。要更新咱們的應用程序,咱們首先要中止auth-service。你能夠在Rancher Compose使用stop命令完成操做。

這會中止運行goauth服務的全部容器,你能夠在Rancher UI中打開堆棧來驗證該服務的狀態是否設置爲Inactive(不活躍)。接下來,咱們要讓Rancher拉取咱們想要部署的鏡像版本。如今,咱們已經能夠動態指定想要運行的版本,而無需每次都要更新模板了。若是你須要屢次push相同的鏡像版本,請添加pull開關,確保咱們使用的是鏡像版本的最新副本。

咱們還能夠經過下面的命令使用升級功能,零停機地實現環境的滾動更新。下一節中咱們將進一步討論滾動更新。在升級完成後,你可使--rollbach命令或--confirm-upgrade來確認更改或者回滾到預覽狀態。

如今咱們已經知道該如何運行咱們的更新,咱們在流水線中建立一個Jenkins做業來執行此操做。和以前同樣,建立一個新的freestyle項目,命名爲deploy-integration。與其餘的做業同樣,它也是一個參數化構建,用GO_AUTH_VERSION做爲字符串參數。接下來,咱們要從上游的build-go-auth做業中複製工件。

最後,咱們須要向Execute Sheell構建步驟中添加Rancher Compose up命令,這是咱們在以前指定好的。須要注意,你還須要提早在Jenkins上設置Rancher CLI,讓它能夠用於你在系統路徑上的構建。執行shell步驟的內容和下面的代碼片斷類似。若是你有多個Rancher Compose節點,負載均衡器容器可能會在不一樣的主機上啓動,你的Route 53記錄集合就可能須要更新。

有了咱們兩個新的Jenkins做業,咱們從上一章就開始構建的流水線如今看起來就像下圖所示。每次對咱們示例應用程序的check-in都會被編譯,確保其沒有出現語法錯誤而且可以經過自動化測試。而後,將這些變動打包,經過集成測試,最後再部署到手動測試中。下面的五個步驟爲構建流水線提供了一個良好的基線模板,而且有助於將代碼從開發階段轉移到測試和部署階段上。擁有一個連續的部署流水線確保了代碼不只能夠進過自動化系統的測試,並且還能快速提供給測試人員使用。除此以外它還可以做爲生產部署自動化的模型,測試操做工具和代碼,持續部署應用程序。

發佈和部署一個新的版本

在咱們將代碼部署到持續的可測試環境中後,咱們就會讓QA團隊測試對這些變動進行一段時間的測試。在他們肯定代碼已經就緒後,咱們能夠建立一個發佈,隨後將它部署到生產環境中。用git-flow發佈的方式相似於特徵分支(咱們在前一章討論過的工做方式),咱們使用gitflow release start [Release Name]命令(以下所示)進行發佈。這將建立一個新的名稱來發布分支。在這個分支中,咱們將執行一些內部的操做,好比增長版本號,作最後的修改。

完成這些後,咱們運行releasefinish命令將發佈分支合併到主分支中。這樣,主分支總能反映出最新發布的代碼。另外,每一個發佈都會加上標籤,對每一個發佈的內容都可以有歷史記錄。若是咱們不須要再進行其餘的更改,咱們就能夠肯定最終的發佈了。

最後一步就是把發佈push到遠端倉庫中

git push origin master
git push --tags //pushes the v1 tag to remote repository

若是你使用的是Github來託管git庫,如今應該會發現有一個新的版本了。咱們還能夠將與發佈名稱相匹配的版本鏡像push到DockerHub,這也是一個不錯的選擇。咱們先運行第一項做業來觸發咱們的CD流水線。可能你還記得,咱們爲CI流水線設置了GitParameter插件,以便可以從git中獲取與過濾器相匹配的全部標記。不過,這是對於默認的開發分支而言,當咱們手動觸發流水線時,咱們能夠從git標籤中進行選擇。例如,在下面咱們爲應用程序提供了兩個版本。咱們選擇其中一個,啓動集成和部署流水線。

而後,通過如下步驟,咱們的應用程序1.1版本將會被部署到長時間運行的集成環境中,只須要點擊幾下就能實現。

  1. 從git中獲取所選的發佈
  2. 構建應用程序,運行單元測試
  3. 建立一個帶有標籤v1.1的新鏡像(好比usman/go-auth:v1.1)
  4. 運行集成測試
  5. Push鏡像(usman/go-auth:v1.1)到DockerHub
  6. 將該版本部署到咱們的集成環境

部署策略

管理長時間運行的環境時會遇到不少挑戰,其中之一就是儘量在發佈期間的停機時間要降至最短,最好爲零。爲了讓這個過程可預測而且安全,須要作至關多的工做。自動化和質量保證確實能夠大大提升發佈的可預測性和安全性。不過即便是這樣,失敗也會發生,並且對任何優秀的運維團隊來講,他們的目標都是在最小化影響的同時快速恢復。在本節中,咱們將介紹一些部署長時間運行環境的策略以及它們的優缺點。

就地更新

第一個策略稱爲就地更新(In-placeupdates),顧名思義,它的思想就是複用應用程序環境,而且就地更新應用程序。這有時也稱做是滾動部署。咱們將使用咱們目前討論的示例應用程序(go-auth)。此外,咱們假定你有用Rancher運行的服務。若是要就地更新,你可使用下面的升級命令:

在用戶看不到的地方,Rancher agent會在每一個運行auth服務容器的主機上獲取新的鏡像(--pull會從新下載,儘管鏡像已經存在)。以後代理會中止舊的容器,批量啓動新的容器。你可使用--batch-size標誌來控制批處理的大小。此外,你還能夠指定批更新之間的暫停時間間隔(--interval),使用足夠大的時間間隔來驗證新容器的行爲是否按照預期運行,而且整體而言,服務是健康的。在默認狀況下,舊的容器終止後,新的容器會在它們的位置上啓動。或者你能夠在rancher-compose.yml中設置start_first標誌,告訴Rancher在啓動新容器以前先中止舊容器。

若是對當前的更新不滿意想要回滾,可使用回滾標誌來完成回滾。或者你想要繼續進行更新,只需告訴rancher指定confirm-update標誌完成更新便可。你也能夠在原始的up命令中指定confirm-update標誌一步完成這些操做。你還能夠在RancherUI執行更新,從服務菜單(下圖所示)中選擇「upgrade」。

就地更新很是簡單,不須要額外的資源來管理多個堆棧。然而,這種生產方式是存在缺點的。首先,對回滾更新進行細粒度控制大多很困難,就是說在故障發生的狀況下它們每每是難以估計的。例如,處理部分故障和滾動更新會變得很是混亂。你須要知道在哪些節點上部署了更改,哪些沒能部署,還有哪些仍在運行以前的版本。其次,你還須要保證全部的更新不只是向後兼容,還能向前兼容,由於舊版本和新版本都是須要在相同的環境中同時運行的。最後,根據使用的狀況,就地更新可能不實用。好比,若是老的客戶端須要繼續使用舊環境,而新的客戶端須要向前滾。在這種狀況下,使用咱們今天要列出的方法分離客戶端會更加容易。

藍綠部署

就地更新的一個問題是缺乏可預測性。爲了克服這一問題,另外一個部署策略是針對應用程序使用兩個並行堆棧:一個處於活躍狀態,另外一個處於待機狀態。要運行新版本,部署應用程序的最新版本到待機堆棧。當驗證到新版本須要工做,將會從活動堆棧切換流量到備用堆棧上。這時,先前活躍的堆棧稱爲備用堆棧,反之亦然。該策略容許驗證已經部署的代碼、快速回滾(切換備用和從新激活),並還能夠在須要時擴展兩個堆棧的併發操做。這種策略一般被稱爲藍綠部署。用咱們的示例應用程序完成這樣的部署,能夠簡單地在Rancher中建立兩個堆棧:go-auth-blue和go-auth-green。此外,咱們假設數據庫不是這些堆棧的一部分,而是獨立管理的。每一個堆棧都會運行goauth和auth-lb服務。若是假設go-auth-green堆棧式活躍的,要執行更新,咱們要作的就是將最新版本部署到藍色堆棧中,執行驗證並將流量切換到它這。

流量切換

有兩個方法可用於執行流量切換,更改DNS記錄來指向新堆棧,或者使用代理或負載均衡器,將流量路由到活動堆棧。下面咱們會詳細介紹這兩個方法。

記錄更新

一個簡單的方法是更新DNS記錄指向活動堆棧。這種方法的一個優勢是,咱們可使用加權DNS記錄將流量慢慢轉換到新版本中。這也是執行canary releases的簡單方法,對安全地在實時環境中進行更新或者作A/B測試很是有用。例如,咱們能夠將實驗性的功能更部署到本身的功能堆棧(或活動堆棧),而後更新DNS,僅將一小部分流量轉發到新版本。若是新更新出現問題,咱們能夠逆轉DNS記錄回滾回來。此外,他比將全部流量從一個堆棧切換到另外一個堆棧要安全得多,由於這樣會覆蓋掉新的堆棧。雖然簡單,若是你但願全部流量能一次切換到新版本,DNS記錄更新就把u 事最簡潔的方法。根據DNS客戶端不一樣,這些更改可能須要很長時間才能傳播,從而致使和舊版本之間的大量通訊,而不是直接了斷切換。

使用反向代理

使用代理或負載均衡器,只須要將其更新成指向新堆棧就能夠一次切換整個流量。這種方法在各類場景下都很是有用,例如非向後兼容的更新。要使用Rancher完成這一操做,咱們首先要建立一個僅包含負載均衡器的堆棧。

接着,咱們爲負載均衡器指定一個端口,配置SSL並從下拉菜單中選擇活動堆棧的負載均衡器做爲target service來完成建立。本質上來講,咱們將負載放到了負載均衡器上,它會在以後將流量路由到實際的服務節點。藉助外部負載均衡器,你不須要更新每一個版本的DNS記錄。相反,你能夠簡單地更新外部負載均衡器指向已更新的堆棧。

總 結

在本章中,咱們介紹瞭如何建立一個持續部署流水線,能夠將咱們的示例應用程序放在集成環境中。咱們還研究瞭如何集成DNS和HTTPs支持來建立一個用戶可以進行集成的更加安全可用的環境。在後續的工做中,咱們着眼於運行中的生產環境。部署到生產環境會帶來一些列的挑戰,咱們但願部署是知足負載,而且有不多停機時間的(理想下爲零)。此外,生產環境也面臨着挑戰,由於它們必須能向外擴展以知足負載,同時還要減小控制成本。最後,爲了提供自動故障轉移以及高可用性,咱們對DNS管理進行了更全面地研究。咱們還將研究生產中Docker環境的操做管理以及不一樣類型的工做負載,好比state-full鏈接服務。

結 論

這一系列文章介紹了使用容器實現完整的CI/CD流水線的幾種方法。咱們嘗試涵蓋常見的使用案例,提供詳細的示例,而且分享了咱們在Web服務公司工做多年的DevOps中學到的一些最佳實踐。將來咱們還會繼續將內容進一步深化,發佈一份子妹篇,深刻介紹如何在生產中使用容器運行服務,敬請保持關注!

相關文章
相關標籤/搜索