“微服務”這個概念近兩年非常熱,正在慢慢改變 DevOps 的思路。微服務架構把一個龐大的業務系統拆解開來,每一個元件變得更加獨立自治、鬆耦合。但是,同時也伴隨著部署單元粒度越來越小,對交付效率要求也越來越高。一套高效、靈活、高可用的 CI/CD 系統就很關鍵。所以說 CI/CD 是微服務架構下必不可少的一部分。
這方面有很多的開源專案和工具,比如 Jenkins、Github 預設支援的 Travis 以及本文主要介紹的GitLab CI。
那麼“當談到 GitLab CI 的時候,我們都該聊些什麼?”
什麼是 GitLab WorkFlow
本章主要講了 GitLab WorkFlow 從研發到釋出交付的一個流程,介紹 CI/CD 所做的事情。
圖1
圖 1 來自 GitLab 官方文件,可以讓我們更加方便的瞭解 CI/CD 做了哪些事情。
從左往右看,首先研發人員完成需求提交程式碼到 GitLab。GitLab 觸發一次 Build,構建好服務,然後開始跑單元測試、整合測試。等待測試結果通過後,再由負責該專案的同事進行 CodeReview,灰度釋出,正式部署到線上。CI/CD 就是指測試和釋出環節,如果能夠做到自動化,那麼就可以大大加快開發迭代的速度。
如何配置 GitLab Runner 如何把專案接入 CI
GitLab CI 相關術語
在介紹 GitLab 之前,先介紹一下本文主要涉及到術語。
- Job/Build,它是最小的任務單元,只負責一件事情,要麼編譯,要麼測試等;
- Stage,階段,每一個 Job 都會有一個階段,一個階段可以包含多個 Job。階段是有先後順序的。通過 stage 可以間接的控制 Job 執行的先後順序;
- Pipeline,多個 Stage 有順序的排列就是 Pipeline,流水線;
- GitLab Runner,是實際處理 Job 的,每個 Runner 可以單獨配置,Runner 支援多種型別的 Job,同一時間單個 runner 只能處理一個 Job;
- GitLab Multi Runner,是一個 GitLab 的開源專案,用來統一管理 Runner;
- Executor,每個 Runner 都需要指定一個 Executor,來決定 runner 最終使用哪個執行器進行處理。
圖2
圖 2 是一個典型的 Pipeline,一共有 5 個階段,Build,Test,Release, Staging, Production,每個階段裡都至少有一個 Job,Test 中有兩個 Job。GitLab 會從左往右依次把任務給到 Runner 處理,如果中途有一個任務沒有處理成功的話,整個 Pipeline 就會退出。這就是持續整合(CI)、持續釋出(CD) 的一個流程。
如何使用 GitLab CI
註冊 Runner
圖3
GitLab 中提供了兩種 Runner 的型別,圖 3 這個介面可以在 GitLab 專案設定頁中找到的,一個是特定的 Specific Runner,另一個是共享的 Shared Runner 。特定的 Runner 只能供部分專案使用,而共享的 Runner 是所有 GitLab 中的專案都可以使用的。而這兩種型別的 Runner 的註冊方式都是一樣。
從註冊一個特定的 Runner 開始講,首先安裝一個 GitLab Mutli Runner,因為是 Go 語言實現的,所以安裝起來會比較簡單,直接採用二進位制安裝即可。第二步正式開始註冊,輸入 Gitlab 地址、token、描述、標籤執行器等。輸入上述資料之後 Runner 就註冊好了,由於 Multi Runner 支援動態載入配置,所以 Runner 就立即生效了。可以在剛才的介面中看到新增了一個 Runner。有了 Runner,第二步就是如何在專案中增加 .gitlab-ci.yml 的 CI 配置檔案。
在專案中增加 .gitlab-ci.yml 的 CI 配置檔案
圖 4
上文所示是一個非常簡單的 CI 配置檔案。定義了兩個階段,一個 test,一個 build,先執行 test 再執行 build,test 階段有一個 job 叫做 test,執行的指令是 echo skip,但是這個 job 需要跑在帶有 opentalk 的這個標籤的 runner 上。build 階段也有一個 job,叫做 build,它會執行 make docker,去構建 docker 映象並且推送到私有倉庫中,這個任務只有當分支中有 tag 提交才會觸發,並且需要跑在帶有 online docker builder 的 runner 上。寫好這樣一個 gitlab-ci.yml 後,commit 一下提交到 Gitlab,你就可以看到 CI/CD 頁面(圖4)中增加一條正在跑的任務。
圖 5
接下來看看 GitLab Runner 的內部實現是怎樣的?
GitLab Runner 的實現細節
本章主要分析了 GitLab CI 跟 Runner 資訊互動的過程。
圖 6
從圖 6 可以看出 GitLab CI 是這樣一個結構,最上面 GitLab 服務,負責託管程式碼,支配分解 Job。下面幾個是 GitLabMultiRunner,由於支援多作業系統環境,所以圖 6 中都加了標註,每一個 GitLabMultiRunner 可以配置多個 GitLab Runner,GitLab Runner 直接跟 GitLab 做互動,這一層通訊是通過 HTTP 協議實現的,之後也會講到。另外有些同學可能已經注意到了,圖中 GitLab 是部署在公網上的,而 GitLab Runner 則是在 Nat 之下的,這個設計非常友好,不需要把 GitLab Runner 跟 GitLab 部署在一起,GitLab Runner 甚至可以在自己的筆記本上。
當我們看完了 GitLab CI 的整體結構後,再看看 Runner 跟 GitLab 之間的資訊互動是怎樣的?
Runner 跟 GitLab 之間的資訊互動是怎樣的?
資訊互動分為幾個部分,第一個部分是 Runner 註冊。
圖 7
Runner 會向 GitLab 傳送一個註冊請求,請求內容中包含 token、 tag 等重要資訊,這些其實都是之前配置的時候需要填寫的, GitLab 接收一個註冊請求之後就會返回一個 token 給 Runner,Runner 之後的請求中都會帶上這個 token。
圖 8
在收到 GitLab 註冊成功的訊息之後,Runner 就會不停的向 GitLab 請求 Job,時間間隔是 3s。可以看到請求中的 token 已經改成註冊時 GitLab 返回的 token 了。
這時會有兩種情況:
第一種是沒有任務,GitLab 返回 204 No Content;
圖 9
第二種情況是有任務,GitLab 會把任務資訊返回回來,包括任務的 token,job_info,git_info,runner_info 等等。Runner 在接收到 Job 之後,就會向 GitLab 傳送一個確認請求,同時更新任務的狀態。傳送完這個請求,Runner 就開始正式跑任務了。Runner 會定時的傳送輸出的中間資料,通過向 GitLab 發 Patch 請求的方式。
圖 10
等任務處理完後,Runner 會傳送最終結果、狀態、日誌等。
圖 11
最後總結下,第一個註冊 Runner,註冊成功後 3s 定時請求 Job,接收到 Job 之後傳送確認請求,然後開始執行任務,定時把中間結果輸出給 GitLab,等任務處理完了,把結果傳送給 GitLab。上述內容就是 Runner 跟 GitLab 之間的資訊互動流程。
現在 Runner 已經從 GitLab 獲取到了任務,下一步 Runner 是怎麼做的呢,Executor 又是怎麼實現?下篇《當談到 GitLab CI 的時候,我們都在聊些什麼》將會重點為大家介紹 Docker Executor 的實現細節。
更多閱讀: