CI/CD Pipeline 之 stage: deploy
本系列文是從 iT 邦幫忙鐵人賽系列文章搬至 gitlab-book.tw,鐵人賽撰文時 GitLab 仍為 12.x 版本,因此本系列文內容已有部分過期,本次搬移至此後,會視狀況新增一些補註說明。
On this page
本系列文是從 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 上執行某些腳本,完成部署的動作。
方式一
方式一需要解決的問題有:
- Runner 如何取得 Artifacts。
- 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 上執行某些腳本,完成部署的動作。
因此方式二需要解決的問題有:
- Runner 需要具備「自動化腳本執行者」的能力。
- Runner 必須以某種方式與目標 Server 溝通,得以在目標 Server 上執行腳本。
- 目標 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
copy
或synchronize
將 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 動作。
今天就先分享到這裡,我們明天見!
參考資料
- https://www.ssh.com/ssh/sftp/
- https://www.ssh.com/ssh/authorized_keys/openssh
- https://www.digitalocean.com/community/tutorials/how-to-use-rsync-to-sync-local-and-remote-directories-on-a-vps
- https://docs.gitlab.com/ee/api/jobs.html#download-the-artifacts-archive
- https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html
- https://docs.ansible.com/ansible/latest/modules/synchronize_module.html
- https://docs.ansible.com/ansible/latest/modules/copy_module.html