1. 程式人生 > >什麼是devops,基於Gitlab從零開始搭建自己的持續整合流水線(Pipeline)

什麼是devops,基於Gitlab從零開始搭建自己的持續整合流水線(Pipeline)

一、gitlab 實現的 auto devops

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

(1) 什麼是持續整合

持續整合(Continuous integration,簡稱CI)指的是,頻繁地(一天多次)將程式碼整合到主幹。

它的好處主要有兩個。

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

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

(2) 持續交付、持續部署的概念

持續交付(Continuous delivery)指的是,頻繁地將軟體的新版本,交付給質量團隊或者使用者,以供評審。如果評審通過,程式碼就進入生產階段。

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

(3) 持續整合系統的組成

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

(4) 為什麼要引入auto devops

  1. 部署的環境問題 ;

  2. Dev, QA, Ops的進度問題 ;

  3. 持續整合的好處 :

    • 編譯問題與Bug可以在push或合併之後第一時間發現並解決;

    • 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 實現一個簡單的流水線 (Pipeline)

1. 準備工作

(1) 從docker hub下載gitlab/gitlab-runner映象

root# docker pull gitlab/gitlab-runner

這裡寫圖片描述

(2) 準備一個用來完成stage的映象

多個步驟使用同一個映象來建立容器,也可以根據不同stage準備多個特定的映象。

這裡只是介紹一個使用docker來完成多個簡單stagedemo,就拿一個最簡單的能完成任務的映象,一個簡單的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

這裡寫圖片描述

2. 上面使用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:

這裡寫圖片描述

2. 註冊runner

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

這裡寫圖片描述

3. 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映象的拉取策略“來說。

4. 一次Pipeline的體驗

提交程式碼

這裡寫圖片描述

流水線在執行的時候

這裡寫圖片描述

流水線執行完畢

這裡寫圖片描述

流水線總體概況

這裡寫圖片描述

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

(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 拉取