使用 GitLab + Jenkins 實(shí)現(xiàn)自動化構(gòu)建

背景


在測試環(huán)境部署這塊,經(jīng)歷過以下幾個階段:

  • 階段一

    有一臺測試服務(wù)器把項(xiàng)目放上面測試,當(dāng)初也沒有什么相關(guān)的經(jīng)驗(yàn)脸爱,每次改完代碼本地打包上傳到服務(wù)器上辩昆,然后一頓命令啟動項(xiàng)目搜骡,完成了最原始的部署。

    這種方式構(gòu)建和部署全靠人肉,項(xiàng)目簡單的時候還好說,項(xiàng)目一多配置一多( 比如微服務(wù) )中間哪個環(huán)節(jié)粗心出點(diǎn)錯那簡直就是災(zāi)難划乖。

    同時還要專門有人對運(yùn)維相關(guān)的技術(shù)比較了解,不然我不在的時候測試工作就完全停滯了挤土。

  • 階段二

    既然都是重復(fù)工作琴庵,那就整理下步驟寫個腳本:

    1. SVN/Git 拉代碼

    2. Maven 構(gòu)建打包

    3. 重啟 Tomcat

    每次執(zhí)行下腳本就搞定了⊙雒溃看著挺不錯的迷殿,不過實(shí)際執(zhí)行時的情況總會復(fù)雜許多( 服務(wù)器賬號權(quán)限、測試人員對 Linux 的熟悉程度筒占、項(xiàng)目啟動依賴復(fù)雜等等問題 )贪庙。

  • 階段三

    了解到 Jenkins 是個不錯的工具,那就把腳本的內(nèi)容遷移到 Jenkins 上翰苫,不管是開發(fā)還是測試只要在 web 界面上點(diǎn)擊一下按鈕即可完成構(gòu)建部署,很 easy 这橙。

  • 階段四

    容器化:使用 Docker 來部署項(xiàng)目奏窑,這樣就可以干掉原來服務(wù)器上散落各地參差不齊的 Tomcat ( 不同項(xiàng)目依賴不同 ),利用 Docker Compose 對項(xiàng)目進(jìn)行編排屈扎,提供一種規(guī)范的構(gòu)建配置( 同時也是一份文檔 )埃唯,大大減小了后期維護(hù)和交接的成本。

  • 階段五

    上面的階段已經(jīng)能解決日常需求了鹰晨,但是還有一點(diǎn)問題就是每次提交完代碼還要手動去 Jenkins 上發(fā)布墨叛,能更自動點(diǎn)就更好了( 嗯止毕,就是懶 )。

    于是就引出了本文的目標(biāo) —— 自動持續(xù)構(gòu)建漠趁,不需要人工操作 ( 留人工操作用于處理特殊情況 )扁凛。

方案流程


cover
  1. 開發(fā)提交代碼。

  2. 開發(fā)對需要發(fā)布的版本打上 Tag 闯传。

  3. 觸發(fā) GitLabtag push 事件谨朝,調(diào)用 Webhook

  4. Webhook 觸發(fā) Jenkins 的構(gòu)建任務(wù)甥绿。

  5. Jenkins 構(gòu)建完項(xiàng)目可以按版本號上傳到倉庫字币、部署、通知相關(guān)人員等等共缕。

安裝 GitLab


GitLab 官方文檔 已經(jīng)介紹的比較詳細(xì)了洗出,這里不再贅述,下面給出最終調(diào)整過的 Docker Compose 配置( 參考 ):

gitlab:
  image: "twang2218/gitlab-ce-zh:11.0.2"
  restart: always
  hostname: 'gitlab'
  ports:
    - "10022:10022"
    - "10086:10086"
    # postgresql 端口
    - "5432:5432"
  volumes:
    - ./gitlab/data:/var/opt/gitlab
    - ./gitlab/log:/var/log/gitlab
    - ./gitlab/config:/etc/gitlab
  environment:
    GITLAB_OMNIBUS_CONFIG: |
      # 倉庫路徑图谷,填寫宿主機(jī)的域名或 IP
      external_url 'http://192.168.xxx.xxx:10086'
      # ssh 連接端口
      gitlab_rails['gitlab_shell_ssh_port'] = 10022

      # 調(diào)整工作進(jìn)程數(shù)減小內(nèi)存占用翩活,最小為 2
      unicorn['worker_processes'] = 2
      # 設(shè)置時區(qū)
      gitlab_rails['time_zone'] = 'Asia/Shanghai'

      # 郵箱配置
      gitlab_rails['gitlab_email_from'] = '<your_email>'
      gitlab_rails['gitlab_email_display_name'] = '<your_email_name>'
      gitlab_rails['smtp_enable'] = true
      gitlab_rails['smtp_address'] = 'smtp.163.com'
      gitlab_rails['smtp_port'] = 25
      gitlab_rails['smtp_user_name'] = "<your_email_account>"
      gitlab_rails['smtp_password'] = "<your_email_password>"
      gitlab_rails['smtp_domain'] = 'smtp.163.com'
      gitlab_rails['smtp_tls'] = false
      gitlab_rails['smtp_openssl_verify_mode'] = 'none'
      gitlab_rails['smtp_enable_starttls_auto'] = false
      gitlab_rails['smtp_ssl'] = false
      gitlab_rails['smtp_force_ssl'] = false

      # 數(shù)據(jù)庫配置
      gitlab_rails['db_host'] = '127.0.0.1'
      gitlab_rails['db_port'] = 5432
      gitlab_rails['db_username'] = "gitlab"
      gitlab_rails['db_password'] = "gitlab"

      postgresql['listen_address'] = '0.0.0.0'
      postgresql['port'] = 5432
      postgresql['md5_auth_cidr_addresses'] = %w()
      postgresql['trust_auth_cidr_addresses'] = %w(0.0.0.0/0)
      postgresql['sql_user'] = "gitlab"
      postgresql['sql_user_password'] = Digest::MD5.hexdigest "gitlab" << postgresql['sql_user']

      # 備份設(shè)置-保留7天
      gitlab_rails['backup_keep_time'] = 604800
    GITLAB_BACKUPS: "daily"
    GITLAB_SIGNUP: "true"
    GITLAB_ROOT_PASSWORD: "lb80h&85"
    GITLAB_GRAVATAR_ENABLED: "true"

說明:

  • 這里使用 漢化版 鏡像,如果不適應(yīng)可以換回 官方原版 鏡像 gitlab/gitlab-ce:11.0.2-ce.0 蜓萄。

  • 項(xiàng)目初始配置 + 啟動很慢隅茎,需要一段時間,日志中出現(xiàn) Reconfigured 時表示啟動成功嫉沽。

  • 192.168.xxx.xxx 替換為宿主機(jī)的 IP 地址辟犀。

  • 初始管理員賬號密碼: root / lb80h&85自行修改配置文件中的密碼 )。

  • 該配置為 乞丐版 绸硕,內(nèi)存占用 2G+worker_processes 越多內(nèi)存占用越大堂竟,默認(rèn)為 8G )。

  • postgresql 為容器中內(nèi)置的數(shù)據(jù)庫( 賬號密碼: gitlab / gitlab )玻佩,非必要情況就不要暴露端口了出嘹。

  • 郵箱填寫用于 發(fā)送找回密碼和通知 的發(fā)件人賬號( 收不到郵件? )咬崔,不想配郵箱可以刪掉相關(guān)配置税稼,不影響正常使用( 注冊賬號時郵箱可以隨便填 )。

  • 如果指定了 external_url 垮斯,那么其中的端口號就是用于 NGINX 監(jiān)聽的端口號( 如果 nginx['listen_port'] 沒有顯式配置 )郎仆,所以上面配置中的端口映射是 10086:10086 而非 10086:80 。( 參考

    Expose GitLab on different ports

  • 由于安全問題兜蠕,新版本瀏覽器禁用了 10080 端口的訪問扰肌,可以換成其他端口。( 參考

安裝 Jenkins


為了測試方便熊杨,本文中使用 Docker 化的 Jenkins 曙旭,如果需要調(diào)用一些特殊的命令或腳本就不是很方便盗舰,實(shí)際使用過程中可以換成普通版的。

Docker Compose 配置如下:

version: '3'
services:
  jenkins:
    image: jenkins/jenkins:2.456
    container_name: jenkins
    networks:
    - net
    user: "root"
    restart: always
    ports:
    - 9000:8080
    environment:
    - JAVA_OPTS="-Duser.timezone=Asia/Shanghai"
    volumes:
    - /etc/localtime:/etc/localtime:ro
    - ./data:/var/jenkins_home:rw
    - ./backup:/var/jenkins_backup:rw
# 網(wǎng)絡(luò)配置
networks:
  net:
    driver: bridge
    ipam:
      driver: default
      config:
      - subnet: 172.23.0.0/16

說明:

  • 初次啟動請打印日志桂躏,日志中有管理員賬號的初始密碼钻趋,第一次登錄的時候需要用到。

    Jenkins initial setup is required. An admin user has been created and a password generated.
    Please use the following password to proceed to installation:
    
    db7bb60324dc4331bc0dd3e79cc499a5
    
    This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
    
  • 為了方便沼头,使用了 root 賬號啟動 Docker 容器爷绘,如果使用默認(rèn)賬號啟動還需要修改本地目錄( data、backup )的讀寫權(quán)限进倍。

  • 初始化過程中有些插件可能搜不到土至,可以在賬號初始化結(jié)束后再進(jìn)入設(shè)置頁面安裝插件。

配置 GitLab


注冊賬號什么的就不贅述了猾昆,建一個測試項(xiàng)目 test 陶因,隨便 commit 幾條內(nèi)容。

GitLab - 新建測試項(xiàng)目

按下圖步驟創(chuàng)建賬號的 access token 垂蜗,用于 Jenkins 調(diào)用 GitLabAPI 楷扬。

GitLab - 創(chuàng)建 access token

GitLab - 獲取 access token

記下這里生成的 access tokengRCtwVWU8cxwHdxxVZJD ),后面要用到贴见。

配置 Jenkins


  • 安裝插件

    安裝過程可能會失敗烘苹,多試幾次就好了,可以嘗試更新 Jenkins 片部。

    插件 說明
    Git Parameter 用于參數(shù)化構(gòu)建中動態(tài)獲取項(xiàng)目分支镣衡。
    Generic Webhook Trigger 用于解析 Webhook 傳過來的參數(shù)。
    GitLab 用于推送構(gòu)建結(jié)果給 GitLab 档悠。
  • 添加 GitLab 憑據(jù)

    憑據(jù) -> 系統(tǒng) -> 全局憑據(jù) -> 添加憑據(jù)廊鸥,把上面 GitLab 中生成的 access token 填進(jìn)去。

    Jenkins - 添加憑據(jù)
  • 配置 GitLab 連接

    系統(tǒng)管理 -> 系統(tǒng)設(shè)置 -> GitLab 配置項(xiàng)辖所,填入 GitLab 相關(guān)的配置惰说,后面配置項(xiàng)目時用到。

    Jenkins - 配置 GitLab 連接
  • 新建項(xiàng)目 test

    Jenkins - 項(xiàng)目完整配置

    新建一個 Job ( 構(gòu)建一個多配置項(xiàng)目 )缘回,大部分配置可以按上圖照抄:

    • 勾選 參數(shù)化構(gòu)建過程吆视,添加 Git Parameter 類型的參數(shù) ref ,這樣手動點(diǎn)擊構(gòu)建按鈕( Build with Parameters )的時候就可以指定分支進(jìn)行構(gòu)建酥宴。

    • Source Code Management 選擇 Git 揩环,添加項(xiàng)目地址和授權(quán)方式( 賬號密碼 或者 ssh key ,不能選 GitLab API token )幅虑,分支填寫構(gòu)建參數(shù) $ref

    • Build Triggers 選擇 Generic Webhook Trigger 方式用于解析 GitLab 推過來的詳細(xì)參數(shù)顾犹,其中 TokenGUID / UUID 生成一個倒庵。

      用法說明:GitLabWebhook 編輯頁面中點(diǎn)擊 View details 查看調(diào)用詳情褒墨,其中 Request body 就是傳遞給 Jenkins 的參數(shù),利用 JSONPath 語法( 在線測試 )將這個大的 JSON 解析為一個個小的自定義參數(shù)用于后面的構(gòu)建流程擎宝。

      其他觸發(fā)方式中: Trigger builds remotelyJenkins 自帶的郁妈, Build when a change is pushed to GitLabGitLab 插件 提供的,都屬于簡單的觸發(fā)構(gòu)建绍申,無法做復(fù)雜的處理噩咪。

    • 雖然 Generic Webhook Trigger 提供了 Token 參數(shù)進(jìn)行鑒權(quán),但為了避免不同項(xiàng)目進(jìn)行混調(diào)( 比如 A 項(xiàng)目提交代碼卻觸發(fā)了 B 項(xiàng)目的構(gòu)建 )极阅,還要對請求做下過濾胃碾。 Optional filterText 填寫需要校驗(yàn)的內(nèi)容( 可使用變量 ), Expression 使用正則表達(dá)式對 Text 進(jìn)行匹配筋搏,匹配成功才允許觸發(fā)構(gòu)建仆百。

    • Build 內(nèi)容按自己實(shí)際的項(xiàng)目類型進(jìn)行調(diào)整,使用 Maven 插件腳本 等等奔脐。

    • GitLab Connection 選擇上面添加的 GitLab 連接( Jenkins 俄周, Post-build Actions 添加 Publish build status to GitLab 動作,實(shí)現(xiàn)構(gòu)建結(jié)束后反饋構(gòu)建結(jié)果給 GitLab 髓迎。

  • 回到 GitLab 的項(xiàng)目頁面中峦朗,添加一個 Webhook

    http://JENKINS_URL/generic-webhook-trigger/invoke?token=<上面 Jenkins 項(xiàng)目配置中的 token>
    

    觸發(fā)器選擇 標(biāo)簽推送事件 。因?yàn)槿粘i_發(fā)中 push 操作比較頻繁而且不是每個版本都需要構(gòu)建排龄,所以只針對需要構(gòu)建的版本打上 Tag 就好了波势。

    GitLab - 添加 Webhook

    創(chuàng)建完使用 test 按鈕 先測試下,可能會出現(xiàn)下面的錯誤:

    Hook execution failed: URL 'http://192.168.xxx.xxx:9000/generic-webhook-trigger/invoke?token=d63ad84eb18cb04d4459ec347a196dce' is blocked: Requests to the local network are not allowed

    解決辦法: 允許 GitLab 本地網(wǎng)絡(luò)發(fā)送 Webhook 請求 涣雕。

測試效果


可以在 GitLab 上直接添加 Tag 艰亮,不過我覺得用 IDEA 操作更方便點(diǎn),就把代碼拉下來在本地操作挣郭。

IDEA - 針對每個 commit 添加 Tag

使用快捷鍵 Ctrl + Shift + K 調(diào)出 Push 窗口 迄埃,把 Tag 推送到 GitLab 中。

IDEA - Push Tag

回到 GitLab 頁面可以看到觸發(fā)了 Webhook 兑障, View details 查看請求詳情侄非, Response bodytriggered 字段值為 true 則表示成功觸發(fā)了 Jenkins 的構(gòu)建。

如果 triggered 字段值為 false 很可能是 Optional filter 中實(shí)際的 Text 值和正則表達(dá)式 Expression 不匹配( 見 Response bodyregexpFilterTextregexpFilterExpression 的具體值 )流译,比如刪除 Tag 的時候沒有 commitsId 就不會匹配上逞怨。

GitLab - Webhook 觸發(fā)歷史

再看下構(gòu)建結(jié)果:

見上面的 Publish build status to GitLab

GitLab - 查看構(gòu)建結(jié)果 — 流水線

GitLab - 查看構(gòu)建結(jié)果 — commits

注意: 每添加一個 Tag 就會觸發(fā)一次事件福澡,不管是不是一起 push 的叠赦。所以一次 push 多個 Tag 會觸發(fā) Jenkins 進(jìn)行多次構(gòu)建。不過 Jenkins 已經(jīng)做了處理革砸,默認(rèn)串行執(zhí)行任務(wù)( 一個任務(wù)結(jié)束后再執(zhí)行下一個 )除秀,而且在構(gòu)建前有一個 pending 狀態(tài)糯累,此時被多次觸發(fā)會進(jìn)行合并,并取首次觸發(fā)的參數(shù)册踩,如下圖所示:

Jenkins - 同時觸發(fā)多次事件

測試發(fā)現(xiàn)新版 Jenkins 似乎不再合并構(gòu)建了泳姐。

關(guān)于 Tag 的幾點(diǎn)說明


  • 推送 Tag 到遠(yuǎn)端的時候,遠(yuǎn)端已存在( 同名 )的 Tag 不會被添加到遠(yuǎn)端暂吉。

  • 拉取遠(yuǎn)端的 Tag 時胖秒,本地已存在( 同名 )的 Tag 不會添加到本地。

  • 拉取遠(yuǎn)端的 Tag 時慕的,本地不會刪除遠(yuǎn)端已刪除的 Tag 阎肝,需要同步遠(yuǎn)端的 Tag 可以先刪除本地所有 Tag 再進(jìn)行 pull

  • 刪除 Tag 也會推送事件业稼,要做好過濾( 上面配置中已使用 commitsId 字段進(jìn)行過濾 )盗痒。

后續(xù)


通過上面的步驟已經(jīng)初步實(shí)現(xiàn)了想要的效果,還有幾個點(diǎn)后續(xù)可以再考慮下:

  • 上文只包含自動構(gòu)建的內(nèi)容低散,對于項(xiàng)目的部署可以考慮幾種方式:手動選擇指定的版本進(jìn)行發(fā)布俯邓、構(gòu)建任務(wù)結(jié)束后直接觸發(fā)部署任務(wù)、定時部署最新版本( 根據(jù)實(shí)際需求調(diào)整 )熔号。

  • 測試發(fā)版的頻率會比較高稽鞭,會生成大量的 Tag ,可以約定 Tag 的格式引镊,比如用 test 0.0.1 表示觸發(fā)測試環(huán)境的項(xiàng)目構(gòu)建朦蕴,用 online 1.0.0 表示觸發(fā)正式版本構(gòu)建,隔離之后可以方便后續(xù)的維護(hù)和清理弟头。

  • 構(gòu)建部分可以整合 Docker 吩抓,把構(gòu)建結(jié)果打包到 Docker 鏡像中( 代碼版本庫的 Tag 正好可以作為鏡像的 Tag ),再上傳到 Docker 鏡像倉庫( 私服 或者第三方倉庫 )中赴恨,后續(xù)部署就可以直接從鏡像倉庫拉取鏡像直接運(yùn)行了疹娶。

  • 集成自動化測試 ,比如 這個 伦连。

  • 嘗試配置 GitLab 自帶的 CI / CD 雨饺。

相關(guān)


總結(jié)


以上就是對曾經(jīng)踩過的一些坑進(jìn)行的整合,也沒什么好總結(jié)的惑淳《罡郏總之,合理地利用現(xiàn)有工具來解放雙手歧焦,就能有更多時間做其他想做的事移斩!

時間有限一些基礎(chǔ)的步驟就不細(xì)講直接一筆帶過了,方案上可能有些細(xì)節(jié)方面也沒考慮全,歡迎評論留言叹哭。


轉(zhuǎn)載請注明出處: http://www.reibang.com/p/7e8037c63d63

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末忍宋,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子风罩,更是在濱河造成了極大的恐慌,老刑警劉巖舵稠,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件超升,死亡現(xiàn)場離奇詭異,居然都是意外死亡哺徊,警方通過查閱死者的電腦和手機(jī)室琢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來落追,“玉大人盈滴,你說我怎么就攤上這事〗文疲” “怎么了巢钓?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長疗垛。 經(jīng)常有香客問我症汹,道長,這世上最難降的妖魔是什么贷腕? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任背镇,我火速辦了婚禮,結(jié)果婚禮上泽裳,老公的妹妹穿的比我還像新娘瞒斩。我一直安慰自己,他們只是感情好涮总,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布胸囱。 她就那樣靜靜地躺著,像睡著了一般妹卿。 火紅的嫁衣襯著肌膚如雪旺矾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天夺克,我揣著相機(jī)與錄音箕宙,去河邊找鬼。 笑死铺纽,一個胖子當(dāng)著我的面吹牛柬帕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼陷寝,長吁一口氣:“原來是場噩夢啊……” “哼锅很!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起凤跑,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤爆安,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后仔引,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扔仓,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年咖耘,在試婚紗的時候發(fā)現(xiàn)自己被綠了翘簇。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡儿倒,死狀恐怖版保,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情夫否,我是刑警寧澤彻犁,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站慷吊,受9級特大地震影響袖裕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜溉瓶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一急鳄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧堰酿,春花似錦疾宏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至哼绑,卻和暖如春岩馍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背抖韩。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工蛀恩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人茂浮。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓双谆,卻偏偏與公主長得像壳咕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子顽馋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容