持續部署概述
持續部署是能以自動化方式,頻繁而且持續性的,將軟體部署到生產環境。使軟體產品能夠快速迭代。
在之前部署 web 專案時,都是手動進行部署
拉取程式碼 ---> 編譯專案 ---> 打包映象 ---> 推送映象倉庫 ---> 伺服器拉取新映象 ---> 停止和移除舊容器 ---> 啟動新容器
這一整套部署步驟枯燥又費時。
持續部署就是使用工具自動處理整套步驟。程式碼在提交之後自動執行整套流程將專案部署到生產環境,省去繁瑣的人工操作。
持續部署整套流程本質上是一個極其簡單的東西。可以拆解為兩個階段
- 打包階段: 拉取程式碼 ---> 編譯專案 ---> 映象打包 ---> 推送映象倉庫
- 部署階段: SSH 連線伺服器 ---> 拉取新映象 ---> 停止和移除舊容器 ---> 啟動新容器
未使用自動化部署工具時,整套套也可以使用 .sh 指令碼實現半自動化。甚至可以編寫一個小程式,自動連線伺服器實現全自動化。
而所謂的持續部署工具本質上做的也是這麼一件事,只是提供了更強大更豐富的功能。
Drone
持續部署工具一開始打算使用 Gitlab
, Gitlab
中直接整合程式碼倉庫和持續部署工具,用起來會方便很多,但部署完 Gitlab
發現小伺服器真心扛不住。
後也考慮過大名鼎鼎的jenkins
,查詢資料發現 Jenkins
資源佔用也挺大,最後選擇了一個輕量級的工具 Drone
Drone
也是一個優秀、開源的持續部署工具,具有很高的關注度。https://github.com/harness/drone
不過稍微遺憾的是 Drone
社群不太完善。尤其國內,資料很少。折騰部署時利用 Google
搜尋也耗費了不少時間。
Drone 簡介
Drone
應用由 Server(伺服器)
和 Runner(執行器)
兩種服務構成。
Server(伺服器)
主要負責管理和展示, Runner(執行器)
主要負責執行操作。
Server
Server(伺服器)
負責的工作主要有
- 連線整合程式碼倉庫
- 提供 web 管理頁面
- 管理
Runner
程式碼倉庫
Drone
可以無縫整合多種主流程式碼倉庫,官方給出了具體的使用文件。
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/57c48418f1506790e9813e00d75624764afbe03a9667eea87326263e401a3254.png)
提供 Web 頁面
Server
負責提供 web 管理頁面顯示執行情況。
管理 Runner
Server
服務可以與一個或多個 Runner
連線通訊進行管理。
Runner
Runner(執行器)
是真正執行持續部署操作服務。Runner
執行時會輪詢 Server
來確定執行的操作。
Drone
官方提供了多種型別的 Runner(執行器)
,用於適配不同的執行環境。
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/31d7e49adc88ef1dde9b8d73fd55650bb9f689116cb0cb454ac2a67654875e13.png)
SSH Runner
型別 Runner
可以使用容器化管理,所以可以使用 Docker Runner
代替。
Drone
提供了 管道(Pipeline)
機制,管道(Pipeline)
機制下一篇介紹
Drone 部署
Database
Drone
資料儲存預設使用 sqlite
資料庫。並且提供支援 postgres
和 mysql
。
官方文件中強烈建議使用 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(上)](https://i.iter01.com/images/f72edc69b46135c35ddcc44731dc386ad5aa0eae0ede8b3f09286685b10f088f.png)
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/2461d202d7b99e14536f6ce0c2b0cb37c33edc32b2a896462ac1e1c6d2077111.png)
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
應用建立了各自獨立的資料庫服務,這種方式會浪費一些伺服器資源。但是維護起來比較方便。
具體採用哪種方案可以根據不同場景選擇
部署 Drone
的 environment 屬性有些麻煩,在此簡單介紹下某些屬性。
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(上)](https://i.iter01.com/images/04f500782a71df03969dcc9c20b2e0ef8181154ef5b32ccfcf6a763367a71528.png)
DRONE_USER_CREATE
此屬性是設定 Drone
管理員。
注意:username 必須設定為 OAuth
使用者(Gitea
的使用者名稱),否則不具有管理員許可權。
非管理員會少部分功能,例如不許設定 Trusted 屬性
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/0e198335d733d345c4b43d2be4bba346009b1fb99035e66007beb5f7fa7a88bb.png)
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
此屬性是設定禁用 Gitea
的 TLS
驗證,
此屬性為 false 時,當 Gitea
使用 HTTPS
協議但證照有問題,會出現授權驗證失敗,報 x509 錯誤。
下圖是將 閘道器(Nginx)
中 Gitea
證照特意處理無效後進行的授權驗證測試。 有興趣的朋友可以自行測試。
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/6512fc348491ee4869b35ae293379a93274e8c0a5bb900f1923abeb35fc17150.png)
當儲存庫使用 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(上)](https://i.iter01.com/images/63da7ff10e45a91b525c97e0807d0fca8fd41b8e6451175fec7ab1734c81e833.png)
登入成功後會跳轉到主頁面,主頁面上只有一項,就是 Gitea
中目前的儲存庫(web),這個儲存庫當前為未啟用狀態。
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/6783ad201552a3a5b230f36a96d082e10d64afd4eb7ba3eee2f8d99ae7c004fe.png)
未啟用情況下進入當前專案會跳轉到 settings 頁面,當前頁面具有一個啟用按鈕,點選就可以啟用此儲存庫
啟用後會向 Gitea
注入一個 Webhook
。
這個 Webhook
會監聽倉庫的變更情況,當程式碼倉庫發生變化時, Webhook
會向 Drone
推送訊息。
Drone
接收到訊息之後便可以執行,這也就是持續部署的第一步。
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/a04325aa77723b534565ef9b45986273b57872dcba6797a130ad1bbaf5893ebb.png)
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/cd5c12cec97954655f57c9a7017763bb5cac40642772b80dab370d24f1e84a32.png)
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/699b851a674d895dec1ad93fd8360d26bb60daa63b7ea2c1baa3d205c116776f.png)
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(上)](https://i.iter01.com/images/800434dc2271efa49bdf981b36d11c0d250747ba002037ce93046c797e847d60.png)
測試執行
現在對 Gitea
中 web 專案提交就可以觸發 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(上)](https://i.iter01.com/images/ca7ab81dee3e102de7b269dd51b94931e754b5cd7edc5deda9ffd45e18dd479f.png)
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/e539640cecf08d20a0d53b6e1d948543662213df7af775f391883dcb11293dac.png)
在根目錄建立 .drone.yml 檔案並新增了一個測試配置,配置檔案中內容下一篇介紹
kind: pipeline # 定義一個管道
type: docker # 當前管道的型別
name: test # 當前管道的名稱
steps: # 定義管道的執行步驟
- name: test # 步驟名稱
image: node:latest # 當前步驟使用的映象
commands: # 當前步驟執行的命令
- echo 測試drone執行
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/e6d2ad5cb039e0c0cb965acfa6276d309c5dcf8bc43f23ce7b68440c10e58b0b.png)
提交程式碼,Webhook
會主動推送到 Drone
,Drone
會成功構建任務。
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/497c28f8dde254bef598806278499d96e9df9599f7c2b21875c993ddf51c3305.png)
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/11656fef5b024ec8c3c0cb772921d7a9b2a851a2375ecfdec3263a31de6eb8ae.png)
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(上)](https://i.iter01.com/images/ce418de38bbbf6c64f6549beccf2c4cb727c9dc11b4f9fb0d6432d8f97d708ce.png)
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/3b5dd26761da28b6d02973bb454746093a4fc6a69e0295ab3c00ec099c9a9cbb.png)
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/f7545a8f8c3065852bb4625931902c0c0b535ee0120b4a42b3c8bb60721561fd.png)
無證照 HTTPS 觸發 Webhook
在部署時碰到這樣一種情況,當 Drone
使用 HTTPS
但是沒有證照情況下,Webhook
推送也會出現 X509 錯誤。
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/a346e1f382904cba3063434163376aaa275815f544645a095d0626992710541e.png)
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/97fa32003948e8fae3e2e3a6d4f172fc9348f509bb13670712d84a9bb87180f3.png)
解決這個問題需要設定 Gitea
的配置, 在 /data/gitea/conf/app.ini 配置檔案中設定跳過驗證
[webhook]
SKIP_TLS_VERIFY = true
![私有化輕量級持續整合部署方案--05-持續部署服務-Drone(上)](https://i.iter01.com/images/1b89bade314cd3b3285bb9651843d87fea801b0a645699a9b61717ee9216bc75.png)
也可以在部署 Gitea
時直接新增在 Dockerfile
中 environment 屬性
#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 超時時間