私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)

莫問今朝乄發表於2022-02-22
提示:本系列筆記全部存在於 Github, 可以直接在 Github 檢視全部筆記

持續部署概述

持續部署是能以自動化方式,頻繁而且持續性的,將軟體部署到生產環境。使軟體產品能夠快速迭代。

在之前部署 web 專案時,都是手動進行部署

拉取程式碼 ---> 編譯專案 ---> 打包映象 ---> 推送映象倉庫 ---> 伺服器拉取新映象 ---> 停止和移除舊容器 ---> 啟動新容器

這一整套部署步驟枯燥又費時。

持續部署就是使用工具自動處理整套步驟。程式碼在提交之後自動執行整套流程將專案部署到生產環境,省去繁瑣的人工操作。

持續部署整套流程本質上是一個極其簡單的東西。可以拆解為兩個階段

  1. 打包階段: 拉取程式碼 ---> 編譯專案 ---> 映象打包 ---> 推送映象倉庫
  2. 部署階段: SSH 連線伺服器 ---> 拉取新映象 ---> 停止和移除舊容器 ---> 啟動新容器

未使用自動化部署工具時,整套套也可以使用 .sh 指令碼實現半自動化。甚至可以編寫一個小程式,自動連線伺服器實現全自動化。

而所謂的持續部署工具本質上做的也是這麼一件事,只是提供了更強大更豐富的功能。

Drone

持續部署工具一開始打算使用 GitlabGitlab 中直接整合程式碼倉庫和持續部署工具,用起來會方便很多,但部署完 Gitlab 發現小伺服器真心扛不住。

後也考慮過大名鼎鼎的jenkins,查詢資料發現 Jenkins 資源佔用也挺大,最後選擇了一個輕量級的工具 Drone

Drone 也是一個優秀、開源的持續部署工具,具有很高的關注度。https://github.com/harness/drone

不過稍微遺憾的是 Drone 社群不太完善。尤其國內,資料很少。折騰部署時利用 Google 搜尋也耗費了不少時間。

Drone 簡介

Drone 應用由 Server(伺服器)Runner(執行器) 兩種服務構成。

Server(伺服器) 主要負責管理和展示, Runner(執行器) 主要負責執行操作。

Server

Server(伺服器) 負責的工作主要有

  1. 連線整合程式碼倉庫
  2. 提供 web 管理頁面
  3. 管理 Runner

程式碼倉庫

Drone 可以無縫整合多種主流程式碼倉庫,官方給出了具體的使用文件。

私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)

提供 Web 頁面

Server 負責提供 web 管理頁面顯示執行情況。

管理 Runner

Server 服務可以與一個或多個 Runner 連線通訊進行管理。

Runner

Runner(執行器) 是真正執行持續部署操作服務。Runner 執行時會輪詢 Server 來確定執行的操作。

Drone 官方提供了多種型別的 Runner(執行器),用於適配不同的執行環境。

私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)

SSH Runner 型別 Runner 可以使用容器化管理,所以可以使用 Docker Runner 代替。

Drone 提供了 管道(Pipeline) 機制,管道(Pipeline) 機制下一篇介紹

Drone 部署

Database

Drone 資料儲存預設使用 sqlite 資料庫。並且提供支援 postgresmysql

官方文件中強烈建議使用 postgres 而非 mysql。 某些操作在 mysql 未得到優化。 https://docs.drone.io/server/storage/database/

PS: 支援 postgres9.6 及更高版本 、 mysql:5.6 及更高版本

Gitea 配置

在此直接整合之前部署的 Gitea 倉庫, 至於其它倉庫,有興趣的可以查詢文件:https://docs.drone.io/server/overview/

部署 Drone 之前需要先在 Gitea 中新增一個 OAuth 登入金鑰, Drone 使用的 OAuth 方式登入。

登入成功後重定向 URL 地址為 Drone 登入頁。 /login 路由。

PS:注意,此地址必須設定公網可訪問地址。

客戶端 ID客戶端金鑰 儲存。 客戶端 ID客戶端金鑰 需要在 Drone 配置中使用

私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上) 私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)

Dockerfile

version: '3.9'
# 建立自定義網路
networks:
  drone:
    name: drone
    driver: bridge
services:
  # 資料庫服務
  db:
    image: postgres:latest
    container_name: drone_db
    restart: always
    networks:
      - drone # 加入到drone網路
    ports:
      - '7931:5432'
    environment:
      - POSTGRES_USER=drone # PGSQL預設使用者
      - POSTGRES_PASSWORD=drone # PGSQL預設密碼
      - POSTGRES_DB=drone # PGSQL預設資料庫
    volumes:
      - /volumes/drone/db:/var/lib/postgresql/data
  # Drone Server 服務
  server:
    image: drone/drone:2.8.0 # 目前drone最新版本為 2.8.0
    container_name: drone_server
    restart: always
    networks:
      - drone # 加入到drone網路
    ports:
      - '7929:80'
    environment:
      - DRONE_SERVER_PROTO=http # 訪問協議,建立webHooks和重定向
      - DRONE_SERVER_HOST=82.157.55.94:7929 # 主機名稱,建立webHooks和重定向
      - DRONE_RPC_SECRET=e1ad8a7f3dbc68ca9c21bcc949335009 # 與 drone runner 通訊的金鑰
      - DRONE_USER_CREATE=username:yxs970707,admin:true # 管理員賬戶
      - DRONE_DATABASE_DRIVER=postgres # 資料庫型別
      - DRONE_DATABASE_DATASOURCE=postgres://drone:drone@db/drone?sslmode=disable # 資料庫連線
      - DRONE_GIT_ALWAYS_AUTH=true # 使用 oauth 身份驗證資訊拉取程式碼
      - DRONE_GITEA_SERVER=https://gitea.mwjz.live # gitea伺服器地址
      - DRONE_GITEA_CLIENT_ID=2c921d85-e40e-41f8-90e0-c77c383786b5 # gitea 客戶端 id
      - DRONE_GITEA_CLIENT_SECRET=ZVZoRWK6jR5mqgAIm6sB5VX6C2LPK1sYKv4hQWyTdULu # gitea 客戶端 金鑰
      - DRONE_GITEA_SKIP_VERIFY=false # 禁用 gitea 連結時 tls 驗證

    volumes:
      - /volumes/drone/server:/data
      - /var/run/docker.sock:/var/run/docker.sock
    depends_on:
      - db
  # Drone Docker Runner
  runner:
    image: drone/drone-runner-docker:1.8.0 # 目前drone-runner-docker最新版本為 1.8.0
    container_name: drone_runner
    restart: always
    networks:
      - drone # 加入到drone網路
    ports:
      - '7930:3000'
    environment:
      - DRONE_RUNNER_NAME=docker-runner
      - DRONE_RUNNER_CAPACITY=10 # 限制runner可執行的併發管道數量
      - DRONE_RPC_PROTO=http # 訪問drone server 協議
      - DRONE_RPC_HOST=server # 訪問drone server 伺服器地址
      - DRONE_RPC_SECRET=e1ad8a7f3dbc68ca9c21bcc949335009 # 與 drone server 通訊的金鑰
      - DRONE_UI_USERNAME=yxs970707 # Drone Runner 的 UI 使用者賬號
      - DRONE_UI_PASSWORD=yxs970707 # Drone Runner 的 UI 使用者密碼
    volumes:
      - '/var/run/docker.sock:/var/run/docker.sock'
    depends_on:
      - server

Dockerfile 中部署了三個服務:

  • 資料庫(postgres)
  • Server(drone/drone:2.8.0)
  • Runner(drone/drone-runner-docker:1.8.0)

資料庫使用的是 postgres。三個服務之間通訊使用的是自定義 network

PS: 多個應用服務可以共享同一個資料庫服務,也可以建立獨立的資料庫服務。在當前伺服器中,Gitea 應用和 Drone 應用建立了各自獨立的資料庫服務,這種方式會浪費一些伺服器資源。但是維護起來比較方便。
具體採用哪種方案可以根據不同場景選擇

部署 Droneenvironment 屬性有些麻煩,在此簡單介紹下某些屬性。

Server

DRONE_SERVER_PROTO 、 DRONE_SERVER_HOST

這兩個屬性是設定 Webhook 重定向 URL 的訪問協議和主機名稱。 Webhook 在下面會介紹到。

DRONE_RPC_SECRET

此屬性是設定 Server(伺服器)Runner(執行器) 之間通訊的金鑰,Server(伺服器)Runner(執行器) 必須設定相同的金鑰值才允許通訊。

可以在 伺服器(Linux) 中使用 openssl 生成金鑰

openssl rand -hex 16

私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)
DRONE_USER_CREATE

此屬性是設定 Drone 管理員。

注意:username 必須設定為 OAuth 使用者(Gitea 的使用者名稱),否則不具有管理員許可權。

非管理員會少部分功能,例如不許設定 Trusted 屬性

私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)
DRONE_DATABASE_DRIVER 、 DRONE_DATABASE_DATASOURCE

這兩個屬性是設定資料庫型別和資料庫連線。

具體連線配置可以參考官方文件

DRONE_GIT_ALWAYS_AUTH

此屬性是設定 OAuth 登入使用者進行拉取程式碼

預設情況下 OAuth 只作用於登入操作。但儲存庫設定為私有時,需要登入使用者才允許拉取程式碼,此時需要將此屬性設定為 true

可以參考 https://discourse.drone.io/t/fatal-could-not-read-username-for/6198

預設值為 false

DRONE_GITEA_SERVER 、 DRONE_GITEA_CLIENT_ID 、DRONE_GITEA_CLIENT_SECRET

這幾個屬性是設定 Gitea 地址和 OAuth ID、金鑰。

DRONE_GITEA_SKIP_VERIFY

此屬性是設定禁用 GiteaTLS 驗證,

此屬性為 false 時,當 Gitea 使用 HTTPS 協議但證照有問題,會出現授權驗證失敗,報 x509 錯誤。

下圖是將 閘道器(Nginx)Gitea 證照特意處理無效後進行的授權驗證測試。 有興趣的朋友可以自行測試。

私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)

當儲存庫使用 HTTPS 協議但沒有證照情況下,此屬性設定設定為 true 跳過 TLS 驗證。

預設值為 false

Runner

DRONE_RUNNER_CAPACITY

此屬性是設定 Runner(執行器) 併發管道數量

預設值為 2

DRONE_RPC_PROTO 、DRONE_RPC_HOST

這兩個屬性設定通訊 Server(伺服器) 的協議和主機名。 主機名使用 server-name

DRONE_UI_USERNAME、DRONE_UI_PASSWORD

Runner(執行器) 也具有 UI 展示頁面,可以檢視當前執行器的執行資訊。這兩個屬性是設定 UI 展示頁面的使用者名稱稱和密碼

執行部署

使用 Dockerfile 進行部署,大概率不會出現問題,我進行了多次測試,

但部署 Drone 難免會碰到問題,每個人碰到的問題還不盡相同。所以需要善用 Google 查詢

部署成功後訪問,會跳轉到歡迎頁面,點選按鈕就會進行 Gitea 登入

私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)

登入成功後會跳轉到主頁面,主頁面上只有一項,就是 Gitea 中目前的儲存庫(web),這個儲存庫當前為未啟用狀態。

私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)

未啟用情況下進入當前專案會跳轉到 settings 頁面,當前頁面具有一個啟用按鈕,點選就可以啟用此儲存庫

啟用後會向 Gitea 注入一個 Webhook

這個 Webhook 會監聽倉庫的變更情況,當程式碼倉庫發生變化時, Webhook會向 Drone 推送訊息。

Drone 接收到訊息之後便可以執行,這也就是持續部署的第一步。

私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上) 私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上) 私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)

Drone 設定

啟用完畢之後 settings 頁面就會出現很多設定

Protected

此屬性是設定 是否要驗證 配置檔案(.drone.yml) 中的簽名,開啟後簽名驗證錯誤則不允許構建

Trusted

此屬性設定是否允許使用掛載許可權,掛載在之後會介紹。

不開通此許可權,volumes 掛 host path 時報 Linter: untrusted repositories cannot mount host volumes 錯誤

注意:非管理員使用者不具有此屬性。

Auto cancel pushes、Auto cancel running

這兩個屬性是優化操作的屬性。

開啟這兩個屬性,當執行構建任務時,會自動取消之前未執行完畢的構建任務。

當合並多個 commit 時,這個屬性具有很好的效果。

Timeout、Configuration

timeout 是設定構建任務執行的超時時間。

Configuration 是設定配置檔案檔案,預設為 .drone.yml。 這個一般不需要改動。

PS: 注意:配置檔案必須設定根目錄

Secrets

secrets 是用來設定敏感屬性的。

編寫配置時,有些敏感資料需要隱藏,如賬號密碼,這些屬性可以配置 Secrets 使用

私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)

測試執行

現在對 Giteaweb 專案提交就可以觸發 Webhook 傳送訊息,

也可以在 Gitea 中主動觸發 Webhook測試

但當前推送會返回一個 context deadline exceeded (Client.Timeout exceeded while awaiting headers) 錯誤。

這個錯誤是因為根目錄中沒有找到 配置檔案(.drone.yml)

https://discourse.gitea.io/t/client-timeout-exceeded-while-awaiting-headers/4148/4

私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上) 私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)

在根目錄建立 .drone.yml 檔案並新增了一個測試配置,配置檔案中內容下一篇介紹

kind: pipeline # 定義一個管道
type: docker # 當前管道的型別
name: test # 當前管道的名稱
steps: # 定義管道的執行步驟
  - name: test # 步驟名稱
    image: node:latest # 當前步驟使用的映象
    commands: # 當前步驟執行的命令
      - echo 測試drone執行
私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)

提交程式碼,Webhook 會主動推送到 DroneDrone 會成功構建任務。

私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上) 私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)

PS:有可能還是會推送失敗或者構建失敗,可能會發生各種各樣的問題。

在頁面中, 具有兩個 steps,這是因為預設第一個會拉取倉庫程式碼,當然這個操作也可以禁用。

閘道器配置


server {
    #SSL 訪問埠號為 443
    listen 443 ssl http2;
    #填寫繫結證照的域名
    server_name drone.mwjz.live;
    #日誌
    error_log /var/log/nginx/drone/error.log;
    access_log /var/log/nginx/drone/access.log;
    #證照檔案
    ssl_certificate /etc/nginx/conf.d/ssl/drone/drone.mwjz.live_bundle.crt;
    #證照金鑰檔案
    ssl_certificate_key /etc/nginx/conf.d/ssl/drone/drone.mwjz.live.key;

    ssl_ciphers SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!3DES:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    location / {
        proxy_pass http://10.0.24.12:7929;
    }
}

Drone 方面,我沒有找到怎麼修改配置,所以直接使用了暴力方式,重新部署。

部署的時候不需要清理 volume, 不清理重新部署還會保留之前的記錄,當然也可以清理後重新部署。

如果沒有刪除 volume的話,需要在 Gitea 中手動修改一下 Webhook 的推送地址

server:
  image: drone/drone:2.8.0 # 目前drone最新版本為 2.8.0
  container_name: drone_server
  restart: always
  networks:
    - drone # 加入到drone網路
  ports:
    - '7929:80'
  environment:
    - DRONE_SERVER_PROTO=https # 訪問協議,建立webHooks和重定向
    - DRONE_SERVER_HOST=drone.mwjz.live # 主機名稱,建立webHooks和重定向
私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上) 私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上) 私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)

無證照 HTTPS 觸發 Webhook

在部署時碰到這樣一種情況,當 Drone 使用 HTTPS 但是沒有證照情況下,Webhook 推送也會出現 X509 錯誤。

私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上) 私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)

解決這個問題需要設定 Gitea 的配置, 在 /data/gitea/conf/app.ini 配置檔案中設定跳過驗證

[webhook]
SKIP_TLS_VERIFY = true
私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)

也可以在部署 Gitea時直接新增在 Dockerfileenvironment 屬性

#gitea服務
server:
  image: gitea/gitea:latest
  container_name: gitea_server
  restart: always
  environment:
    - GITEA__webhook__SKIP_TLS_VERIFY=true # webhook 跳過 tls 驗證
    - GITEA__webhook__DELIVER_TIMEOUT=10 # webhook 超時時間

相關文章