已收藏,可在 我的資料庫(kù) 中查看
關(guān)注作者
您可能還需要
獨(dú)立站
國(guó)潮領(lǐng)航?破浪出海
立即報(bào)名
加入社群
獨(dú)立站近期活動(dòng)

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

今天我們介紹的主題是 “企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路”,也就是我們 KubeSphere DevOps 的成長(zhǎng)之路。

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

今天我們介紹的主題是 “企業(yè)級(jí)容器 CI/CD 的進(jìn)階之”,也就是我們 KubeSphere DevOps 的成長(zhǎng)之路。

我這里介紹將分為以下幾部分,我們 KubeSphere DevOps 主要分為兩個(gè)重要功能,一是 DevOps 流水線,二是 S2I/B2I。

首先,我們介紹我們?yōu)槭裁词褂?Jenkins 作為我們流水線的底層引擎,當(dāng)我們選擇好 Jenkins 后,我們?nèi)绾伟阉?KubeSphere 融合在一起,打造我們 KubeSphere CI/CD 流水線。同時(shí),我們后面使用復(fù)雜的方案,可能有些用戶(hù)不太接受,我們提出更加簡(jiǎn)單易用的 S2I/B2I。我們?cè)谏暇€后有很多用戶(hù),這些用戶(hù)給我們做了很多反饋,我們踩了很多的坑。這里講講我們具體優(yōu)化的點(diǎn),以及我們未來(lái)的簡(jiǎn)單規(guī)劃。

1、為什么我們選擇 Jenkins

首先,為什么我們選擇 Jenkins 作為我們 CI/CD 流水線?

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

先看看企業(yè)里的 CI/CD 流程。KubeSphere 最初的目標(biāo)用戶(hù)是比較大型的用戶(hù),像大型的銀行業(yè)、保險(xiǎn)業(yè),面對(duì)的用戶(hù) DevOps 流程很復(fù)雜。我們可以看到在圖中,這里涉及很多人員、流程復(fù)雜、審批等一系列的需求。同時(shí),在大型企業(yè)當(dāng)中已經(jīng)有一些 CI/CD 工具時(shí),已經(jīng)有 CI/CD 自己的流程,我們希望通過(guò) KubeSphere 的流水線把傳統(tǒng)用上的工具融合進(jìn)來(lái),同時(shí)也能為它提供容器平臺(tái)之上,借助 KubeSphere 助力業(yè)務(wù)快速上線的能力。

在這些客戶(hù)當(dāng)中,一些企業(yè)已經(jīng)在使用一些 DevOps 工具做測(cè)試、進(jìn)度管理等,但是他不知道如何在容器上做發(fā)布,我們希望能夠通過(guò) KubeSphere 的 DevOps 功能對(duì)整個(gè)流程進(jìn)行把控。

于是我們開(kāi)始做技術(shù)選型。在做技術(shù)選型時(shí),這是我從國(guó)外的網(wǎng)站 StackShare 拿到的一份數(shù)據(jù),我選了一個(gè)我認(rèn)為比較主流的 CI/CD 引擎。這里是市場(chǎng)份額的數(shù)據(jù),可以明顯看到 Jenkins 的用戶(hù)、相關(guān)問(wèn)題、投票都非常多。比如 Drone.io 和 GitLab CI 是幾百,到了 Jenkins 是幾萬(wàn)。

那用戶(hù)為什么會(huì)選擇 Jenkins 呢?

這也是我們選擇 Jenkins 作為我們流水線引擎非常重要依據(jù),這里可以看到 Drone.io 和 GitLab CI,用戶(hù)喜歡他們的點(diǎn)是安裝簡(jiǎn)單、配置簡(jiǎn)單,和 Docker 結(jié)合很簡(jiǎn)單等一系列的東西。當(dāng)我們看 Jenkins 時(shí),首先是開(kāi)源和可以私有化部署。

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

更重要的是使用 Jenkins 我們可以和許多 CI/CD 工具很容易結(jié)合在一起,完成打包、部署一系列的流程。同時(shí) Jenkins 有很多插件、文檔,他們有成熟且活躍的社區(qū),我們可以借助社區(qū)的力量,來(lái)完成我們的 DevOps 功能。

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

這是使用 Jenkins 的代表企業(yè),可以從代表企業(yè)看出,我們不了解這些企業(yè)具體是做什么的,只有 Jenkins 的代表企業(yè)我看的比較眼熟,比如 Facebook、Netflix、ebay 等這種比較出名的國(guó)外大型企業(yè),說(shuō)明他們企業(yè)內(nèi)部的復(fù)雜流水,使用 Jenkins 是可以滿(mǎn)足的。

于是我們選擇了 Jenkins 作為我們 CI/CD 底層流水線引擎。這個(gè)方案是用戶(hù)喜歡的方案,已經(jīng)有很多用戶(hù)在使用。它有活躍、成熟的社區(qū),我們可以很容易借助社區(qū)的力量完成我們的產(chǎn)品。同時(shí)很容易跟企業(yè)已有的 CI/CD 工具進(jìn)行集成。它有非常可靠的插件體系,我們想完成 Jenkins 和我們 KubeSphere 進(jìn)行融合,很有可能會(huì)使用插件擴(kuò)展的功能,如果它沒(méi)有可靠的擴(kuò)展開(kāi)發(fā)的體系,可能我們集成起來(lái)會(huì)比較困難。

當(dāng)我們選擇 Jenkins 作為我們 CI/CD 的引擎后,下一步是如何將 Jenkins 融入到我們 KubeSphere CI/CD 流水線里。

2、打造 KubeSphere CI/CD Pipeline

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

KubeSphere CI/CD 流水線早期時(shí)有一系列的需求,我簡(jiǎn)單列出來(lái)。首先是多租戶(hù)隔離的需求,最初一些大企業(yè)用戶(hù)有很多部門(mén)、分公司,他們希望用我們 KubeSphere 作為容器平臺(tái),最后是多租戶(hù)管理,方便他們進(jìn)行管理。我們是一個(gè)容器平臺(tái)我選擇 K8s 作為我們底層容器的引擎。我們希望在 K8s 上,Jenkins 可以充分地釋放、利用 K8s 自己的能力,并且我們要把前面提到的企業(yè)中復(fù)雜的開(kāi)發(fā)、測(cè)試、構(gòu)建、部署一整套流程。同時(shí)我們要支持多種方式的流水線,我和代碼倉(cāng)庫(kù)綁定還是不綁定,滿(mǎn)足企業(yè)的復(fù)雜需求。有一些用戶(hù)沒(méi)用過(guò) Jenkins,他搭建流水線比較困難,我們希望通過(guò)圖形化編輯的手段簡(jiǎn)化他們流水線搭建的過(guò)程,使用起來(lái)更加簡(jiǎn)單。

首先,我介紹一下我們?nèi)绾螌?shí)現(xiàn)多租戶(hù)。在多租戶(hù)里主要分為兩部分,一是認(rèn)證部分,二是鑒權(quán)部分。在認(rèn)證部分比較簡(jiǎn)單,我們 KubeSphere 本身內(nèi)置 Ldap 進(jìn)行用戶(hù)的存儲(chǔ)。Jenkins 本身有對(duì)接 Ldap 方案的,我們讓 Jenkins 直接對(duì)接 Ldap 里。這時(shí)候我們完成用戶(hù)的打通,這時(shí)候會(huì)有一個(gè)問(wèn)題,用戶(hù)打通后,Requset 無(wú)法打通。KubeSphere 不知道 Ldap 里的用戶(hù)的密碼是什么,因此在 KubeSphere 想要以用戶(hù)身份對(duì) Jenkins 做操作時(shí)也比較困難了。

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

如何完成認(rèn)證?

在認(rèn)證里,我當(dāng)時(shí)做了一些調(diào)研,我發(fā)現(xiàn) Jenkins 擴(kuò)展果然很豐富,左邊是 Jenkins 一張官方的圖,介紹 Jenkins 鑒權(quán)過(guò)程是怎樣的。他分為 Web UI 和 Rest API 兩部分,在 Rest API 里面有一個(gè)叫 Basic Header 驗(yàn)證器,我看到這個(gè)驗(yàn)證器有真正的密碼驗(yàn)證器、API Token 驗(yàn)證器,我想這是不是可擴(kuò)展的密碼,我研究了一下發(fā)現(xiàn)它真的可以擴(kuò)展,我們自己寫(xiě)了一個(gè) KubeSphere Token 的驗(yàn)證器,幫用戶(hù)使用 KubeSphere Token 請(qǐng)求 Rest API 時(shí),這個(gè)請(qǐng)求最后會(huì)轉(zhuǎn)發(fā)到我們 KubeSphere IAM 請(qǐng)求驗(yàn)證的過(guò)程。

這時(shí)候我們的認(rèn)證完成了,我們的用戶(hù)是打通的,并且我們可以使用統(tǒng)一的 API Token 進(jìn)行驗(yàn)證,訪問(wèn) Jenkins 的 API。

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

接下來(lái)是另一部分鑒權(quán)。

這一部分里,我先介紹 Jenkins 的 API 和 K8s API 的區(qū)別。上面是 K8s API 獲取的信息,下面是 Jenkins 的 API。K8s 的 API 我們可以非常容易發(fā)現(xiàn)它非常結(jié)構(gòu)化,它有自己的動(dòng)作、API group,它具體請(qǐng)求的 Resource 是什么,它的名稱(chēng)是什么。

我們?cè)賮?lái)看 Jenkins 的 API,Jenkins 的 API 看起來(lái)是一堆不知道是什么的東西,Jenkins 在設(shè)計(jì)之初不是基于 API 的服務(wù),這導(dǎo)致它的一些差距。我們可以看 K8s 的界面方式,K8s 的方式是基于 Rest API 的路徑和動(dòng)作進(jìn)行鑒權(quán)的。但在 Jenkins 當(dāng)中,從一些代碼里內(nèi)嵌檢查語(yǔ)句,看這個(gè)人是不是有管理權(quán)限或者讀權(quán)限等。這說(shuō)明我們很難借助 K8s 的能力把它鑒權(quán)。

前面提到 K8s 的鑒權(quán)有很多問(wèn)題,我們后面進(jìn)行改造。最初我們希望借助 K8s 的能力,我們?cè)谙?DevOps 能否借助 Jenkins 的能力先完成鑒權(quán)的方法。于是我們使用了另一個(gè)方案,這可以理解為是暫時(shí)的方案。最后我們會(huì)通過(guò) KubeSphere 內(nèi)置鑒權(quán)可擴(kuò)展來(lái)完成這部分工作。

這時(shí)候用戶(hù)在請(qǐng)求 KubeSphere API 時(shí)分為兩部分,一部分是和權(quán)限操作相關(guān)的。比如我要為 DevOps 工程添加用戶(hù),分類(lèi)、角色等。另一部分是非權(quán)限相關(guān)的,當(dāng) K8s API 收到請(qǐng)求后,權(quán)限 API 轉(zhuǎn)發(fā)為 API Server,我們會(huì)在 API Server 里同步往 Jenkins 寫(xiě)入一些權(quán)限規(guī)則,滿(mǎn)足權(quán)限的匹配。當(dāng)你們?cè)L問(wèn)其他 API 時(shí)可以直接發(fā)到 Jenkins,借助原有 Jenkins 的鑒權(quán)能力和 API 的能力,使用這種方式有一個(gè)優(yōu)點(diǎn),用戶(hù)仍然可以使用 Jenkins 的頁(yè)面。我們的鑒權(quán)、認(rèn)證是可以打通的,并且我們不需要對(duì) Jenkins 的 API 進(jìn)行大量的包裝,因?yàn)樗灰?guī)則,我們包裝起來(lái)非常困難。我們?cè)谥蟮陌姹局幸矊?duì) API 進(jìn)行了包裝。這時(shí)候我們完成了認(rèn)證和鑒權(quán)的部分,可以滿(mǎn)足多租戶(hù)的需求。

關(guān)于如何充分釋放 K8s 能力,最初我們使用 Jenkins 設(shè)計(jì)中的 Kubernetes Plugin 的方案,我們做了配置上的調(diào)整,我們默認(rèn)全部使用 Kubernetes 的 Agent,自動(dòng)動(dòng)態(tài)創(chuàng)建,這樣比較節(jié)省資源,也可以充分釋放 K8s 的能力。

這時(shí)候有一個(gè)問(wèn)題,用戶(hù)寫(xiě) Jenkinsfile 需要 Agent 的定義。這對(duì)不熟悉 K8s 的人來(lái)說(shuō)是非常困難的,他要先學(xué)會(huì)怎么做 Docker 鏡像,再學(xué)會(huì)怎么寫(xiě) K8s yaml 文件,再運(yùn)行。于是我們內(nèi)置了一些用戶(hù)可能比較常用的 Agent 類(lèi)型,比如 Maven Agent、NodeJs Agent 同時(shí)支持用戶(hù)自己擴(kuò)展 Agent 類(lèi)型,滿(mǎn)足他自己獨(dú)特的需求。通過(guò)這種方式,我們充分釋放 K8s 的能力。

另一部分是 In SCM 流水線的實(shí)現(xiàn)方式,我們的流水線一般分為兩種,一種是通過(guò)代碼操作綁定的,另一種是通過(guò)代碼操作不綁定的。我調(diào)研了很多方案,很多廠商做的和代碼分支綁定,我個(gè)人認(rèn)為是比較假的方案。我綁定了這個(gè)流水線到某一個(gè)代碼倉(cāng)庫(kù)的某一個(gè)分支上,我不支持自己發(fā)現(xiàn)分支,發(fā)現(xiàn)它的 PR,自動(dòng)進(jìn)行 CI/CD。我實(shí)際上只能為一個(gè)分支執(zhí)行流水線的過(guò)程。

這會(huì)有一些問(wèn)題,我們?cè)陂_(kāi)發(fā)過(guò)程中很容易創(chuàng)建新的分支、新的 PR,這時(shí)候 DevOps 是沒(méi)有運(yùn)行的。只有將提交代碼到 Master 分支或者其他的已經(jīng)設(shè)置了流水線的分支上才會(huì),不利于企業(yè) DevOps 的發(fā)展。

于是我們當(dāng)時(shí)調(diào)研想著借助 Jenkins 的生態(tài)來(lái)提供分支發(fā)現(xiàn)這樣的功能。Jenkins 自己有支持 Jenkinsfile 發(fā)現(xiàn)的功能,它可以支持多種廠商的 SCM,有 Git、GitHub、GitLab、Bitbucket 等,當(dāng)我們選擇這種方案時(shí),同時(shí)還擁有了另一個(gè)能力,可以兼容傳統(tǒng)用戶(hù)的 Jenkinsfile,我們不需要自己定義一套流水線的編寫(xiě)規(guī)范。如果是傳統(tǒng)的 Jenkins 用戶(hù),他們想遷移到 KubeSphere 的流水線上來(lái)也會(huì)變得更加簡(jiǎn)單。

我們需要圖形化編輯流水線的能力,在了解這個(gè)功能時(shí)候,我們不得不提到 Jenkinsfile 具體內(nèi)容。Jenkinsfile 有兩種類(lèi)型:腳本類(lèi)型的 Jenkinsfile 和聲明式定義的 Jenkinsfile。

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

這是我舉的兩個(gè)簡(jiǎn)單的例子,想說(shuō)明他倆有什么不同。左邊的 Jenkinsfile 里面有變量定義、有 for 循環(huán),一看感覺(jué)我在寫(xiě)代碼,不是在寫(xiě)一個(gè)流水線的定義。這個(gè)方案有一個(gè)缺點(diǎn),學(xué)習(xí)曲線非常陡峭。我要先學(xué)會(huì) Groovy 語(yǔ)言,再學(xué)習(xí) Jenkins 上的 Groovy 語(yǔ)言。顯然對(duì)于我們前端的同學(xué)來(lái)說(shuō)是非常難以解析的,這不是結(jié)構(gòu)化的定義,我們要做圖形化的編輯不能用這種方案。

另一種是聲明式流水線,我們可以來(lái)看看聲明式的流水線定義:它有一個(gè)流水線,在流水線有很多 Stage,Stage 下面可能有具體的 Step 執(zhí)行一些命令。這種方案曲線相對(duì)平滑,他們的功能相對(duì)有限,但足以滿(mǎn)足企業(yè)里復(fù)雜的 CI/CD 的需求。這時(shí)候可以進(jìn)行結(jié)構(gòu)化的解析,我們后端提供結(jié)構(gòu)化解析的 API,前端同學(xué)拿到結(jié)構(gòu)化解析的數(shù)據(jù),再進(jìn)行流水線的展示。于是我們得到 KubeSphere 流水線的編輯頁(yè)面,在編輯頁(yè)面里我們可以很順利添加順序的 Stage 或者運(yùn)行的 Stage,添加一些具體的 Step,比如我們要拉代碼、執(zhí)行命令等。

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

經(jīng)過(guò)這個(gè)階段,我們可以滿(mǎn)足企業(yè)用戶(hù)的復(fù)雜 DevOps 流程,讓他們?cè)?K8s 之上進(jìn)行 DevOps 的方案,讓企業(yè)擁有更快的上線時(shí)間、更高的部署頻率、更快的修復(fù)時(shí)間和更短的恢復(fù)時(shí)間。

當(dāng)我們發(fā)布了復(fù)雜流水線的功能后,我們?cè)谏鐓^(qū)和其他用戶(hù)收到很多反饋。使用 Jenkins 的方案,它的流程定義是相對(duì)復(fù)雜的,我要定義我的構(gòu)建、測(cè)試、部署等一系列的階段。而有些企業(yè)就是想試一試自己能否快速將自己的應(yīng)用部署到 K8s 之上,復(fù)雜的流水線對(duì)這種用戶(hù)來(lái)說(shuō)是不適用的,于是我們提供了更加簡(jiǎn)單易用的 S2I/B2I 功能。

3、更加簡(jiǎn)單易用的 S2i

首先,S2I 是什么?S2I 不是我們創(chuàng)造的一個(gè)概念,它是開(kāi)源社區(qū)的一個(gè)命令行工具。這個(gè)工具用來(lái)做什么?讓用戶(hù)在不需要了解 Docker 情況下可以構(gòu)建自己的應(yīng)用鏡像。那 S2I 和傳統(tǒng)的 Docker 構(gòu)建有什么區(qū)別呢?在我們使用傳統(tǒng) Docker 構(gòu)建的時(shí)候是這樣一個(gè)過(guò)程,我們有很多應(yīng)用,每個(gè)應(yīng)用都可以有自己 Dockerfile,通過(guò) Dockerfile 可以得到應(yīng)用的鏡像。使用 S2I 后,我們的流程變成了什么?我們每個(gè)應(yīng)用可以通過(guò)同一個(gè) S2I 的 Builder Image 來(lái)構(gòu)建自己的應(yīng)用鏡像,Builder Image 也是 Docker 鏡像。

用戶(hù)只需要選擇 Image 就可以得到自己應(yīng)用的鏡像,這時(shí)候用戶(hù)構(gòu)建 Docker 的過(guò)程變得比較簡(jiǎn)單,因?yàn)槲覀冎恍枰褂?S2I Image 進(jìn)行簡(jiǎn)單的選擇,并且在我們企業(yè)用戶(hù)中,維護(hù)、管理起來(lái)更加方便。

比如我收到安全警報(bào)說(shuō)某某版本有一個(gè)安全漏洞,我們要進(jìn)行升級(jí)。企業(yè)當(dāng)中有很多應(yīng)用,但其實(shí)他們的 Dockerfile 都很類(lèi)似,我要通知他們一個(gè)個(gè)進(jìn)行升級(jí)。而當(dāng)我們使用 S2I 時(shí),我們只需要找專(zhuān)門(mén)的人升級(jí) Image,告訴每個(gè)應(yīng)用負(fù)責(zé)的人員觸發(fā)構(gòu)建就升級(jí)完成了,可以一步上線。管理復(fù)雜度也減小了。

使用 S2I 后,可以簡(jiǎn)化開(kāi)發(fā)者的工作方式。業(yè)務(wù)開(kāi)發(fā)人員只需要在自己的 IDE 里寫(xiě)代碼,提交代碼到 Git 倉(cāng)庫(kù),觸發(fā)構(gòu)建。通過(guò)構(gòu)建器鏡像構(gòu)建出他自己的應(yīng)用鏡像,就可以把這個(gè)鏡像推送到 Docker 的鏡像倉(cāng)庫(kù),并且進(jìn)行部署等一系列的過(guò)程。

前面介紹了使用 S2I 開(kāi)發(fā)者的流程是怎樣的。S2I 很好,但它只是一個(gè)命令行工具,在企業(yè)中使用,大家不是特別喜歡這種方式。因?yàn)橐獙W(xué)習(xí)它的命令,交互起來(lái)沒(méi)那么輕松。于是我們想著把 S2I 這個(gè)不錯(cuò)的工具融入到我們 KubeSphere Console 或者 KubeSphere 里。讓它成為我們功能模塊的一部分。

這里不得不提到 CRD,CRD 是擴(kuò)展 K8s 的方式,叫特殊資源定義。使用這個(gè)方式我們可以輕松得到和 K8s 一樣的聲明式 API,我們模塊之間是松耦合的。K8s 底層提供了 List-Watch 機(jī)制,使用這種方式我們可以快速響應(yīng)用戶(hù) S2I 的需求。

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

于是我們 KubeSphere 里,S2I 架構(gòu)變成這樣。左邊是我們的用戶(hù),右邊是我們的具體細(xì)節(jié)。用戶(hù)可以通過(guò) Kubectl 或者其他工具,比如 KubeSphere Console,或者直接請(qǐng)求我們的 API。這個(gè) API Server 是 K8s 的 API Server,K8s 的 API Server 在收到用戶(hù)請(qǐng)求時(shí),會(huì)把數(shù)據(jù)存儲(chǔ)到 etcd 里,會(huì)通知 S2I Operator 完成一系列的任務(wù)操作。

在這里我們主要定義了三個(gè) CRD,第一個(gè)是 S2I Template,有 Java、Golang 和 Binary。在填寫(xiě)很多信息時(shí)不想填寫(xiě)重復(fù)的信息,他想要選擇一個(gè)模板。比如我創(chuàng)建流水線時(shí),我是 Java 語(yǔ)言的,S2I Template 就是這樣。S2i Builder 類(lèi)似我們的流水線定義,當(dāng)我們選擇好要使用語(yǔ)言,這時(shí)候只需要選擇代碼倉(cāng)庫(kù)或者上傳制品,加上填寫(xiě)我們要制作的鏡像或者推送的鏡像名稱(chēng),這時(shí)候我們定義好一個(gè)流水線。我們可以觸發(fā),每次觸發(fā)都會(huì)生出一個(gè) S2I Run,在 S2I Run 里我們具體執(zhí)行 S2I 的過(guò)程,完成構(gòu)建鏡像、推送鏡像,幫忙把這一系列的信息上報(bào)到 API Server 進(jìn)行匯總展示。

于是我們簡(jiǎn)單的 CI/CD 只需要填寫(xiě)簡(jiǎn)單的表單,我們選擇構(gòu)建環(huán)境是什么,填寫(xiě)鏡像、倉(cāng)庫(kù)地址、名稱(chēng),就可以完成了。通過(guò)這種方式,在我們 KubeSphere Console 上,可以從源代碼一鍵直達(dá)服務(wù),我們不是只有構(gòu)建鏡像的過(guò)程,我還會(huì)自動(dòng)為你創(chuàng)建 Deployment 以及 Service 等資源。用戶(hù)通過(guò)填寫(xiě)一個(gè)表單可以一鍵啟動(dòng)自己的服務(wù)。

當(dāng)然,用戶(hù)可能有一些團(tuán)隊(duì)協(xié)作需求。我們會(huì)在平臺(tái)展示構(gòu)建數(shù)據(jù)、統(tǒng)計(jì),方便團(tuán)隊(duì)協(xié)作。比如我看到他今天下午構(gòu)建了一次等。這是我們 KubeSphere S2I 2.1 版本后有一個(gè)單獨(dú)的頁(yè)面展示其狀態(tài),用戶(hù)使用起來(lái)是非常簡(jiǎn)單的。通過(guò)簡(jiǎn)單的 S2I/B2I,我們?yōu)榱俗層脩?hù)有更快的上線時(shí)間、更高的頻率、更快的修復(fù)時(shí)間和更短的恢復(fù)時(shí)間。

4、持續(xù)優(yōu)化,讓 CI/CD 更加迅速

我們 DevOps 流水線和 S2I/B2I 可以滿(mǎn)足絕大多數(shù)用戶(hù)的需求,包括復(fù)雜的 CI/CD 場(chǎng)景,還有簡(jiǎn)單的 CI/CD 場(chǎng)景。我們還會(huì)有一些優(yōu)化點(diǎn),這是我們 KubeSphere 中的頁(yè)面。

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

如果你是 KubeSphere 早期流水線的用戶(hù),相信你一定見(jiàn)過(guò)這個(gè)頁(yè)面。這個(gè)地方是流水線在初始化,初始化時(shí)間很長(zhǎng),這困擾了我們團(tuán)隊(duì)很久,也困擾我們的客戶(hù)、用戶(hù)很久。于是我們?cè)?Jenkins 社區(qū)中進(jìn)行了一些研究。

這里提到 Jenkins EMA 算法,這個(gè)算法你們不需要了解它是什么,我簡(jiǎn)單介紹它的功能是什么。Jenkins 誕生的年代非常早,大概有十幾二十年的時(shí)間,這個(gè) EMA 算法其實(shí)是 Jenkins 內(nèi)部的 Agent 調(diào)度算法,在這個(gè)調(diào)度算法里當(dāng)時(shí)的目標(biāo)滿(mǎn)足一個(gè)目標(biāo),不要讓我們 Agent 發(fā)生頻繁的變化,比如你要擴(kuò)容,我判斷是否有任務(wù)運(yùn)行完了,如果有任務(wù)要運(yùn)行完了,要等一等。因?yàn)樽鰟?dòng)態(tài)的擴(kuò)容、縮容非常消耗資源,也很慢。

但 EMA 算法不適合這個(gè)時(shí)代,我們知道 K8s 的能力是瞬間啟動(dòng),啟動(dòng)完后瞬間執(zhí)行。于是我進(jìn)行了一系列的調(diào)研,發(fā)現(xiàn)默認(rèn)的調(diào)度算法是可以進(jìn)行擴(kuò)展的。我改變了 Kubernetes Agent 的調(diào)度算法,現(xiàn)在已經(jīng)貢獻(xiàn)給社區(qū)。

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

最后變成右邊的樣子,策略非常簡(jiǎn)單,沒(méi)有任何延遲的調(diào)度策略。如果有一個(gè)流水線來(lái)了,我們立馬對(duì)它啟動(dòng)一個(gè) Agent 執(zhí)行流水線。我們進(jìn)行測(cè)試會(huì)發(fā)現(xiàn)原來(lái)初始化時(shí)間等待有幾十秒、幾分鐘甚至幾十分鐘。通過(guò)優(yōu)化可以讓調(diào)度時(shí)間變成毫秒級(jí),也就是說(shuō)我收到一個(gè)任務(wù)后,立馬可以啟動(dòng),執(zhí)行我的任務(wù)。

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

在這張圖是 Jenkins 的監(jiān)控圖,灰色線指的是等待構(gòu)建任務(wù)的數(shù)量,紅色線指的是忙碌 Agent 數(shù)量??梢钥吹交疑€剛剛開(kāi)始后,紅色的線會(huì)迅速升起來(lái),完成 CI/CD 的任務(wù)。我們當(dāng)時(shí)做了 Master 節(jié)點(diǎn)的監(jiān)控,可以從這個(gè)時(shí)間看出來(lái),我們當(dāng)時(shí)測(cè)試了 100 個(gè)流水線,大概完成時(shí)間,同時(shí)完成需要 4 分鐘。我們這里看到 Jenkins Master CPU 用量當(dāng)時(shí)打滿(mǎn)了。如果我們對(duì) Master 節(jié)點(diǎn)進(jìn)行擴(kuò)容,或者對(duì) K8s 環(huán)境進(jìn)行擴(kuò)容,我們可能可以跑得更快。

這一部分是我們 Jenkins Agent 的擴(kuò)展。當(dāng) Agent 啟動(dòng)后有一個(gè)問(wèn)題,我們?cè)趺醋屃魉€跑的更快?這時(shí)候提到用戶(hù)的場(chǎng)景,用戶(hù)很多是 Java 的開(kāi)發(fā)者,他們會(huì)在企業(yè)的環(huán)境搭一個(gè) Nexus 作為自己的制品管理和依賴(lài)緩存。

他們當(dāng)時(shí)使用這種方案,在我們 Jenkinsfile 里配置使用 Nexus,看起來(lái)是沒(méi)問(wèn)題的,實(shí)際上真的沒(méi)有問(wèn)題嗎?這時(shí)不得不說(shuō)到開(kāi)發(fā)高峰期,當(dāng)開(kāi)發(fā)高峰期來(lái)的時(shí)候,一個(gè)下午開(kāi)發(fā)人員最多提交代碼有幾十個(gè)或者上百人同時(shí)提交代碼,會(huì)啟動(dòng)非常多的 Agent。因?yàn)?Agent 每次會(huì)銷(xiāo)毀,所以每次運(yùn)行流水線的時(shí)候,Agent 都需要從 Nexus 重新拉緩存,這時(shí)候我們發(fā)現(xiàn) Agent 宿主機(jī)的硬盤(pán) I/O 跑滿(mǎn)了,并且 Nexus 出口帶寬也跑滿(mǎn)了。Nexus 還會(huì)出現(xiàn)部分的連接失敗,它的流水線雖然啟動(dòng)很快,但運(yùn)行不夠快。

于是我們?cè)?2.1 版本中添加了另一個(gè)功能,基于硬盤(pán)的依賴(lài)緩存。之前我們使用 Nexus 緩存中心倉(cāng)庫(kù),在這個(gè)版本中我們從節(jié)點(diǎn)硬盤(pán)中加上緩存,當(dāng)沒(méi)有依賴(lài)的時(shí)候,我會(huì)先檢查節(jié)點(diǎn)的上有沒(méi)有依賴(lài),如果沒(méi)有,我會(huì)去 Nexus,Nexus 沒(méi)有再去中心倉(cāng)庫(kù)。使用這種方式我們硬盤(pán) I/O 和 Nexus 出口帶寬已經(jīng)降下來(lái),可以避免每次重新拉緩存,讓我們 CI/CD 跑得更迅速。

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

這是我們的構(gòu)建,主要針對(duì)緩存的對(duì)比??梢钥吹竭@里有兩個(gè)測(cè)試用例,一個(gè)是 Java 的,另一個(gè)是 Node.js,二者也是開(kāi)源的。通過(guò)用它滿(mǎn)足依賴(lài),我們速度提升,Java 可以做到 9 倍,Node.js 差不多有 5 倍之多。當(dāng)我們的運(yùn)行速度、調(diào)度速度很快的時(shí)候,企業(yè)的發(fā)布速度也會(huì)變得很快。

當(dāng)然,我介紹了 KubeSphere DevOps 優(yōu)化的兩個(gè)點(diǎn),我們優(yōu)化了很多地方,包括前面提到的用戶(hù)優(yōu)化、無(wú)感知緩存以及我們支持 S2i Runtime Image 等,還有 DevOps 動(dòng)態(tài) PVC,我們做的優(yōu)化是想讓用戶(hù)使用得更方便,讓他擁有更快上線時(shí)間、更高的部署頻率、更快的修復(fù)時(shí)間和更短的恢復(fù)時(shí)間。

針對(duì)前兩部分,我的 CI/CD 可以跑得很快,并且滿(mǎn)足用戶(hù)的任何需求。其實(shí)我們還是有很多未來(lái)的規(guī)劃,在這里我只是展示了未來(lái)規(guī)劃的設(shè)計(jì)圖。

技術(shù)分享|企業(yè)級(jí)容器 CI/CD 的進(jìn)階之路

這是我們?cè)?3.0 計(jì)劃做的目標(biāo)和創(chuàng)建,我們 Jenkinsfile 定義起來(lái)相對(duì)比較復(fù)雜,我們希望用戶(hù)可以通過(guò)選擇語(yǔ)言,選擇自己做什么的方式可以完成自己復(fù)雜的流水線創(chuàng)建,簡(jiǎn)化用戶(hù)的創(chuàng)建過(guò)程。我們也會(huì)支持用戶(hù)的郵件通知等。我這里沒(méi)有列出太多,我希望能夠從社區(qū)的用戶(hù)、社區(qū)貢獻(xiàn)者當(dāng)中得到更多的反饋,包括你可以向我們反饋你想要什么樣的功能,或者你直接給我們提交代碼,讓我們的社區(qū)變得更好。(來(lái)源:青云QingCloud

以上內(nèi)容屬作者個(gè)人觀點(diǎn),不代表雨果網(wǎng)立場(chǎng)!如有侵權(quán),請(qǐng)聯(lián)系我們。

分享到:

--
評(píng)論
最新 熱門(mén) 資訊 資料 專(zhuān)題 服務(wù) 果園 標(biāo)簽 百科 搜索
雨果跨境顧問(wèn)
工具服務(wù)顧問(wèn)-Owen
雨果跨境官方顧問(wèn)

收藏

--

--

分享