簡介
Automate Software Testing and Delivery Drone is a self-service Continuous Delivery platform for busy development teams.
Drone是一個為繁忙的開發團隊提供的自助式連續交付平臺。
除了Drone目前做的比較成熟的還有Gitlab-CI、Jenkins、最近新推出的Github-Actions等。因為Drone佔用的資源比較少,並且喜歡它的容器即外掛的理念,(是我大Golang寫的)所以選擇用它來體驗一下CI。
!但是不得不吐槽的是Drone的文件做的很爛。。所以希望這篇文章能讓你少走彎路?
本文用的是Drone最新版本,不是網上很多1.0之前的版本,根據這個教程走下去應該不會有什麼問題。
配置
整個CI流程需要通過 git hook
來觸發,Drone支援Github、GitLab、Gitea、Gogs、Bitbucket Cloud、Bitbucket Server幾種SCM(source control management),期初我是使用gogs來搭建的,由於https證照問題產生的x509錯誤最終放棄了gogs方案,最終使用的是github+drone。
Github相關配置
Drone和Github互動需要通過OAuth進行鑑權,所以要先申請一個OAuth應用。
開啟github.com
點選頭像,選擇Settings / Developer settings / OAuth Apps
,然後點選New OAuth App
建立OAuth應用。
其中http://cici.xxxx.com
是你部署Drone的域名,注意callback url 不要填錯。
然後註冊應用,記錄下其中的ClientID
和ClientSecret
下面要用到
docker-compose相關配置
我這裡是通過docker的方式安裝的,docker-compose編排。
安裝Drone需要一個drone-server
和drone-runner
,
drone-runner不是必選的,官方不推薦吧runner和server安裝在一個例項上,如果你安裝到一個例項上的話可以設定DRONE_AGENTS_ENABLED=false,drone-server將會作為預設的runner,我這為了演示,runner和server是在一個同伺服器上的。
docker-compose.yml 檔案:
version: '2'
services:
drone-server:
image: drone/drone:latest
container_name: drone-server
networks:
- dronenet # 讓drone-server和drone-agent處於一個網路中,方便進行RPC通訊
ports:
- '10081:80' # Web管理皮膚的入口 PROTO=http 時使用該埠
- '10082:443' # Web管理皮膚的入口 PROTO=https 時使用該埠
- '10083:9000' # RPC服務埠
volumes:
- /var/run/docker.sock:/var/run/docker.sock # docker.sock [1]
- /var/data/drone/:/var/lib/drone # drone資料存放路徑
environment:
- DRONE_AGENTS_ENABLED=true # 使用Runner
- DRONE_GITHUB_SERVER=https://github.com # github的地址
- DRONE_GITHUB_CLIENT_ID=${DRONE_GITHUB_CLIENT_ID} # 上一步獲得的ClientID
- DRONE_GITHUB_CLIENT_SECRET=${DRONE_GITHUB_CLIENT_SECRET} # 上一步獲得的ClientSecret
- DRONE_RPC_SECRET=${DRONE_RPC_SECRET} # RPC祕鑰 [2]
- DRONE_SERVER_HOST=${DRONE_SERVER_HOST} # RPC域名(在一個例項上可以不用)
- DRONE_SERVER_PROTO=${DRONE_SERVER_PROTO} # git webhook使用的協議(我建議http)
- DRONE_OPEN=true # 開發drone
- DRONE_DATABASE_DATASOURCE=/var/lib/drone/drone.sqlite # 資料庫檔案
- DRONE_DATABASE_DRIVER=sqlite3 # 資料庫驅動,我這裡選的sqlite
- DRONE_DEBUG=true # 除錯相關,部署的時候建議先開啟
- DRONE_LOGS_DEBUG=true # 除錯相關,部署的時候建議先開啟
- DRONE_LOGS_TRACE=true # 除錯相關,部署的時候建議先開啟
- DRONE_USER_CREATE=username:TheWinds,admin:true # 初始管理員使用者
- TZ=Asia/Shanghai # 時區
restart: always
drone-agent:
image: drone/agent:latest
container_name: drone-agent
networks:
- dronenet # 讓drone-server和drone-agent處於一個網路中,方便進行RPC通訊
depends_on:
- drone-server
volumes:
- /var/run/docker.sock:/var/run/docker.sock # docker.sock [1]
environment:
- DRONE_RPC_SERVER=http://drone-server # RPC服務地址
- DRONE_RPC_SECRET=${DRONE_RPC_SECRET} # RPC祕鑰
- DRONE_RPC_PROTO=${DRONE_RPC_PROTO} # RPC協議(http || https)
- DRONE_RUNNER_CAPACITY=2 # 最大併發執行的 pipeline 數
- DRONE_DEBUG=true # 除錯相關,部署的時候建議先開啟
- DRONE_LOGS_DEBUG=true # 除錯相關,部署的時候建議先開啟
- DRONE_LOGS_TRACE=true # 除錯相關,部署的時候建議先開啟
- TZ=Asia/Shanghai
restart: always
networks:
dronenet: # 讓drone-server和drone-agent處於一個網路中,方便進行RPC通訊
複製程式碼
- [1] 因為外掛本身也是一個容器,要在容器中(docker-server、drone-runnere)中執行容器。將docker.sock掛載到容器中,可以讓容器通過docker unix socket API得到管理容器的能力。
- [2] 你可以通過
openssl rand -hex 16
這個命令隨機生成祕鑰
.env檔案:
DRONE_GITHUB_CLIENT_ID=your_github_client_id
DRONE_GITHUB_CLIENT_SECRET=your_github_client_secret
DRONE_RPC_SECRET=your_rpc_secret
DRONE_SERVER_HOST=cici.xxxx.com
DRONE_SERVER_PROTO=http
DRONE_RPC_SERVER=rpc.cici.xxxx.com
DRONE_RPC_PROTO=http
複製程式碼
啟動
將docker-compose.yml
和.env
檔案上傳至伺服器同一目錄,然後執行
docker-compose up -d
複製程式碼
啟動服務,一起順利的話開啟你的域名你將會看到
OAuth的授權頁面,進行授權之後就可以看到管理皮膚了 ?
使用
基本使用基本上參考https://docs.drone.io/上面的文件就可以了,沒什麼好說的,下面我主要想說一下Secret管理和私有倉庫的使用方法。
Secret管理
CI工作流編排是寫在倉庫中的.drone.yml
中的,如果我們想進行一些私有的操作(比如ssh_key,用於通知的賬號密碼…)就要把這些敏感資訊寫在yml裡,而這些私有資訊的暴露肯定是不允許發生的。所以這些祕密資訊一般在構建過程中由CI工具注入到環境變數中的。
drone支援多種secret管理方式,最基本和最方便的方式就是直接通過Web後臺進行管理。
開啟Repositories/your_repo_name/settings
找到Secrets選項卡,輸入Secret Name和Secret Value就可以新增Name=>Value的祕鑰鍵值對了,這些祕鑰將在構建過程中被注入。
下面就來試一下
- Github建立專案 drone_test_pub
.
├── .drone.yml
└── main.go
複製程式碼
- main.go
package main
import (
"fmt"
"os"
"strings"
)
func main() {
aSecret := os.Getenv("A_SECRET")
fmt.Println(aSecret)
fmt.Println(reverseString(aSecret))
}
func reverseString(s string) string {
r := []rune(s)
sb := strings.Builder{}
for i := len(r) - 1; i >= 0; i-- {
sb.WriteRune(r[i])
}
return sb.String()
}
複製程式碼
- .drone.yml
---
kind: pipeline
type: docker
name: default
steps:
- name: build
image: golang
environment:
A_SECRET:
from_secret: a_secret
commands:
- echo $$A_SECRET
- go run . > test_secret.txt
- cat test_secret.txt
複製程式碼
- Drone管理皮膚,啟用倉庫drone_test_pub 並建立一個倉庫級別的Secret
a_secret = terces elbakaepsnu
- 推送程式碼到Github檢視構建情況
▶ git commit --allow-empty
[master 0460b0d] test push
▶ git push
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 179 bytes | 179.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To github.com:TheWinds/drone_test_pub.git
0ccca9b..0460b0d master -> master
複製程式碼
4.構建結果
從活動流裡可以看到,已經成功進行了克隆和構建,首先是進行了預設的clone步驟,然後進行的build步驟。
從build的執行結果來看,我們 echo $A_SECRET
的時候得到的是一個掩碼********
,然後在main.go將 $A_SECRET進行反轉後得到了unspeakable secret
說明已經成功得到了注入的Secret。
通過檢視Drone-Runtime的原始碼可以看到,執行的時候對於要顯示在控制檯的內容,都會把Secret Value 加入到string replacer中,統一被替換為掩碼********
。然而這並沒有什麼卵用,通過字串操作就能使其輸出未進行掩碼的Secret,然後就能進行還原了。。
克隆私有倉庫
Drone預設會有一個Clone的步驟,要克隆私有倉庫要把這個步驟關閉。
然後把Github該倉庫的 deploy_key
對應的私鑰設為Secret注入到 SSH_KEY 環境變數中。
接下來建立一個clone的步驟,我這裡使用的是alpine/git的映象,通過echo "$$SSH_KEY" > /root/.ssh/id_rsa
吧私鑰寫入到id_rsa中,git clone 填寫你的私有倉庫ssh地址就可以進行克隆了。
deploy_key相比github的全域性sshkey,可以控制到僅克隆倉庫的許可權,適合進行部署操作,具體怎麼去設定我就不再贅述了
生成一對sshkey可以用
ssh-keygen -t rsa -b 4096 -C "your_email"
這個命令
- .drone.yml
---
kind: pipeline
type: docker
name: default
clone:
disable: true
steps:
- name: clone
image: alpine/git
environment:
SSH_KEY:
from_secret: ssh_key
commands:
- mkdir -p /root/.ssh/
- echo "$$SSH_KEY" > /root/.ssh/id_rsa
- chmod -R 600 /root/.ssh/
- ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts
- git clone -v git@github.com:TheWinds/drone_test.git .
- name: build
image: golang
commands:
- go run . > hello.txt
- cat hello.txt
複製程式碼
結語
DroneCI斷斷續續搞了將近一週的時間,期間因為文件不清楚找不到問題還放棄了幾次?。但是都開始了,就很難放棄,查了很多資料看了一下原始碼後終於整好了。
祝你好運。