DroneCI+Github入坑指北

TheWinds發表於2019-10-04

簡介

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 不要填錯。

urigiT.png

然後註冊應用,記錄下其中的ClientIDClientSecret下面要用到

urFN01.png

docker-compose相關配置

我這裡是通過docker的方式安裝的,docker-compose編排。

安裝Drone需要一個drone-serverdrone-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的授權頁面,進行授權之後就可以看到管理皮膚了 ?

urmY80.png

使用

基本使用基本上參考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的祕鑰鍵值對了,這些祕鑰將在構建過程中被注入。

下面就來試一下

  1. 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
複製程式碼
  1. Drone管理皮膚,啟用倉庫drone_test_pub 並建立一個倉庫級別的Secret a_secret = terces elbakaepsnu

ur8ZPe.md.png

  1. 推送程式碼到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,然後就能進行還原了。。

urGPzj.md.png

urGALq.md.png

克隆私有倉庫

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斷斷續續搞了將近一週的時間,期間因為文件不清楚找不到問題還放棄了幾次?。但是都開始了,就很難放棄,查了很多資料看了一下原始碼後終於整好了。

祝你好運。