国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

容器環(huán)境下的持續(xù)集成最佳實(shí)踐:構(gòu)建基于 Drone + GitFlow + K8s 的云原生語義化

asoren / 815人閱讀

摘要:集成測試完成后,由運(yùn)維同學(xué)從發(fā)起一個(gè)到分支,此時(shí)會(huì)會(huì)運(yùn)行單元測試,構(gòu)建鏡像,并發(fā)布到預(yù)發(fā)布環(huán)境測試人員在預(yù)發(fā)布環(huán)境下再次驗(yàn)證功能,團(tuán)隊(duì)做上線前的其他準(zhǔn)備工作運(yùn)維同學(xué)合并,將為本次發(fā)布的代碼及鏡像自動(dòng)打上版本號并書寫,同時(shí)發(fā)布到生產(chǎn)環(huán)境。

云原生 (Cloud Native) 是伴隨的容器技術(shù)發(fā)展出現(xiàn)的的一個(gè)詞,最早出自 Pivotal 公司(即開發(fā)了 Spring 的公司)的一本技術(shù)小冊子 Migrating to Cloud-Native Application Architectures, 其中定義了云原生應(yīng)用應(yīng)當(dāng)具備的一些特質(zhì),如無狀態(tài)、可持續(xù)交付、微服務(wù)化等。隨后云原生概念被廣為引用,并圍繞這一概念由數(shù)家大廠牽頭,成立了 CNCF 基金會(huì)來推進(jìn)云原生相關(guān)技術(shù)的發(fā)展,主要投資并孵化云原生生態(tài)內(nèi)的若干項(xiàng)目,包括了如 Kubernetes / etcd / CoreDNS 等耳熟能詳?shù)闹匾?xiàng)目。而這張大大的云原生版圖仍然在不斷的擴(kuò)展和完善。

從個(gè)人理解來說,傳統(tǒng)的應(yīng)用由于年代久遠(yuǎn),更多會(huì)考慮單機(jī)部署、進(jìn)程間通信等典型的“單機(jī)問題”,雖然也能工作在容器下,但由于歷史包袱等原因,架構(gòu)上已經(jīng)很難做出大的調(diào)整。而“云原生”的應(yīng)用大都是從一開始就為容器而準(zhǔn)備,很少考慮在單機(jī)環(huán)境下使用,有些甚至無法脫離容器環(huán)境工作;考慮的場景少,從而更輕量,迭代更快。比如 etcd 之于 zookeeper , traefik 之于 nginx 等,相信只要在容器環(huán)境下實(shí)現(xiàn)一次同樣的功能,就能強(qiáng)烈的體會(huì)到云原生應(yīng)用所特有的便捷之處。

在 CNCF 的版圖下,持續(xù)集成與持續(xù)交付(Continuous Integration & Delivery)板塊一直缺少一個(gè)欽定的主角,雖然也不乏 Travis CI、GitLab、Jenkins 這樣的知名項(xiàng)目,但最能給人云原生應(yīng)用感覺的,應(yīng)該還是 Drone 這個(gè)項(xiàng)目,本文將圍繞 Drone 結(jié)合 GitFlow 及 Kubernetes 介紹一些容器環(huán)境下持續(xù)集成、持續(xù)發(fā)布 (CI/CD) 方面的實(shí)踐經(jīng)驗(yàn)。

主流 CI/CD 應(yīng)用對比

之前我也介紹過基于 Travis CI 的一些持續(xù)集成實(shí)踐。后來經(jīng)過一些比較和調(diào)研,最終選擇了 Drone 作為主力 CI 工具。截止本文,團(tuán)隊(duì)已經(jīng)使用 Drone 有 2 年多的時(shí)間,從 v0.6 一路用到現(xiàn)在即將發(fā)布的 v1.0,雖然也踩了不少坑,但總的來說 Drone 還是可以滿足大部分需求,并以不錯(cuò)的勢頭在完善和發(fā)展的。

下面這張表總結(jié)了主流的幾個(gè) CI/CD 應(yīng)用的特點(diǎn)

項(xiàng)目名稱 開發(fā)語言 配置語言 公有云服務(wù) 私有部署 備注
Travis CI Ruby YAML 不支持 公共項(xiàng)目免費(fèi),私有項(xiàng)目 $69/單進(jìn)程, $129/2 進(jìn)程
CircleCI Clojure YAML 不支持 單進(jìn)程免費(fèi),$50/加 1 進(jìn)程
Gitlab CI Ruby YAML 支持 綁定 Gitlab 代碼管理
Jenkins Java Groovy 支持
Drone Go YAML 支持 Cloud 版本不支持私有項(xiàng)目,自建版本無此限制

Travis CI 和 CircleCI 是目前占有率最高的兩個(gè)公有云 CI,易用性上相差無幾,只是收費(fèi)方式有差異。由于不支持私有部署,如果并行的任務(wù)量一大,按進(jìn)程收費(fèi)其實(shí)并不劃算;而且由于服務(wù)器位置的原因,如果推送鏡像到國內(nèi),速度很不理想。

Gitlab CI 雖然好用,但和 Gitlab 是深度綁定的,我們的代碼托管在 Github,整體遷移代碼庫的成本太大,放棄。

Jenkins 作為老牌勁旅,也是目前市場占有率最高的 CI,幾乎可以覆蓋所有 CI 的使用場景,由于使用 Java 編寫,配置文件使用 Groovy 語法,非常適合 Java 為主語言的團(tuán)隊(duì)。Jenkins 顯然是可以滿足我們需要的,只是團(tuán)隊(duì)并非 Java 為主,又已經(jīng)習(xí)慣了使用 YAML 書寫 CI 配置,抱著嘗鮮的心態(tài),將 Jenkins 作為了保底的選擇。

綜上,最終選擇 Drone 的結(jié)論也就不難得出了,Drone 即開源,又可以私有化部署,同時(shí)作為云原生應(yīng)用,官方提供了針對 Docker、Docker Swarm、K8s 等多種容器場景下的部署方案,針對不同容器場景還有特別優(yōu)化,比如在 Docker Swarm 下 Drone 是以 agent 方式運(yùn)行 CI 任務(wù)的,而在 K8s 下則通過創(chuàng)建 K8s Job 來實(shí)現(xiàn),顯然充分利用了容器的優(yōu)勢所在,這也是 Drone 優(yōu)于其他 CI 應(yīng)用之處。個(gè)人還覺得 Drone 的語法是所有 CI 中最容易理解和掌握的,由于 Drone 每一個(gè)步驟都是運(yùn)行一個(gè) Docker 容器,本地模擬或調(diào)試也非常容易。

一句話概況 Drone,可以將其看做是可以支持私有化部署的開源版 CircleCI,并且目前仍然沒有看到有其他主打這個(gè)定位的 CI 工具,因此個(gè)人認(rèn)為 Drone 是 CI/CD 方面云原生應(yīng)用頭把交椅的有力競爭者。

容器環(huán)境下一次規(guī)范的發(fā)布應(yīng)該包含哪些內(nèi)容

技術(shù)選型完成后,我想首先演示一下最終的成果,希望能直觀的體現(xiàn)出 CI 對自動(dòng)化效率起到的提升,不過這就涉及到一個(gè)問題:在容器環(huán)境下,一次發(fā)布應(yīng)該包含哪些內(nèi)容,其中有哪些部分是可以被 CI 自動(dòng)化完成的。這個(gè)問題雖然每家公司各不相同,不過按經(jīng)驗(yàn)來說,容器環(huán)境下一次版本發(fā)布通常包含這樣一個(gè) Checklist:

[ ] 代碼的下載構(gòu)建及編譯

[ ] 運(yùn)行單元測試,生成單元測試報(bào)告及覆蓋率報(bào)告等

[ ] 在測試環(huán)境對當(dāng)前版本進(jìn)行測試

[ ] 為待發(fā)布的代碼打上版本號

[ ] 編寫 ChangeLog 說明當(dāng)前版本所涉及的修改

[ ] 構(gòu)建 Docker 鏡像

[ ] 將 Docker 鏡像推送到鏡像倉庫

[ ] 在預(yù)發(fā)布環(huán)境測試當(dāng)前版本

[ ] 正式發(fā)布到生產(chǎn)環(huán)境

看上去很繁瑣對嗎,如果每次發(fā)布都需要人工去處理上述的所有內(nèi)容,不僅容易出錯(cuò),而且也無法應(yīng)對 DevOps 時(shí)代一天至少數(shù)次的發(fā)布頻率,那么下面就來使用 CI 來解決所有問題吧。

CI 流程演示

為了對 CI 流程有最直觀的認(rèn)識,我創(chuàng)建了一個(gè)精簡版的 Github 項(xiàng)目 AlloVince/drone-ci-demo 來演示完整的流程,同時(shí)項(xiàng)目對應(yīng)的 CI 地址是 cloud.drone.io/AlloVince/drone-ci-demo ,項(xiàng)目自動(dòng)構(gòu)建的 Docker 鏡像會(huì)推送到 docker registry 的 allovince/drone-ci-demo,。為了方便說明,假設(shè)這個(gè)項(xiàng)目的核心文件只有 index.html 一個(gè)靜態(tài)頁面。

單人開發(fā)模式

目前這個(gè)項(xiàng)目背后的 CI 都已經(jīng)配置部署好,假設(shè)我是這個(gè)項(xiàng)目的唯一開發(fā)人員,如何開發(fā)一個(gè)新功能并發(fā)布新版本呢?

Clone 項(xiàng)目到本地, 修改項(xiàng)目代碼, 如將 Hello World 改為 Hello World V2

git add .,然后書寫符合約定的 Commit 并提交代碼, git commit -m "feature: hello world v2”

推送代碼到代碼庫git push,等待數(shù)分鐘后,開發(fā)人員會(huì)看到單元測試結(jié)果,Github 倉庫會(huì)產(chǎn)生一次新版本的 release,release 內(nèi)容為當(dāng)前版本的 ChangeLog, 同時(shí)線上已經(jīng)完成了新功能的發(fā)布。

雖然在開發(fā)者看來,一次發(fā)布簡單到只需 3 個(gè)指令,但背后經(jīng)過了如下的若干次交互,這是一次發(fā)布實(shí)際產(chǎn)生交互的時(shí)序圖,具體每個(gè)環(huán)節(jié)如何工作將在后文中詳細(xì)說明。

多人開發(fā)模式

一個(gè)項(xiàng)目一般不止一個(gè)開發(fā)人員,比如我是新加入這個(gè)項(xiàng)目的成員,在這個(gè) Demo 中應(yīng)該如何上線新功能呢?同樣非常簡單:

Clone 項(xiàng)目到本地,創(chuàng)建一個(gè)分支來完成新功能的開發(fā), git checkout -b feature/hello-world-v3。在這個(gè)分支修改一些代碼,比如將Hello World V2修改為Hello World V3

git add .,書寫符合規(guī)范的 Commit 并提交代碼, git commit -m "feature: hello world v3”

將代碼推送到代碼庫的對應(yīng)分支, git push origin feature/hello-world

如果功能已經(jīng)開發(fā)完畢,可以向 Master 分支發(fā)起一個(gè) Pull Request,并讓項(xiàng)目的負(fù)責(zé)人 Code Review

Review 通過后,項(xiàng)目負(fù)責(zé)人將分支合并入主干,Github 倉庫會(huì)產(chǎn)生一次新版本的 release,同時(shí)線上已經(jīng)完成了新功能的發(fā)布。

這個(gè)流程相比單人開發(fā)來多了 2 個(gè)環(huán)節(jié),很適用于小團(tuán)隊(duì)合作,不僅強(qiáng)制加入了 Code Review 把控代碼質(zhì)量,同時(shí)也避免新人的不規(guī)范行為對發(fā)布帶來影響。實(shí)際項(xiàng)目中,可以在 Github 的設(shè)置界面對 master 分支設(shè)置寫入保護(hù),這樣就從根本上杜絕了誤操作的可能。當(dāng)然如果團(tuán)隊(duì)中都是熟手,就無需如此謹(jǐn)慎,每個(gè)人都可以負(fù)責(zé) PR 的合并,從而進(jìn)一步提升效率。

GitFlow 開發(fā)模式

在更大的項(xiàng)目中,參與的角色更多,一般會(huì)有開發(fā)、測試、運(yùn)維幾種角色的劃分;還會(huì)劃分出開發(fā)環(huán)境、測試環(huán)境、預(yù)發(fā)布環(huán)境、生產(chǎn)環(huán)境等用于代碼的驗(yàn)證和測試;同時(shí)還會(huì)有多個(gè)功能會(huì)在同一時(shí)間并行開發(fā)。可想而知 CI 的流程也會(huì)進(jìn)一步復(fù)雜。

能比較好應(yīng)對這種復(fù)雜性的,首選 GitFlow 工作流, 即通過并行兩個(gè)長期分支的方式規(guī)范代碼的提交。而如果使用了 Github,由于有非常好用的 Pull Request 功能,可以將 GitFlow 進(jìn)行一定程度的簡化,最終有這樣的工作流:

以 dev 為主開發(fā)分支,master 為發(fā)布分支

開發(fā)人員始終從 dev 創(chuàng)建自己的分支,如 feature-a

feature-a 開發(fā)完畢后創(chuàng)建 PR 到 dev 分支,并進(jìn)行 code review

review 后 feature-a 的新功能被合并入 dev,如有多個(gè)并行功能亦然

待當(dāng)前開發(fā)周期內(nèi)所有功能都合并入 dev 后,從 dev 創(chuàng)建 PR 到 master

dev 合并入 master,并創(chuàng)建一個(gè)新的 release

上述是從 Git 分支角度看代碼倉庫發(fā)生的變化,實(shí)際在開發(fā)人員視角里,工作流程是怎樣的呢。假設(shè)我是項(xiàng)目的一名開發(fā)人員,今天開始一期新功能的開發(fā):

Clone 項(xiàng)目到本地,git checkout dev。從 dev 創(chuàng)建一個(gè)分支來完成新功能的開發(fā), git checkout -b feature/feature-a。在這個(gè)分支修改一些代碼,比如將Hello World V3修改為Hello World Feature A

git add .,書寫符合規(guī)范的 Commit 并提交代碼, git commit -m "feature: hello world feature A"

將代碼推送到代碼庫的對應(yīng)分支, git push origin feature/feature-a:feature/feature-a

由于分支是以feature/命名的,因此 CI 會(huì)運(yùn)行單元測試,并自動(dòng)構(gòu)建一個(gè)當(dāng)前分支的鏡像,發(fā)布到測試環(huán)境,并自動(dòng)配置一個(gè)當(dāng)前分支的域名如 test-featue-a.avnpc.com

聯(lián)系產(chǎn)品及測試同學(xué)在測試環(huán)境驗(yàn)證并完善新功能

功能通過驗(yàn)收后發(fā)起 PR 到 dev 分支,由 Leader 進(jìn)行 code review

Code Review 通過后,Leader 合并當(dāng)前 PR,此時(shí) CI 會(huì)運(yùn)行單元測試,構(gòu)建鏡像,并發(fā)布到測試環(huán)境

此時(shí) dev 分支有可能已經(jīng)積累了若干個(gè)功能,可以訪問測試環(huán)境對應(yīng) dev 分支的域名,如 test.avnpc.com,進(jìn)行集成測試。

集成測試完成后,由運(yùn)維同學(xué)從 Dev 發(fā)起一個(gè) PR 到 Master 分支,此時(shí)會(huì) CI 會(huì)運(yùn)行單元測試,構(gòu)建鏡像,并發(fā)布到預(yù)發(fā)布環(huán)境

測試人員在預(yù)發(fā)布環(huán)境下再次驗(yàn)證功能,團(tuán)隊(duì)做上線前的其他準(zhǔn)備工作

運(yùn)維同學(xué)合并 PR,CI 將為本次發(fā)布的代碼及鏡像自動(dòng)打上版本號并書寫 ChangeLog,同時(shí)發(fā)布到生產(chǎn)環(huán)境。

由此就完成了上文中 Checklist 所需的所有工作。雖然描述起來看似冗長,但不難發(fā)現(xiàn)實(shí)際作為開發(fā)人員,并沒有任何復(fù)雜的操作,流程化的部分全部由 CI 完成,開發(fā)人員只需要關(guān)注自己的核心任務(wù):按照工作流規(guī)范,寫好代碼,寫好 Commit,提交代碼即可。

接下來將介紹這個(gè)以 CI 為核心的工作流,是如何一步步搭建的。

Step by Step 構(gòu)建 CI 工作流 Step.0: 基于 K8s 部署 Drone v1.0.0

以 Github 為例,截止本文完成時(shí)間(2019 年 3 月 28 日), Drone 剛剛發(fā)布了第一個(gè)正式版本 v1.0.0。官方文檔已經(jīng)提供了分別基于 Docker、K8s 的 Drone 部署說明,不過比較簡略,因此這里給出一個(gè)相對完整的配置文件。

首先需要在 Github 創(chuàng)建一個(gè) Auth App,用于 repo 的訪問授權(quán)。應(yīng)用創(chuàng)建好之后,會(huì)得到 Client IDClient Secret 。同時(shí) Authorization callback URL 應(yīng)填寫 Drone 服務(wù)對應(yīng)域名下的 /login,如https://ci.avnpc.com/login

Drone 支持 SQLite、MySQL、Postgres、S3 等多種后端存儲(chǔ),主要用于記錄 build logs 等文本信息,這些信息并不是特別重要,且我們的 CI 有可能做遷移,因此個(gè)人更推薦使用 SQLite。

而在 K8s 環(huán)境下,SQLite 更適合用掛載 NAS 的方式供節(jié)點(diǎn)使用,因此首先將存儲(chǔ)的部分獨(dú)立為文件drone-pvc.yml,可以根據(jù)實(shí)際情況配置 nfs.pathnfs.server

kubectl apply -f drone-pvc.yaml

Drone 的配置主要涉及兩個(gè)鏡像:

drone/kubernetes-secrets 加密數(shù)據(jù)服務(wù),用于讀取 K8s 的 secrets

drone/drone:1.0.0-rc.6 就是 Drone 的 server 端,由于在 K8s 下 Drone 利用了 Job 機(jī)制,因此不需要部署 agent。

這部分配置較長,可以直接參考示例 drone.yaml

主要涉及到的配置項(xiàng)包括:

drone/kubernetes-secrets 鏡像中

SECRET_KEY: 數(shù)據(jù)加密傳輸所用的 key,可以使用 openssl rand -hex 16 生成一個(gè)

drone/drone鏡像中

DRONE_KUBERNETES_ENABLED: 開啟 K8s 模式

DRONE_KUBERNETES_NAMESPACE: Drone 所使用的 Namespace, 這里使用 default

DRONE_GITHUB_SERVER: Github 服務(wù)器地址,一般為 https://github.com

DRONE_GITHUB_CLIENT_ID: 上文創(chuàng)建 Github Auth App 得到的 Client ID

DRONE_GITHUB_CLIENT_SECRET: 上文創(chuàng)建 Github Auth App 得到的 Client Secret

DRONE_SERVER_HOST: Drone 服務(wù)所使用的域名

DRONE_SERVER_PROTO: http 或 https

DRONE_DATABASE_DRIVER: Drone 使用的數(shù)據(jù)庫類型,這里為 sqlite3

DRONE_DATABASE_DATASOURCE: 這里為 SQLite 數(shù)據(jù)庫的存放路徑

DRONE_SECRET_SECRET: 對應(yīng)上文的 SECRET_KEY

DRONE_SECRET_ENDPOINT: 加密數(shù)據(jù)服務(wù)的地址,這里通過 k8s service 暴露,無需修改

最后部署即可

kubectl apply -f drone.yaml

部署后首次登錄 Drone 就會(huì)跳轉(zhuǎn)到 Github Auth App 進(jìn)行授權(quán),授權(quán)完畢后可以看到所有能讀寫的 Repo,選擇需要開啟 CI 的 Repo,點(diǎn)擊 ACTIVATE 即可。 如果開啟成功,在 Github Repo 的 Settings > Webhooks 下可以看到 Drone 的回調(diào)地址。

Step.1: Hello World for Drone

在正式開始搭建工作流之前,首先可以測試一下 Drone 是否可用。Drone 默認(rèn)的配置文件是 .drone.yml, 在需要 CI 的 repo 根目錄下創(chuàng)建.drone.yml, 內(nèi)容如下,提交并git push到代碼倉庫即可觸發(fā) Drone 執(zhí)行 CI。

kind: pipeline  
name: deploy  
  
steps:  
- name: hello-world
  image: docker  
  commands:  
    - echo "hello world"

Drone v1 的語法主要參考的 K8s 的語法,非常直觀,無需閱讀文檔也可以知道,我們首先定義了一個(gè)管道 (pipeline),管道由若干步驟 (step) 組成,Drone 的每個(gè)步驟是都基于容器實(shí)現(xiàn)的,因此 Step 的語法就回到了我們熟悉的 Docker,一個(gè) Step 會(huì)拉取 image 定義的鏡像,然后運(yùn)行該鏡像,并順序執(zhí)行 commands 定義的指令。

在上例中,Drone 首先 clone git repo 代碼到本地,然后根據(jù) .drone.yml 所定義的,拉取 Docker 的官方鏡像,然后運(yùn)行該進(jìn)行并掛載 git repo 的代碼到 /drone/src 目錄。

在 Drone 的界面中,也可以清楚的看到這一過程。

本階段對應(yīng)

代碼部分: https://github.com/AlloVince/...

Drone 構(gòu)建記錄: https://cloud.drone.io/AlloVi...

Docker 鏡像: 無

Step.2: 單人工作流,自動(dòng)化單元測試與 Docker 鏡像構(gòu)建

有了 Hello World 的基礎(chǔ),接下來我們嘗試將這個(gè)工作流進(jìn)行擴(kuò)充。

為了方便說明,這里假設(shè)項(xiàng)目語言為 js,項(xiàng)目內(nèi)新增了test/index.js文件用于模擬單元測試,一般在 CI 中,只要程序的返回值為 0,即代表運(yùn)行成功。這個(gè)文件中我們僅僅輸出一行 Log Unit test passed用于模擬單元測試通過。

我們希望將代碼打包成 Docker 鏡像,根目錄下增加了 Dockerfile 文件,這里直接使用 Nginx 的官方鏡像,構(gòu)建過程只有 1 行COPY index.html /usr/share/nginx/html/, 這樣鏡像運(yùn)行后可以通過 http 請求看到index.html的內(nèi)容。

至此我們可以將工作流改進(jìn)為:

當(dāng) master 分支接收到 push 后,運(yùn)行單元測試

當(dāng) github 發(fā)布一次 release, 構(gòu)建 Docker 鏡像,并推送到鏡像倉庫

對應(yīng)的 Drone 配置文件如下

kind: pipeline  
name: deploy  
  
steps:  
  - name: unit-test  
    image: node:10  
    commands:  
      - node test/index.js  
    when:  
      branch: master  
      event: push  

  - name: build-image  
    image: plugins/docker  
    settings:  
      repo: allovince/drone-ci-demo  
      username: allovince  
      password:  
        from_secret: DOCKER_PASSWORD  
      auto_tag: true  
    when:  
      event: tag

雖然比 Hello World 復(fù)雜了一些,但是可讀性仍然很好,配置文件中出現(xiàn)了幾個(gè)新概念:

Step 運(yùn)行條件, 即 when 部分,上例中展示了當(dāng)代碼分支為 master,且收到一個(gè) push;以及當(dāng)代碼被標(biāo)記 tag 這兩種情況。Drone 還支持 repo、運(yùn)行結(jié)果等很多其他條件,可以參考 Drone Conditions 文檔。

Plugin 插件,上例中用于構(gòu)建和推送鏡像的是 plugins/docker 這個(gè) Plugin, 一個(gè) Plugin 本質(zhì)上仍然是一個(gè) Docker 鏡像,只是按照 Drone 的規(guī)范接受特定的輸入,并完成特定的操作。所以完全可以將 Plugin 看做一個(gè)無法更改 command 的 Docker 鏡像。

Docker 這個(gè) Plugin 由 Drone 官方提供,用于 Docker 鏡像的構(gòu)建和推送,具體的用法可以查看Docker 插件的文檔 。例子中演示的是將鏡像推送到私有倉庫,如果不做特殊配置,鏡像將被推送到 Docker 的官方倉庫。

此外 Docker 插件還有一個(gè)很方便的功能,如果設(shè)置 auto_tag: true,將根據(jù)代碼的版本號自動(dòng)規(guī)劃 Docker 鏡像的標(biāo)簽,如代碼版本為1.0.0,將為 Docker 鏡像打三個(gè)標(biāo)簽 1, 1.0, 1.0.0。如果代碼版本號不能被解析,則鏡像標(biāo)簽為 latest

目前 Drone 的插件已經(jīng)有很多,可以覆蓋主流的云服務(wù)商和常見的工作流,并且自己制作插件的成本也不高。

Secret 加密數(shù)據(jù),鏡像倉庫的用戶名和密碼都屬于敏感信息,因此可以使用 from_secret 獲取加密數(shù)據(jù)。一條加密數(shù)據(jù)就是一個(gè) key / value 對,如上例中的 DOCKER_PASSWORD 就是我們自己定義的加密數(shù)據(jù) key。即便加密數(shù)據(jù)在 log 中被打印,UI 也只能看到 ***。加密數(shù)據(jù)的 value 需要提前保存好,保存的方式有 3 種:

通過 Drone UI 界面中, repo -> Settings -> Secrets 添加,所添加的加密數(shù)據(jù)將保存在 Drone 的數(shù)據(jù)庫中,僅能在當(dāng)前 repo 中使用。

通過Drone cli 加密后保存在 .drone.yml文件中, 使用范圍僅限 yaml 文件內(nèi)

通過 K8s 保存為K8s Secret,稱為 External Secrets,所有的 repo 都可以共享。如果是團(tuán)隊(duì)使用的話,這種保存方式顯然是最方便的,但也要注意安全問題,因此 External Secrets 還支持 repo 級別的權(quán)限管理, 可以只讓有當(dāng)前 repo 寫入權(quán)限的人才能使用對應(yīng) secret。

這個(gè)階段對應(yīng)

代碼倉庫: https://github.com/AlloVince/...

push 時(shí)觸發(fā)的 Drone CI: https://cloud.drone.io/AlloVi...

release 時(shí)觸發(fā)的 Drone CI: https://cloud.drone.io/AlloVi...

release 后 CI 構(gòu)建的 Docker 鏡像: allovince/drone-ci-demo:latest

Step.3: GitFlow 多分支團(tuán)隊(duì)工作流

上面的工作流已經(jīng)基本可以應(yīng)付單人的開發(fā)了,而在團(tuán)隊(duì)開發(fā)時(shí),這個(gè)工作流還需要一些擴(kuò)展。不需要引入 Drone 的新功能,只需要在上文基礎(chǔ)上根據(jù)分支做一點(diǎn)調(diào)整即可。

首先保證單元測試位于 steps 的第一位,并且限定團(tuán)隊(duì)工作的分支,在 push 和 pull_request 時(shí),都能觸發(fā)單元測試。

- name: unit-test  
  image: node:10  
  commands:  
    - node test/index.js  
  when:  
    branch:  
      include:  
        - feature/*  
        - master  
        - dev  
    event:  
      include:  
        - push  
        - pull_request

然后根據(jù) Gitflow 的流程對于不同的分支構(gòu)建 Docker 鏡像并打上特定標(biāo)簽,以 feature 分支為例,下面的配置約定了當(dāng)分支名滿足 feature/*,并收到 push 時(shí),會(huì)構(gòu)建 Docker 鏡像并打標(biāo)簽,標(biāo)簽名稱為當(dāng)前分支名去掉 feature/。如分支 feature/readme, 對應(yīng) docker 鏡像為 allovince/drone-ci-demo:readme,考慮到 feature 分支一般都出于開發(fā)階段,因此新的鏡像會(huì)覆蓋舊的。配置如下

- name: build-branch-image  
  image: plugins/docker  
  settings:  
    repo: allovince/drone-ci-demo  
    username: allovince  
    password:  
      from_secret: DOCKER_PASSWORD  
    tag:  
      - ${DRONE_BRANCH##feature/}  
  when:  
    branch: feature/*  
    event: push

鏡像的 Tag 處不再使用自動(dòng)方式,其中DRONE_BRANCH是 Drone 的內(nèi)置環(huán)境變量 (Environment),對應(yīng)當(dāng)前的分支名。##feature/是執(zhí)行了一個(gè)字符串的替換操作 (Substitution)。更多的環(huán)境變量和字符串操作都可以在文檔中找到。

以此類推,可以查看這個(gè)階段的完整 .drone.yml ,此時(shí)我們的工作流示例如下:

團(tuán)隊(duì)成員從 dev 分支 checkout 自己的分支 feature/readme

feature/readme提交代碼并 push, CI 運(yùn)行單元測試,構(gòu)建鏡像allovince/drone-ci-demo:readme

功能開發(fā)完成后,團(tuán)隊(duì)成員向 dev 分支 發(fā)起 pull request , CI 運(yùn)行單元測試

團(tuán)隊(duì)其他成員 merge pull request, CI 運(yùn)行單元測試,構(gòu)建鏡像allovince/drone-ci-demo:test

運(yùn)維人員從 dev 向 master 發(fā)起 pull request,CI 運(yùn)行單元測試,并構(gòu)建鏡像allovince/drone-ci-demo:latest

運(yùn)維人員 merge pull request, 并 release 新版本 pre-0.0.2, CI 構(gòu)建鏡像allovince/drone-ci-demo:pre-0.0.2

可能細(xì)心的同學(xué)會(huì)發(fā)現(xiàn) dev -> master 的 pull request 時(shí),構(gòu)建鏡像失敗了,這是由于 Drone 出于安全考慮限制了在 pull request 時(shí)默認(rèn)無法讀取加密數(shù)據(jù),因此無法得到 Docker Registry 密碼。如果是私有部署的話,可以在 Repo Settings 中勾選Allow Pull Requests,此處就可以構(gòu)建成功。

Step.4: 語義化發(fā)布

上面基本完成了一個(gè)支持團(tuán)隊(duì)協(xié)作的半自動(dòng) CI 工作流,如果不是特別苛刻的話,完全可以用上面的工作流開始干活了。

不過基于這個(gè)工作流工作一段時(shí)間,會(huì)發(fā)現(xiàn)仍然存在痛點(diǎn),那就是每次發(fā)布都要想一個(gè)版本號,寫 ChangeLog,并且人工去 release。

標(biāo)記版本號涉及到上線后的回滾,追溯等一系列問題,應(yīng)該是一項(xiàng)嚴(yán)肅的工作,其實(shí)如何標(biāo)記早已有比較好的方案,即語義化版本。在這個(gè)方案中,版本號一共有 3 位,形如 1.0.0,分別代表:

主版本號:當(dāng)你做了不兼容的 API 修改,

次版本號:當(dāng)你做了向下兼容的功能性新增,

修訂號:當(dāng)你做了向下兼容的問題修正。

雖然有了這個(gè)指導(dǎo)意見,但并沒有很方便的解決實(shí)際問題,每次發(fā)布要搞清楚代碼的修改到底是不是向下兼容的,有哪些新的功能等,仍然要花費(fèi)很多時(shí)間。

而語義化發(fā)布 (Semantic Release) 就能很好的解決這些問題。

語義化發(fā)布的原理很簡單,就是讓每一次 Commit 所附帶的 Message 格式遵守一定規(guī)范,保證每次提交格式一致且都是可以被解析的,那么進(jìn)行 Release 時(shí),只要統(tǒng)計(jì)一下距離上次 Release 所有的提交,就分析出本次提交做了何種程度的改動(dòng),并可以自動(dòng)生成版本號、自動(dòng)生成 ChangeLog 等。

語義化發(fā)布中,Commit 所遵守的規(guī)范稱為約定式提交 (Conventional Commits)。比如 node.js、 Angular、Electron 等知名項(xiàng)目都在使用這套規(guī)范。

語義化發(fā)布首先將 Commit 進(jìn)行分類,常用的分類 (Type) 有:

feat: 新功能

fix: BUG 修復(fù)

docs: 文檔變更

style: 文字格式修改

refactor: 代碼重構(gòu)

perf: 性能改進(jìn)

test: 測試代碼

chore: 工具自動(dòng)生成

每個(gè) Commit 可以對應(yīng)一個(gè)作用域(Scope),在一個(gè)項(xiàng)目中作用域一般可以指不同的模塊。

當(dāng) Commit 內(nèi)容較多時(shí),可以追加正文和腳注,如果正文起始為BREAKING CHANGE,代表這是一個(gè)破壞性變更。

以下都是符合規(guī)范的 Commit:

feat: 增加重置密碼功能
fix(郵件模塊): 修復(fù)郵件發(fā)送延遲BUG
feat(API): API重構(gòu)

BREAKING CHANGE: API v3上線,API v1停止支持

有了這些規(guī)范的 Commit,版本號如何變化就很容易確定了,目前語義化發(fā)布默認(rèn)的規(guī)則如下

Commit 版本號變更
BREAKING CHANGE 主版本號
feat 次版本號
fix / perf 修訂號

因此在 CI 部署 semantic-release 之后,作為開發(fā)人員只需要按照規(guī)范書寫 Commit 即可,其他的都由 CI 完成。

具體如何將語義化發(fā)布加入 CI 流程中呢, semantic-release 是 js 實(shí)現(xiàn)的,如果是 js 的項(xiàng)目,可以直接在package.json中增加配置項(xiàng),而對于任意語言的項(xiàng)目,推薦像 Demo 中一樣,在根目錄下增加 配置文件release.config.js。這個(gè)配置目的是為了禁用默認(rèn)開啟的 npm 發(fā)布機(jī)制,可以直接套用。

semantic-release 要執(zhí)行 Github release,因此我們需要在 CI 中配置自己的 Personal access tokens 讓 CI 有 Github repo 的讀寫權(quán)限, 可以通過 Github 點(diǎn)擊自己頭像 -> Settings -> Developer settings -> Personal access tokens -> Generate new token 生成一個(gè) Token。 然后在 Drone 的 repo 設(shè)置界面新增一個(gè) Secret, key 為 GITHUB_TOKEN, value 填入剛生成的 Token。

最后在 .drone.yml 中增加這樣一段就可以了。

- name: semantic-release  
  image: gtramontina/semantic-release:15.13.3  
  environment:  
    GITHUB_TOKEN:  
      from_secret: GITHUB_TOKEN  
  entrypoint:  
    - semantic-release  
  when:  
    branch: master  
    event: push

來再次模擬一下流程,feature 分支部分與上文相同

從 dev 向 master 發(fā)起 pull request,CI 運(yùn)行單元測試,并構(gòu)建鏡像allovince/drone-ci-demo:latest

merge pull request,CI 會(huì)執(zhí)行單元測試并運(yùn)行 semantic-release , 運(yùn)行成功的話能看到 Github 新增 release v1.0.0

Github release 再次觸發(fā)CI 構(gòu)建生產(chǎn)環(huán)境用 Docker 鏡像allovince/drone-ci-demo:1.0.0

最終我們能得到這樣一個(gè)賞心悅目的 release

Step.5: Kubernetes 自動(dòng)發(fā)布

Docker 鏡像推送到倉庫后,我們還剩最后一步就可以完成全自動(dòng)發(fā)布的閉環(huán),即通知 Kubernetes 將鏡像發(fā)布到生產(chǎn)環(huán)境。這一步實(shí)現(xiàn)比較靈活,因?yàn)楹芏嘣品?wù)商在容器服務(wù)都會(huì)提供 Trigger 機(jī)制,一般是提供一個(gè) URL,只要請求這個(gè) URL 就可以觸發(fā)容器服務(wù)的發(fā)布。Demo 中我們使用更為通用的方法,就是將 kubectl 打包為容器,以客戶端調(diào)用 K8s 集群 Master 節(jié)點(diǎn) API ( kube-apiserver ) 的形式完成發(fā)布。

假設(shè)我們在生產(chǎn)環(huán)境下 drone-ci-demo 項(xiàng)目的 K8s 發(fā)布文件如下

---  
apiVersion: extensions/v1beta1  
kind: Deployment  
metadata:  
  name: ci-demo-deployment  
  namespace: default  
spec:  
  replicas: 1  
  template:  
    spec:  
      containers:  
        - image: allovince/drone-ci-demo  
          name: ci-demo  
      restartPolicy: Always

對應(yīng) .drone.yml 中增加 step 如下。這里使用的插件是honestbee/drone-kubernetes, 插件中kubectl 連接 API 使用的是證書+ Token 的方式鑒權(quán),因此需要先獲得證書及 Token, 已經(jīng)授權(quán)的 Token 保存于 k8s secret,可以通過kubectl get secret [ your default secret name ] -o yaml | egrep "ca.crt:|token:"獲得并配置到 drone 中,注意插件要求 token 是明文的,需要 base64 解碼一下:echo [ your token ] | base64 -d && echo ""

- name: k8s-deploy  
  image: quay.io/honestbee/drone-kubernetes  
  settings:  
    kubernetes_server:  
      from_secret: KUBERNETES_SERVER  
    kubernetes_cert:  
      from_secret: KUBERNETES_CERT  
    kubernetes_token:  
      from_secret: KUBERNETES_TOKEN  
    namespace: default  
    deployment: ci-demo-deployment  
    repo: allovince/drone-ci-demo  
    container: ci-demo  
    tag:  
      - ${DRONE_TAG}  
  when:  
    event: tag

在示例)中,可以看到在語義化發(fā)布之后 CI 會(huì)將新版本的 Docker 鏡像自動(dòng)發(fā)布到 K8s),這里為了演示僅打印了指令并未實(shí)際運(yùn)行。相當(dāng)于運(yùn)行了如下的指令:

kubectl -n default set image deployment/ci-demo-deployment ci-demo=allovince/drone-ci-demo:v1.0.2

由于自動(dòng)發(fā)布的環(huán)節(jié)勢必要接觸到生產(chǎn)服務(wù)器,需要格外注意安全問題,首推的方式當(dāng)然是將 CI 和 K8s 集群放于同一內(nèi)網(wǎng)中,同時(shí)可以使用 K8s 的 RBAC 權(quán)限控制,為自動(dòng)發(fā)布多帶帶創(chuàng)建一個(gè)用戶),并刪除不必要的權(quán)限。

后話

總結(jié)一下,本文展示了從 Hello World 到 單人單分支手動(dòng)發(fā)布 到 團(tuán)隊(duì)多分支 GitFlow 工作流 到 團(tuán)隊(duì)多分支 semantic-release 語義化發(fā)布 到 通知 K8s 全自動(dòng)發(fā)布,如何從零開始一步一步搭建 CI 將團(tuán)隊(duì)開發(fā)、測試、發(fā)布的流程全部自動(dòng)化的過程,最終能讓開發(fā)人員只需要認(rèn)真提交代碼就可以完成日常的所有 DevOps 工作。

最終 Step 的完成品可以適配之前的所有 Step,如果不太在意實(shí)現(xiàn)細(xì)節(jié)的話,可以在此基礎(chǔ)上稍作修改,直接使用。

然而寫好每一個(gè) Commit 這個(gè)看似簡單的要求,其實(shí)對于大多數(shù)團(tuán)隊(duì)來說并不容易做到,在實(shí)施過程中,經(jīng)常會(huì)遇到團(tuán)隊(duì)成員不理解為什么要重視 Commit 規(guī)范,每個(gè) Commit 都要深思熟慮是否過于吹毛求疵等等疑問。

以 Commit 作為 CI 的核心,個(gè)人認(rèn)為主要會(huì)帶來以下幾方面的影響:

一個(gè)好的 Commit,代表著開發(fā)人員對當(dāng)前改動(dòng)之于整個(gè)系統(tǒng)的影響,有非常清楚的認(rèn)識,代碼的修改到底算 feat 還是 fix ,什么時(shí)候用 BREAKING CHANGE 等都是要仔細(xì)斟酌的,每個(gè) Commit 都會(huì)在 ChangeLog 里“留底”,從而約束團(tuán)隊(duì)不隨意提交未經(jīng)思考的代碼,提高代碼質(zhì)量

一個(gè)好的 Commit 也代表開發(fā)人員有能力對所實(shí)現(xiàn)功能進(jìn)行精細(xì)的劃分,一個(gè)分支做的事情不宜過多,一個(gè)提交也應(yīng)該專注于只解決一個(gè)問題,每次提交(至少是每次 push )都應(yīng)該保持系統(tǒng)可構(gòu)建、可運(yùn)行、可測試,如果能堅(jiān)持做到這些,對于合并代碼時(shí)的沖突解決,以及集成測試都有很大幫助。

由于每次發(fā)布能清楚的看到所有關(guān)聯(lián)的 Commit 以及 Commit 的重要程度,那么線上事故的回滾也會(huì)非常輕松,回滾到哪個(gè)版本,回滾后哪些功能會(huì)受到影響,只要看 CI 自動(dòng)生成的 Release 記錄就一目了然。如果沒有這些,回滾誤傷到預(yù)期外的功能從而引發(fā)連鎖反應(yīng)的慘痛教訓(xùn),可能很多運(yùn)維都有過類似經(jīng)歷吧。

因此 CI 自動(dòng)化其實(shí)是錦上添花而非雪中送炭,如果團(tuán)隊(duì)原本就無視規(guī)范,Commit 全是空白或者沒有任何意義的單詞,分支管理混亂,發(fā)布困難,奢望引入一套自動(dòng)化 CI 來能解決所有這些問題,無疑是不現(xiàn)實(shí)的。而只有原本就重視代碼質(zhì)量,有一定規(guī)范意識,再通過自動(dòng)化 CI 來監(jiān)督約束,團(tuán)隊(duì)在 CI 的幫助下代碼質(zhì)量提高,從而有機(jī)會(huì)進(jìn)一步改進(jìn) CI 的效率,才能形成良性循環(huán)。

愿天下不再有難發(fā)布的版本。

References:

云原生應(yīng)用之路

相關(guān)討論可以在我的 Telegram Group 給我留言。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/27760.html

相關(guān)文章

  • 容器環(huán)境下的持續(xù)集成最佳實(shí)踐構(gòu)建基于 Drone + GitFlow + K8s 的云原生語義

    摘要:集成測試完成后,由運(yùn)維同學(xué)從發(fā)起一個(gè)到分支,此時(shí)會(huì)會(huì)運(yùn)行單元測試,構(gòu)建鏡像,并發(fā)布到預(yù)發(fā)布環(huán)境測試人員在預(yù)發(fā)布環(huán)境下再次驗(yàn)證功能,團(tuán)隊(duì)做上線前的其他準(zhǔn)備工作運(yùn)維同學(xué)合并,將為本次發(fā)布的代碼及鏡像自動(dòng)打上版本號并書寫,同時(shí)發(fā)布到生產(chǎn)環(huán)境。 云原生 (Cloud Native) 是伴隨的容器技術(shù)發(fā)展出現(xiàn)的的一個(gè)詞,最早出自 Pivotal 公司(即開發(fā)了 Spring 的公司)的一本技術(shù)小...

    DevTalking 評論0 收藏0
  • Kubernetes和云原生的巨浪要把云計(jì)算帶向何處

    摘要:本屆大會(huì)議題數(shù)量接近,比去年規(guī)模較大的北美峰會(huì)多出了近一倍。同時(shí)還在華為伙伴公有云等云平臺上創(chuàng)建集群并接入了他們的平臺,以便于快速響應(yīng)技術(shù)峰會(huì)等大型活動(dòng)期間暴漲的計(jì)算量。Kubernetes,云原生,service mesh,這些驚人的全球增長趨勢,令人欣喜之余迫不及待想要看看云原生在未來究竟會(huì)發(fā)展出怎樣一派繁榮的景象。 容器領(lǐng)域最具影響力的技術(shù)峰會(huì)之一 KubeCon + Cloud...

    hizengzeng 評論0 收藏0
  • 基于drone的CI/CD,對接kubernetes,見證靈活與自由,CI/CD對接kubernet

    摘要:所以我們選一個(gè)倉庫倉庫比較多,我這里選用,都行,根據(jù)需求自行選擇訪問端口,然后就沒有然后了功能沒有那么強(qiáng)大,不過占用資源少,速度快,我們穩(wěn)定運(yùn)行了幾年了。 kubernetes集群三步安裝 CI 概述 用一個(gè)可描述的配置定義整個(gè)工作流 程序員是很懶的動(dòng)物,所以想各種辦法解決重復(fù)勞動(dòng)的問題,如果你的工作流中還在重復(fù)一些事,那么可能就得想想如何優(yōu)化了 持續(xù)集成就是可以幫助我們解決重復(fù)的代碼...

    iOS122 評論0 收藏0
  • 2018年已過半,Kubernetes和云原生的巨浪要把云計(jì)算帶向何處

    摘要:自年月舉辦以來,規(guī)模持續(xù)增大。本屆大會(huì)議題數(shù)量接近,比去年規(guī)模較大的北美峰會(huì)多出了近一倍。同時(shí)還在華為伙伴公有云等云平臺上創(chuàng)建集群并接入了他們的平臺,以便于快速響應(yīng)技術(shù)峰會(huì)等大型活動(dòng)期間暴漲的計(jì)算量。 Kubernetes,云原生,service mesh,這些驚人的全球增長趨勢,令人欣喜之余迫不及待想要看看...

    Pines_Cheng 評論0 收藏0
  • UCan技術(shù)開放日(上海站)——云原生在多行業(yè)場景的落地實(shí)踐

    摘要:技術(shù)開放日云原生在多行業(yè)場景的落地實(shí)踐當(dāng)前,云計(jì)算已成為萬千企業(yè)數(shù)字化轉(zhuǎn)型的基石,隨之而來的是對云計(jì)算應(yīng)用效能的更高要求。UCloud UCan技術(shù)開放日——云原生在多行業(yè)場景的落地實(shí)踐當(dāng)前,云計(jì)算已成為萬千企業(yè)數(shù)字化轉(zhuǎn)型的基石,隨之而來的是對云計(jì)算應(yīng)用效能的更高要求。敏捷開發(fā)、彈性架構(gòu)、多集群運(yùn)維等,讓企業(yè)現(xiàn)有IT架構(gòu)面臨新的挑戰(zhàn)。云原生以其獨(dú)特的技術(shù)特點(diǎn),很好地契合了云計(jì)算發(fā)展的本質(zhì)需求...

    Tecode 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<