基於 Gitlab 從零開始搭建自己的持續集成流水線(Pipeline)


 

一、gitlab 實現的 auto devops

1. DevOps 中的一些概念與原則

持續集成(Continuous integration,簡稱CI)指的是,頻繁地(一天多次)將代碼集成到主干。

它的好處主要有兩個。

  • 快速發現錯誤。每完成一點更新,就集成到主干,可以快速發現錯誤,定位錯誤也比較容易。
  • 防止分支大幅偏離主干。如果不是經常集成,主干又在不斷更新,會導致以后集成的難度變大,甚至難以集成。

持續集成的目的,就是讓產品可以快速迭代,同時還能保持高質量。它的核心措施是,代碼集成到主干之前,必須通過自動化測試。只要有一個測試用例失敗,就不能集成。

(2) 持續交付、持續部署的概念 持續交付(Continuous delivery)指的是,頻繁地將軟件的新版本,交付給質量團隊或者用戶,以供評審。如果評審通過,代碼就進入生產階段。

持續部署(continuous deployment)是持續交付的下一步,指的是代碼通過評審以后,自動部署到生產環境。

(3) 持續集成系統的組成

  • 一個自動構建過程,包括自動編譯、分發、部署和測試等。
  • 一個代碼存儲庫,即需要版本控制軟件來保障代碼的可維護性,同時作為構建過程的素材庫。
  • 一個持續集成服務器。

(4) 為什么要引入auto devops

  1. 部署的環境問題 ;
  2. Dev, QA, Ops的進度問題 ;
  3. 持續集成的好處 :
    1. 編譯問題與Bug可以在push或合並之后第一時間發現並解決;
    2. Devops使持續交付成為可能,使產品隨時可交。過去公司做測試可能需要十幾、二十幾個組件,集成一次往往要一兩個小時,費力費時,而且復雜容易出錯,而一旦配置出錯的話耗時會更久。因此,一次集成測試一周才會做一次,測出Bug要到下一周才能更新,再做測試,這個周期會非常漫長。而持續集成的意義就在於減少風險,和重復的過程,最終提高工作效率。

2. GitLab CI中的一些概念

(1) Pipeline

  • 一次 Pipeline 其實相當於一次構建任務,里面可以包含多個流程,比如自動構建、自動進行單元測試、自動進行代碼檢查等流程 ;
  • 任何提交或者 Merge Request 的合並都可以觸發 Pipeline ;

(2) stages

  • stages 表示構建階段,就是上面提到的流程 ;
  • 可以在一次 Pipeline 中定義多個 stage ;
  • stages有如下特點 :
    • 所有 stages 會按照順序運行,即當一個 stage 完成后,下一個 stage 才會開始
    • 只有當所有 stages 成功完成后,該構建任務 (Pipeline) 才算成功
    • 如果任何一個 stage 失敗,那么后面的 stages 不會執行,該構建任務 (Pipeline) 失敗

(3) jobs

  • job表示構建工作,表示某個stage里面執行的工作 ;
  • 一個stage里面可以定義多個job ;
  • jobs有如下特點 :
    • 相同 stage 中的jobs 會並行執行
    • 相同 stage 中的 jobs 都執行成功時,該 stage 才會成功
    • 如果任何一個job 失敗,那么該 stage 失敗,即該構建任務 (Pipeline) 失敗

(4) gitlab runner

  • 執行構建任務的一個服務 ;
  • 把構建任務放到runner里面而不是在CI里面做是不想把”構建”這個重任(通常較大的工程構建都比較小號資源) 放到gitlab上而影響gitlab性能。通過把gitlab runner安裝到不同機器上,讓這台單獨的機器來執行構建任務
  • 關於 gitlab server 與 gitlab runner 之間的關系以及信息交互可以通過下面這個鏈接看到 : https://xiaozhuanlan.com/topic/3529176084

二、使用 Gitlab 實現一個簡單的流水線 (Pipeline)

1. 准備工作

(1) 從docker hub下載gitlab/gitlab-runner鏡像

root# docker pull gitlab/gitlab-runner

(2) 准備一個用來完成stage的鏡像

多個步驟使用同一個鏡像來創建容器,也可以根據不同stage准備多個特定的鏡像。

這里只是介紹一個使用docker來完成多個簡單stage的demo,就拿一個最簡單的能完成任務的鏡像,一個簡單的Dockerfile如下:

FROM docker.io/ubuntu MAINTAINER user.name user.email # install tools USER root RUN apt-get update RUN apt-get install -y git cmake g++ gcovr ENTERPOINT /bin/bash

這篇文章介紹的流水線有兩個步驟,第一個步驟完成構建,第二個步驟完成單元測試以及單元測試覆蓋率的計算。其實兩個stage完全可以放到一個容器中來進行。 為模擬真實的流水線,每個環節做特定的工作。這里假設兩個stage完全不同,需要使用不同的容器來完成。

下面是我們根據需要創建的兩個不同鏡像 :

具體docker的基本操作請自行Google,也可以參考《每天五分鍾玩轉Docker容器技術》這本書。

(3) 安裝docker-compose

root# sudo curl -L https://github.com/docker/compose/releases/download/1.17.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

如果上面的源下不了,使用下面的方式 :

yum install -y epel-release yum install -y python-pip pip install --upgrade pip pip install docker-compose

(4) 編寫docker-compose.yml 一個簡單的docker-compose.yml文件:

runner:
  image: gitlab/gitlab-runner restart: always container_name: gitlab-runner volumes: - /var/run/docker.sock:/var/run/docker.sock - /srv/gitlab-runner/config:/etc/gitlab-runner

解釋一下:

  • /var/run/docker.sock:Docker 守護進程 (Docker daemon) 默認監聽的 Unix 域套接字(Unix domain socket),容器中的進程可以通過它與 Docker 守護進程進行通信。
  • /srv/gitlab-runner/config:runner的配置文件,可以通過修改這個目錄下的config.toml文件來修改runner配置。host主機中的/srv/gitlab-runner/config/config.toml這個文件被映射到runner中的/etc/gitlab-runner/config.toml文件中,主機上的/srv/gitlab-runner/config/config.toml的修改,會導致runner內部的/etc/gitlab-runner/config.toml做同步修改。
  • 下面通過docker-compose啟動的容器就是流水線的runner,流水線在這個runner里面觸發並開始執行,之后runner會接着創建另外的docker容器,來完成流水線中的構建和單元測試任務。-v 表示掛載,runner通過與主機通信,看似在runner中創建容器,其實是在host主機中創建的. 這個也比較好驗證,因為runner中並沒有並沒有安裝docker,如何啟動容器;另外流水線完成后在host主機中通過docker ps -a可以看到中間生成的臨時容器。

1. 使用docker-compose啟動容器

root# docker-compose up -d
  1. 上面使用docker-compose的方式啟動容器,完全可以換成使用docker run來啟動容器
docker run -d --name gitlab-runner --restart always \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /srv/gitlab-runner/config:/etc/gitlab-runner \ gitlab/gitlab-runner

(5) 在工程中開啟 auto devops 選項 項目設置 –> CI/CD –> General pipelines settings –> Enable Auto DevOps

使用一個具體的 runner

如果這個項目打開了shared runner,里面可能有多個 runner,我們不想用別人的 runner,只想用自己剛注冊的 runner,可以把 shared runner 選項關閉,或者也可以在.gitlab-ci.yml里面的 stage 里面,使用 tags 關鍵字指定特定的 runner 。關閉共享 runner 如下圖:

(6) 編寫 .gitlab-ci.yml 文件 .gitlab-ci.yml 這個文件以 yaml 的格式描述了整個流水線有哪些流程,應該做哪些事。具體語法就不說了,可以Google下。編寫完成以后,這個文件需要放到倉庫的根目錄,受Git版本控制。yaml 格式在編寫時容易出錯,可以在 “Gitlab 側邊欄 CI/CD –> Pipelines”頁面,右上角有個 “CI Lint” 按鈕,進去后輸入編寫的 .gitlab-ci.yml 文件內容,點擊左下角 “Validate” 按鈕。

下面是工程中需要用到的 .gitlab-ci.yml:

注冊runner

root# docker exec -it gitlab-runner gitlab-runner register

runner的配置文件

配置文件路徑: /srv/gitlab-runner/config/config.toml

concurrent = 1 check_interval = 0 [[runners]] name = "docker_runner" url = "https://gitlab.com/" token = "xxxxxxxxxxxxxxxxxxxxxx" executor = "docker" [runners.docker] tls_verify = false image = "docker:latest" privileged = false disable_cache = false volumes = ["/cache"] shm_size = 0 pull_policy = "never" [runners.cache] Insecure = false

正常情況下,注冊完畢后是沒有 pull_policy = “never” 這一行的,可以先手動加上。這放到下面的”docker鏡像的拉取策略“來說。

一次Pipeline的體驗 提交代碼

流水線在執行的時候

流水線運行完畢

流水線總體概況

  1. 其他一些需要注意的地方

(1) 如何節省因為特定容器配置的時間

在.gitlab-ci.yml里面,一個stage可能需要一個特定的容器來做任務,這樣的話,默認會首先從 docker hub 里面 pull,並且如果使用剛 pull 下來的鏡像生成容器,還需要更新源以安裝配置所需環境,這時候可以考慮使用Dockerfile來配置特定的鏡像來做特定任務,在一個 stage 中使用本地鏡像來創建容器(容器可以在秒級啟動,這個時間跟整個構建流程來說是可以接受的)。使用本地鏡像,需要在 /srv/gitlab-runner/config/config.toml 里面添加pull-policy策略,策略有多個可選,可以設置為優先使用本地鏡像,如果本地不存在鏡像,再從docker hub里面pull,pull-policy的使用語法是 pull _policy = “if_not_present”,if_not_present 這個關鍵字好像不能用了,可以直接換成 never,不使用遠程鏡像。

(2) docker 鏡像的拉取策略有三種 never 任何情況下都不從 docker hub 拉取鏡像 always 任何情況下都不使用本地鏡像 if-not-present 優先使用本地鏡像,如果本地不存在該鏡像,會從 docker hub 拉取


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM