CI (Continuous Integration) / CD (Continuous Delivery)
這系列 Drone 的文章是我在公司中因為需要優化開發流程而寫的 CI / CD 工具架設過程紀錄,給有需要的人參考,其中很感謝我的架構師夥伴 Jackie-Cheng 的技術協助,幫我一起研究文件、做了許多嘗試,最後才有這系列的文章。
Outline
- 什麼是 CI / CD ?
- CI 流程 - 流程設計
- CI 流程 - 與 Bitbucket 串接
- CI 流程 - 執行程式碼測試
- CI 流程 - 整合至 Docker Hub
什麼是 CI / CD ?
身為一個程式開發者,在產品開發完畢後多少都會碰到環境架設的工作,規模小一點的專案,其實我自己以前也都是手動連上主機去拉最新版本下來更新的。但是稍微有一點規模的專案,很可能同時是會需要不同環境(正式/測試/開發環境)來配合的,所以上述說的舊做法可能就不再適用。
為了節省時間,我們需要引入 CI / CD(持續整合 / 持續發佈 )。
什麼是 CI 呢 ? CI 存在的目的就是為了創造一系列能夠自動化建置、打包、或測試專案的方式,如此一來團隊在開發產品的時候就能夠更頻繁的提交進度,然後系統透過監測每次的變動,就能夠持續地自動測試並驗證以確保品質和穩定性。
在 CI 階段結束,整合完畢確定沒問題之後,就可以透過 CD 流程來把新釋出的版本推送到測試/正式環境上,讓相關專案人員可以直接瀏覽更新後的結果,而這中間從推送新版本、測試程式碼功能及可讀性、到環境測試及部署,完全都是可以持續進行且自動化的,這就是 CI / CD 現在這麼熱門的原因。
我自己比較常聽見的 CI / CD 工具有 Travis CI / Jekins / Drone CI 三套,而 Drone CI 因為架設快速,設定撰寫方便, 又是開源免費的,所以我最近也對這套工具產生興趣,在這系列文章裡面,我打算以Drone為例,把整個建置流程記錄下來與大家分享。
CI 流程 - 流程設計
先構想一下整個 CI 流程, 一個可能的CI 流程如下:
- 發送 Commit / Merge / PR 到 Git Remote Repo
- 該 Repo 偵測到改變,通知 Drone Server 根據 drone.yml 做出相對應的 Task
- 開始跑測試及建置
- 沒問題之後發佈到 Docker Registry (ex. Docker Hub) 上推出新版本
整合新版本到 Docker Hub 之後其實還可以讓 Docker Registry 偵測更變然後自動部署到串接好的機器上,就像 Bitbucket 偵測程式碼的改變然後做動作一樣,不過這應該屬於 CD 的部分,先不深究,附上流程圖:
CI 流程圖
CI 流程 - 與 Bitbucket 串接
CI 通常會跟版本控制的流程綁在一起,而版控則有許多雲端服務,例如 Github / Gitlab / Gitlab 等幾個,透過這些 Git 服務,就能夠讓開發者可以把自己的專案源碼存放在第三方(較安全),這些服務基本上都是免費的,除非有需要使用到比較進階的功能。在這裡我們會用 Bitbucet 為例子來跟自己架設的 Drone Server 做串接來做到第一階段的 CI 部分。
Step 1. Bitbucket OAuth Setting
首先要在Bitbucket個人設定頁面新增一組 OAuth 的 Secret-Key Pair 來讓之後架設的 Drone CI 能夠得到對本人帳戶拉取 Git Repo 的權限。
進入新增頁面之後把Name / Description / Callback Url 寫一寫,記得 Callback Url 要填寫之後預計要架設 Drone Server 的位置後面加上 ‘/login’,才能讓 Drone Server 的 UI 正常運作!填好之後就可以送出了,會拿到一組 Key 跟 Secret,記得記下來。
Step 2. Drone Server 安裝及部署
之後可以連到你預計要跑 CI 測試的機器上,先把 Drone 的 Image 拉下來:
docker pull drone/drone:1.0.0-rc.1
之後就可以把 Drone 的 Container 起起來了,用docker run 搭配對應的參數來啟動 Drone Server :
docker run \
--volume=/var/run/docker.sock:/var/run/docker.sock \
--volume=/var/lib/drone:/data \
--env=DRONE_BITBUCKET_CLIENT_ID={% your-bitbucket-key %} \
--env=DRONE_BITBUCKET_CLIENT_SECRET={% your-bitbucket-secret %} \
--env=DRONE_RUNNER_CAPACITY=2 \
--env=DRONE_SERVER_HOST={% your-drone-server-host %} \
--env=DRONE_SERVER_PROTO={% your-drone-server-protocol %} \
--env=DRONE_AGENTS_DISABLED=true \
--env=DRONE_TLS_AUTOCERT=false \
--env=DRONE_USER_CREATE=username:{% your-repo-host-user%},admin:true \
--publish=80:80 \
--publish=443:443 \
--restart=always \
--detach=true \
--name=drone \
drone/drone:1
上述參數說明 :
- your-bitbucket-key / secret : 在第一步驟時 Bitbucket OAuth 設定完成後取得的 Key Pair
- your-drone-server-host : 在 Bitbucket OAuth 設定時所輸入的 Redirect Url 的 Host,如果使用 IP 位址的話可以把 Port 帶進來
- your-drone-server-protocol : 你的 Drone Server 所使用的傳輸協定,輸入 http 或 https
- your-repo-host-user : 對你的 repository 有控制權的使用者名稱,以這個專案為例,就是 Bitbucket 的使用者名 ,這行等於是讓自己對 Drone Server 有最高的存取權限,使用 GUI 時才能看到完整設定。
順利啟動之後,應該就可以在你所設定的位置看到 Drone 的操作介面了,第一次進入時會跳出跟 Bitbucket 要求權限的確認視窗,之後就不會有了。示意圖:
CI 流程 - 執行程式碼測試
把基本設定做完之後,Drone 在被觸發時,會自己找專案根目錄裡面的 .drone.yml 去做相對應的 Pipeline 動作,一個最基本 Drone Pipeline 的範例如下:
kind: pipeline
name: default
steps:
- name: frontend
image: node
commands:
- npm install
- npm test
...
steps 是一個 list ,用來描述你要做哪些事情。 你可以寫好幾個 step 分別執行不同的動作,每個 step 都會根據你 image 的設定,啟動一個包含你 Repo 的新 container ,然後根據 commands 執行你想做的事情,範例中的 step 就會安裝完專案所需的 module 之後,執行測試,然後結束。
CI 流程 - 自動發布到 Docker Hub
當 Drone Server 上面跑完測試,並且確認沒問題之後,我還希望 Drone 可以幫我自動推到 Ducker Hub 上發出新版本的 Image ,這一樣可以透過 drone.yml 設定檔完成。 加上一個新的 step 並且搭配 drone 的 Docker plugin ,然後把你 Docker Hub 帳號密碼 跟 Repo 名稱填入之後即可。
steps:
...
- name: docker
image: plugins/docker
settings:
repo: your-dockerhub-name / repo-name
target: production
username: herocat
password: 123456
tags: latest
這樣設定好以後每次有新的更動,我就能夠自動地 docker build 然後推新的 image 到我給的位置,這邊的帳號密碼如果沒有搭配其他工具,就只能用明碼寫入,非常不安全,不過這邊只是為了說明所以這樣做。後面我們會講到如何搭配 Drone 內建的機密資訊管理工具來確保專案資訊的隱密性(讓密碼或token這類資訊在 drone.yml 內可以不用明碼紀錄)。
補充一下,如果不想要每次推上新的 Commit 都跑 Docker 相關 task,則可以用 when 關鍵字來限定某些 branch 才會觸發。
steps:
...
- name: docker
image: plugins/docker
settings:
repo: your-dockerhub-name / repo-name
target: production
username: herocat
password: 123456
tags: latest
when:
branch:
- master
- feature/*
OK,目前已經完成我們設計的 CI 流程,在下一章節我會繼續往下補充如何完成 CD 的流程讓專案的新版本能夠自動部署到另外一台 Server 上。
參考文章:
What is CI/CD? Continuous integration and continuous delivery explained