架設 CI/CD 第一時間會想到老牌的 Jenkins,但他有一些缺點,比如說學習成本高、難以維護、頁面功能複雜等等。
後來逐漸出現 CI/CD 託管服務,如 github action、circle CI,引入 docker 的架構,同時 pipeline 撰寫門檻降低,功能直覺好用,但量多要付費。
有沒有可以白嫖、自己架設的呢?有,就是今天要介紹的 Drone!
目錄
Drone 的優勢
Drone 有什麼優勢呢?在這裡簡單列出幾點:
- 完全 Dockerize
無論是 Drone 系統本身,以及 pipeline 的執行,都在 docker container 裡面運作。當 pipeline 結束後,過程中的資料會自動移除,再也不用像 Jenkins 時常因硬碟爆滿而罷工,增加 devops 的困擾 - UI 簡單直覺
第一次用 Drone 會發現,頁面能按的東西也太少了吧!做的非常精簡,又能滿足使用者日常的需求。若需要作更多設定,Drone 提供工程師最愛的 cli 介面,敲幾下鍵盤就能搞定! - 使用 yaml 檔撰寫 CI/CD 流程
簡單清晰,和 github action 非常相似 - 豐富的 plugin
Drone 提供 Plugins Marketplace,裡面有許多大神已經包好的 docker image,直接使用就能完成相當多的整合,包含 AWS 等等雲端服務。因為已經包成 docker image,也可以自己用 docker 指令來測試該 plugin,之後再寫入 yaml 檔。有需要亦可自己包 image 引入 pipeline 中! - 無痛串接 github、gitlab、bitbucket
只要提供 OAuth token,drone 都能幫你處理好!真正是無痛串接!回頭看隔壁棚的 Jenkins,當年串接的時候就搞了好久…… - 資源消耗極少
Drone 是用 go 寫成,跑了幾天才使用 10 MB,轉頭看隔壁棚用 Java 寫的 Jenkins….
說了這麼多,剩下的靠各位自己去體驗!我們立刻來看怎麼架設!
如何架設 Drone
Drone 的架構分為 server
和 runner
。 server
的職責是提供 web 介面,和監聽 source control management 平台 webhook 的回呼,將 event 依照 .drone.yml
中的定義分配給對應的 runner
去執行。
在文件中提到 runner
有很多種,我們重點看以下三種:
- docker runner
是今天主要示範的 runner,pipeline 跑在 docker container 裡面 - exec runner
某些情境下 pipeline 需要直接跑在 host 裡(如 macOS build code),此時可以在 host 裡安裝 exec runner,並在.drone.yml
中指名 runner 即可 - ssh runner
有時需要 ssh 到遠端機器上作一些操作,此時可透過 ssh runner 來實現。ssh runner 本身也是 dockerize 的 runner。 除了官方提供的 ssh runner,亦可使用 appleboy 大大的 drone-ssh docker runner 來實現,就看大家喜好
以下以串接 github 為例。
啟動 ngrok forwarding (optional)
如果是在本機測試的話,可用以下指令先準備好 ngrok
ngrok http 8080
複製好 ngrok 提供的一次性網址備用
Session Status online
Account xxxxxx (Plan: Free)
Update update available (version 3.1.0, Ctrl-U to update)
Version 3.0.6
Region Japan (jp)
Latency 40ms
Web Interface http://127.0.0.1:4040
Forwarding https://e293-118-161-32-120.jp.ngrok.io -> http://localhost:8080
需特別注意,ngrok 重新啟動後網址會變更,若要維持正常串接,需要手動調整與 github webhook 的設定,建議正式上線時使用固定網域較佳
建立 github OAuth app
drone 的帳號系統直接整合 source control management 平台帳號(如 github login),因此我們需要為 drone 取得 github OAuth apps 的 client id 和 secret
到 github 個人設定頁面,點左下角的 Developer settings
點左邊選項的 OAuth apps,再點綠色的 Register a new application
依序輸入必填項目,其中 Authorization callback URL
必須填入能夠打回 drone server 的網址,並在網域後方加上 /login
。如果是在自己電腦上測試,可以使用 ngrok 等服務取得一次性網址。如果已經有網域則直接填入,並建議用 nginx 為 drone 作反向代理,提供 https 對外溝通。
點按紐 Generate a new client secret
,把 client id 和 secret 複製下來,等一下要放到 docker-compose.yml
檔中
啟動 drone container
回到 console 利用以下 docker-compose.yml
起 drone server 和 drone docker runner:
範例原始碼在此下載:github
version: "3"
services:
drone:
image: drone/drone:2.15
container_name: drone.server
restart: always
ports:
- 8080:80 # 對外的 port 可自由修改,這邊以 8080 為例
networks:
- drone
volumes:
- ./data:/data
logging:
driver: "json-file"
options:
max-size: "1m"
max-file: "3"
deploy:
resources:
limits:
memory: 2G
environment:
DRONE_SERVER_HOST: xxx.xxx.xxx # your domain,填與 github webhook callback url 一樣即可
DRONE_SERVER_PROTO: https # 與外界溝通使用 https
DRONE_RPC_SECRET: xxxxxxxx # 可自行產生一串亂碼作為 drone rpc token
# github
DRONE_GITHUB_CLIENT_ID: <CLIENT_ID> # 填入 github OAuth 提供的 client id
DRONE_GITHUB_CLIENT_SECRET: <CLIENT_SECRET> # 填入 github OAuth 提供的 client secret
# log, for debug use
DRONE_DEBUG: true
DRONE_LOGS_PRETTY: true
DRONE_LOGS_COLOR: true
DRONE_LOGS_TRACE: true
drone-runner:
image: drone/drone-runner-docker:1.8.2
container_name: drone.runner
restart: always
networks:
- drone
volumes:
- /var/run/docker.sock:/var/run/docker.sock
logging:
driver: "json-file"
options:
max-size: "1m"
max-file: "3"
deploy:
resources:
limits:
memory: 2G
environment:
DRONE_RPC_HOST: drone
DRONE_RPC_SECRET: xxxxxxxx # 填入和上面 drone server 一樣的值
DRONE_RPC_PROTO: http # 與 drone server 是透過 docker 內網溝通,使用 http 即可
DRONE_RUNNER_CAPACITY: 5
DRONE_RUNNER_NAME: drone-docker-runner
# log, for debug use
DRONE_DEBUG: true
DRONE_LOGS_PRETTY: true
DRONE_LOGS_COLOR: true
DRONE_LOGS_TRACE: true
networks:
drone:
name: drone
driver: bridge
儲存後 up 一下就可以囉!
docker compose up -d
進入 Drone Web Dashboard
在瀏覽器填入 drone 所在網址(如果是用 ngrok 作代理,填入 ngrok 提供的一次性網址),即可看到以下畫面
點 continue 會跳轉 github 授權畫面
授權後簡單填一下註冊資訊,就能在 drone dashboard 看到你所有的 repo 了!
如何設定 drone CI/CD 與 github 整合?
選擇你想要啟動 drone pipeline 的 repo,切換至 setting 頁面,點選 Activate Repository
按鈕,就….就完成了!drone 會自動幫你處理對應 repo webhook 的設定,轉頭看看 Jenkins 的設定過程,這UX體驗實在太讚了!
啟動後,選項保持預設就能使用,有需要再額外調整
實際寫一份 drone pipeline 試試
在 activate pipeline 的 repo 根目錄下新增 .drone.yml
撰寫 pipeline
這邊就略過 hello world 等級的示範,以我實際的需求為例:想要 tag release 版號後,自動 build code ,並上傳 build artifact 到 github release 中
範例原始碼在此下載:github
---
# 指定 pipeline,且由 docker runner 執行
kind: pipeline
type: docker
name: default
# 如果 docker runner 都跑在 arm64 的機器上(如 m1, raspberry pi),這邊一定要給定 arm64
# 否則預設 linux / amd64 會導致 pipeline 一直 pending
platform:
os: linux
arch: arm64
# 指定 pipeline trigger 的條件
# 這邊想要在 tag release 版號後觸發 pipeline build code 並 upload
# 因此 event 填入 tag
trigger:
event:
- tag
# for build code 使用,clone 時抓 depth = 1 即可,加快速度
clone:
depth: 1
# 這邊開始定義 pipeline 的每個步驟
steps:
- name: build
image: node:14.17.6-buster-slim
environment:
CRX_KEY:
# 重要資訊可以從 web 介面建立 secret 後,將 secret name 填入
from_secret: crx_key
commands:
# 在這個 step, container 要跑的 shell command
- npm install
- npm run build
- npm run crx
- tar zcvf dist.tar.gz dist
- name: publish
# 官方提供的 plugin,可以將 build assets 上傳到 github release
image: plugins/github-release
settings:
api_key:
# 填入在 github 的 personal access token,文後教學如何取得
from_secret: github_api_token
files:
- dist.tar.gz
- crx/dist.crx
# 給定 release name,這邊直接採用 tag 的名稱
# 透過 drone 提供的環境變數,帶入目前 tag name(只有 tag event 才會有)
title: ${DRONE_TAG}
因使用實際的 .drone.yml
為範例,這邊補充一些背景資訊
如何在 pipeline 中指定 platform
使用以下語法在 yml 中給定
platform:
os: linux
arch: arm64
如前面 yml 中註解提到,如果沒有給定 platform,drone 預設是 linux / amd64,若恰好 runner 都不在這平台上,pipeline 就會一直 waiting 下去,讓人誤以為哪裡設定錯誤了,這邊一定要特別注意!(尤其是使用 m1 的朋友們)
如何在 drone 建立 secret
到 repo 下的 Settings > Secrets,點 New Secret,填入 Name 和對應 Value
比如 Name = github_api_token
Value = xxxxx
在 .drone.yml
中用以下語法即可帶入
# 明碼方式帶入值,不安全
api_key: xxxxx
# 使用 drone secret 帶入
api_key:
from_secret: github_api_token
如何取得 github personal access token
和剛剛建立 OAuth Apps 一樣頁面,但改選左邊的 Personal access tokens
,輸入想要的 scope 後即可取得。此 token 是提供 create release 和 upload build assets 使用
如何建立並上傳 build asset 到 github release
使用官方提供的 plugin github-release
image: plugins/github-release
settings:
api_key:
from_secret: github_api_token
files:
- dist.tar.gz
- crx/dist.crx
title: ${DRONE_TAG}
在 api_key
填入 github personal access token, files
填入需要上傳的檔案們,最後 title
給定 release 的名稱。這邊由 drone 提供的環境變數 DRONE_TAG
代入 tag 的名稱。
實際跑 pipeline 看看
.drone.yml
寫好後 commit 進去,並且對某一個 commit 下 tag,就會看到 drone 開始跑起來了!
如何透過 drone cli 控制 drone server
首先依照文件指令在本機安裝 drone cli,並在架設好的 drone web 介面查詢 drone personal token
點畫面左下角帳號的頭像,就能找到自己的 token
到 console 中設定環境變數並測試,若設定正確則回傳帳號名稱與信箱
$ export DRONE_SERVER=https://<your_drone_url>
$ export DRONE_TOKEN=<your_personal_token>
$ drone info
User: Jim
Email: [email protected]
如果覺得每次設定很麻煩,可以寫成一份 sh 檔,需要時 source 他即可
$ nano drone.sh
----------------------
#!/bin/zsh
export DRONE_SERVER=https://<your_drone_url>
export DRONE_TOKEN=<your_personal_token>
----------------------
$ source drone.sh
$ drone info
User: Jim
Email: [email protected]
剩下的指令就讓大家自行去文件中翻翻囉!
drone 還有很多好用的功能可以仔細研究,大家趕緊試試看吧!