CI/CD Pipeline 之 stage: deploy

本系列文是從 iT 邦幫忙鐵人賽系列文章搬至 gitlab-book.tw,鐵人賽撰文時 GitLab 仍為 12.x 版本,因此本系列文內容已有部分過期,本次搬移至此後,會視狀況新增一些補註說明。

本系列文是從 iT 邦幫忙鐵人賽系列文章搬至 gitlab-book.tw,鐵人賽撰文時 GitLab 仍為 12.x 版本,因此本系列文內容已有部分過期,本次搬移至此後,會視狀況新增一些補註說明。 鐵人賽原文網址:https://ithelp.ithome.com.tw/articles/10220724

在昨天我們完成了 CI Pipeline 的 Stage: build,今天接續進度要來處理 Stage: deploy。

如果你忘記目前假想的 CI/CD Pipeline 情境為何,你可以參閱前兩天的文章。

Stage: deploy

在這個 stage 我們要想辦法讓 Artifacts 能被部署至我們的 Server,這裡同樣也沒有標準做法,根據不同的考量,有多種不同的實踐方式,並且其中的執行細節與應用的工具更是千奇百怪。以我們目前的假想情境,這裡介紹兩種不同的實踐方式。

  • 方式一:由 GitLab Runner 擔任檔案傳遞的角色,因此 Runner 會負責取得 Artifacts,然後透過某種方式,將 Artifacts 部署至目標 Server。
  • 方式二:GitLab Runner 只擔任自動化腳本執行者的角色,Runner 會連線至目標 Server,在 Server 上執行某些腳本,完成部署的動作。

方式一

方式一需要解決的問題有:

  1. Runner 如何取得 Artifacts。
  2. Runner 如何將 Artifacts 上傳至目標 Server。

其實在昨天的分享中,我們已經解決了第一個問題「Runner 如何取得 Artifacts」,只要有在負責 build 的 CI Job 中設定 artifacts:,那麼在後續的 stage 中 GitLab Runner 都會自動下載 Artifacts。

compile:
  stage: build
  tags:
    - "build"
  script:
    - ./configure
    - make
  artifacts:
    paths:
      - bin/compiled-code

【新增補充】artifacts: 還有更多不同的 keyword 可以設置,可參閱原廠文件學習更多的使用方式。

第二個問題的解決辦法就很多種了,隨便列舉幾種:

  • 老派作法,先在目標 Server 上架設 FTP,讓 Runner 用 FTP Command 將 Artifacts 上傳到目標 Server 指定路徑。(現在沒人這麼做了吧?)
  • 在目標 Server 上建立特定的 User 與 password,然後開啟 SFTP (SSH File Transfer Protocol) 的功能,接著一樣讓 Runner 用 FTP Command 將 Artifacts 上傳到目標 Server 指定路徑。
  • 在 Runner 設置 ssh key,並在目標 Server 的特定 User 設置 authorized_keys,接著讓 Runner 用 rsync Command 將 Artifacts 上傳到目標 Server 的指定路徑。

從上述列舉的幾種方式中,其實我們可以看出兩個重點:

  • 要用哪一種工具來達成「檔案上傳」的動作?
  • 要如何授權與認證只有 Runner 才有權限可以將檔案上傳到目標 Server 的指定路徑?

因此,依據上述列舉的解決辦法,我們的 .gitlab-ci.yml 這一段可能會變成下面的模樣。

compile:
  stage: build
  tags:
    - "build"
  script:
    - ./configure
    - make
  artifacts:
    paths:
      - bin/compiled-code

deploy-for-testing:
  stage: deploy
  tags:
    - "shell"
  script:
    # 這邊就是以 rysnc 將 artifacts 上傳目標 Server
    - rsync -chavzP --stats /local/file/path user@host:/remote/file/path

當然還有更多不同的作法,且根據做法也可能會延伸更多需要考量的重點,方式一就先介紹到這裡。

方式二

在方式二我們會讓 GitLab Runner 只擔任自動化腳本執行者的角色,Runner 會連線至目標 Server,在 Server 上執行某些腳本,完成部署的動作。

因此方式二需要解決的問題有:

  1. Runner 需要具備「自動化腳本執行者」的能力。
  2. Runner 必須以某種方式與目標 Server 溝通,得以在目標 Server 上執行腳本。
  3. 目標 Server 可能也需要具備某些能力,才能順利的執行自動化腳本。

方式二,艦長就偷懶只舉一種範例,且私心的就用 Ansible 這套 Configuration Management Tool 來解決上述的問題。

既然要採用 Ansible,那麼問題一的解答就是 Runner 這台 Server 上我們必須安裝好 Ansible,及其相依的 Packages,如此 Runner 才算是具備了「自動化腳本執行者」的能力。

問題二,Ansible 是 Agentless 的工具,Ansible 與目標 Server 溝通也是透過 ssh。因此與前面的方式一類似,在目標 Server 上要事先設置好可以 ssh 登入的 User、Password 或 authorized_keys,讓 Ansible 能夠以此與目標 Server 溝通,並且在目標 Server 上執行腳本。當然如果是其他的 Configuration Management Tool,有些就是透過 Agent 來與目標 Server 溝通的,那又會是不同的授權與認證方式。

問題三,以 Ansible 來說,目標 Server 上也必須安裝好 Python 以相依的 Packages,如此一來 Ansible 才能順利的執行自動化腳本。

因此只要你了解 Ansible 是如何安裝與使用的,那麼方式二需要處理的問題,應該都難不倒你。於是我們的 .gitlab-ci.yml 可能會變成下面的模樣。

compile:
  stage: build
  tags:
    - "build"
  script:
    - ./configure
    - make
  artifacts:
    paths:
      - bin/compiled-code

deploy-for-testing:
  stage: deploy
  tags:
    - "shell"
  script:
    # 這邊就變成直接執行 ansible 的腳本 playbook 完成將 artifacts 上傳目標 Server 的動作。
    - ansible-playbook deploy-for-testing.yml

是不是簡潔有力啊?至於在這個 deploy-for-testing.yml 中我們可以有好幾種方式來完成部署的動作:

  • 利用 Ansible 的 module copysynchronize 將 artifacts 上傳目標 Server。(其實也等於類似方式一的 rsync 或 SFTP。)
  • 利用 Ansible 直接在目標 Server 上,透過 GitLab API 直接由目標 Server 去下載存放在 GitLab Server 上的 Artifacts。如此檔案就不是從 Runner 上傳到目標 Server,而是目標 Server 主動去下載檔案。

同樣的這裡也還有更多不同的作法,且根據做法也可能會延伸更多需要考量的重點,方式二也就先到此告一個段落。

小結

今天我們完成了 Stage: deploy 的動作,不過艦長也只是輕描淡寫的介紹,其實這裡面有很多問題是需要解決的,在今天這個 Stage 有哪些關鍵問題需要處理呢?:

  • 你的 CI Server/Worker 是否具備 deploy 的能力?
  • 續上,要用哪一種工具或實踐方式讓 CI Server 具備 deploy 能力?
  • Runner 與目標 Server 之間的授權與認證機制?
  • 目標 Server 是否有哪些前置作業需要完成?或同樣必須某些能力?
  • deploy 的動作,應該要一行又一行的寫清楚在 script: 中?還是應該寫成一個自動化腳本來管理?
  • 續上,如果寫成自動化腳本,那該腳本應該存放在哪裡管理與維護呢?是要放在同一個 Project 內,還是另外獨立一個管理腳本的 Project?
  • 續上,CI Server 又要如何取得這些自動化腳本呢?
  • deploy 真的只需要將 Artifacts 上傳到目標 Server 就夠了嗎?還有沒有哪些額外的動作需要處理?例如是否需要設置 Nginx?是否有 DB Migrate 的動作需要處理?

deploy 說來簡單,但其實裡面也是暗藏許多的細節,例如在今天的文章中艦長就故意沒有涉及上面的最後一個關鍵問題「deploy 真的只是將檔案上傳而已嗎?」。如果你深入去考慮它,就會發現又挖出許多問題需要去解決。這也就是為何現在各大雲端供應商針對 deploy 都會提供各種方便的工作與服務,讓開發者與工程師可以做到一鍵、一個 Command 或一個 yaml 檔案就能完成繁雜的 deploy 動作。

今天就先分享到這裡,我們明天見!

參考資料