史上最齊全最詳細的Drone自動化教學文件 === ###### tags: `drone` `agent` `devops` `runner` `CI/CD` [TOC] --- ## 概述 Drone可以協助開發者commit code之後,自動將code佈署到主機,並且將佈署結果自動發布通知給相關人員,減少人為執行重複佈署的工作。 但在建立Drone之前,需要清楚該主機作為client或是server的角色,不然很容易搞混SSL/TLS Key的授權。 以下為簡單Drone流程圖 ![](https://i.imgur.com/9GA9bNn.png) 建立Drone自動化,關鍵步驟在於: * 清楚知道現在設定的主機是流程圖的哪個角色 * 確認主機是Server or Client * **建立SSH/TLS Key免密碼登入(最重要!!)** --- ## Drone主機資訊 Drone Server : xxxxx (Core OS) 外網開放IP/Port:xxxx:port 登入資訊: xxxx / xxxx Drone資料夾(使用docker):/docker/drone Drone Runner(Agent) : xxxxx 外網開放IP/Port:xxx:xxxx 登入資訊: xx / xxxxx Drone資料夾(使用docker):/docker/dr-runner --- ## 透過SSH Key建立主機之間的連接 ### Drone Server與Drone Runner Drone Server需要將Trigger訊號送至Drone Runner,所以在SSL Key的角色為Client Side, 因此要將Drone Server的帳號(比如root)的SSL Key加到Drone Runner。 ![](https://i.imgur.com/gHsvaTG.png) --- #### Drone Server 1. 切換成root身份 > sudo su 2. 確認SSL Key(Public Key) > ls ~/.ssh/id_rsa.pub 如果不存在就自己建立一組公私鑰: ``` ssh-keygen -t rsa ``` 不設phrasepassword,後面直接Enter確定。 3. Copy公鑰內容到Server端(Drone Runner) > ssh-copy-id centos@1.2.3.4 接著輸入Runner主機的密碼,日後即可不透過輸入密碼就能登入。 (Drone運作過程中若需要輸入帳密,佈署流程就會被中斷) 4. 測試無密碼登入 測試登入,應該不會出現要求輸入密碼。如果有,則使用手動方式,將公鑰加入到Server主機的authorized_keys。 > ssh centos@1.2.3.4 ==**!!注意!! 在進行SSH KEY配對之前,要確認你是用什麼使用者身份登入對方主機再做KEY配對**== 比如 ```Client: root, Server: centos``` 就要在client side的主機,尋找root的Public Key,並且加到server side的centos使用者的~/.ssh/authorized_keys 如果沒有確認使用者身份,很容易混亂,加錯Key,造成無法登入的問題。 #### Drone Runner 5. 確認使用者是centos 6. 確認SSH Key(Public Key) > vim ~/.ssh/authorized_keys > 確認authorized_keys檔案有加入剛剛ssh-copy-id過來的Drone Server公鑰(id_rsa.pub)內容。 ***若是ssh-copy-id失敗,也可以使用手動複製client side的id_rsa.pub將內容貼到Server side的authorized_keys內*** ***注意!若server與agent為跨外網的兩台主機,drone server需要建立對外的http server,若該主機已經有其他http server,需要更改預設80 port,URL指定至主機對外的IP,並且在Firewall設定Port Forwarding到內部主機。*** ### Runner與Production Runner需要驅動佈署到正式區主機(Production Server),所以也要建立Runner與Production的SSL連結。 ![](https://i.imgur.com/071z9W4.png) #### Drone Runner(Agents) 1. 切換成root身份 > sudo su > 2. 確認SSH Key(Public Key) > ls ~/.ssh/id_rsa.pub 如果不存在就自己建立一組公私鑰: ``` ssh-keygen -t rsa ``` 不設phrasepassword,後面直接Enter確定。 3. Copy公鑰內容到Server端(Production Server) > ssh-copy-id root@5.6.7.8 接著輸入Runner主機的密碼,日後即可不透過輸入密碼就能登入。 (Drone運作過程中若需要輸入帳密,佈署流程就會被中斷) > ssh root@5.6.7.8 測試登入,應該不會出現要求輸入密碼。如果有,則使用手動方式,將公鑰加入到Server主機的authorized_keys。 #### Production Server 4. 切換成root > sudo su 5. 確認SSL Key(Public Key) > vim ~/.ssh/authorized_keys > 確認authorized_keys檔案有加入剛剛ssh-copy-id過來的runner公鑰(id_rsa.pub)內容。 ***若是ssh-copy-id失敗,也可以使用手動複製runner的id_rsa.pub將內容貼到Server side的authorized_keys內*** --- ### Github(Bitbucket)與Production Server Code佈署上去的Production Servers(以下簡稱PD)也需要與版控平台(Github, Bitbucket)建立佈署權限,相當於開發者將完成測試的codes從 Github Pull下來的動作,因此在自動佈署之前,需要完成從PD可自動從Github Pull下來的權限(不詢問密碼)。 ![](https://i.imgur.com/BLzdbsC.png) #### Bitbucket 至Bitbucket專案資料夾,點擊Clone按鈕取得 > xxxxx@bitbucket.org:/xxxxplatform/xxxx.git 的專案連結 #### Production Server 在需要的佈署的程式資料夾執行以下指令: ```shell= $ git init $ git remote add origin master $ git remote set-url origin abcdefg@bitbucket.org:/platform/xxxx.git $ sudo ssh -T abcdefg@bitbucket.org ``` 在最後一步輸入你的Bitbucket密碼就可完成權限開通,之後在Drone對此資料夾做Pull的動作都不用再人工輸入密碼。 ### Github(Bitbucket)與Drone Server Github(Bitbucket)的專案一旦收到更新,就會執行.drone.yml文件的內容,所以必須建立Runner與Github之間的金鑰連接,在執行過程才不會出錯。 ![](https://i.imgur.com/hHAPWAX.png) #### Bitbucket 使用OAuth2.0與Bitbucket建立連結 1. 登入Bitbucket 2. 點擊你在Bitbucket的個人帳號選單 -- All workspaces 3. 選擇你個人的Workspaces ![](https://i.imgur.com/hXq2nNF.png) 4. 點擊Settings ![](https://i.imgur.com/3P8f6rR.png) 5. 點選OAuth consumers -- Add consumers ![](https://i.imgur.com/uBG7mQ3.png) ***參考設定*** 注意,要預先設定給Drone Server使用的URL域名,如果只是要臨時測試用可使用ngrok 可以參考 [這裡](https://vagrantpi.github.io/2018/09/28/drone-101/) 6. 紀錄Key and Secret 7. 撰寫專案的.drone.yml 在你要佈署測試的專案內建立一個新檔案,檔名為.drone.yml,此檔案使用yaml格式撰寫如何將程式pull, test and deployment的流程。 ##### 設定Yml文件 專案pipeline的yml文件可參考官方文件 [這裡](https://docs.drone.io/pipeline/overview/) 本案例以整合docker使用為主。並且使用appleboy/drone-ssh的Drone套件,將佈署流程寫在pipeline的yml檔內。 注意在yml文件內,ssh的登入使用key secret,避免密碼以明碼方式顯露。 ![](![](https://i.imgur.com/RnkLNo4.png) ***請注意:在主機之間盡量不要用明碼顯示登入密碼,透過後台 UI 介面將密碼或者是金鑰內容儲存在 Secret 設定頁面,就可以使Runner與被佈署主機之間的通訊不因帳密問題而中止*** ##### 參考設定(以包網為例) .drone.yml file: ```shell=yaml kind: pipeline name: Deploy_Bao clone: depth: 20 workspace: path: /docker/drone-runner steps: - name: ssh-deploy-WebA image: appleboy/drone-ssh settings: repo: /aaaplatform/xxxx host: - 1.2.3.4 username: root key: from_secret: ssh_key port: 2201 timeout: 60s command_timeout: 2m script: - cd /home/www/xxxx/ - git fetch --all - git reset --hard origin/master - git pull origin master when: branch: - master - name: ssh-deploy-WebB image: appleboy/drone-ssh settings: host: - 1.2.3.4 username: root key: from_secret: ssh_key port: 2202 timeout: 60s command_timeout: 2m script: - cd /home/www/xxxx - git fetch --all - git reset --hard origin/master - git pull origin master when: branch: - master - name: ssh-deploy-WebC image: appleboy/drone-ssh settings: host: - 1.2.3.4 username: root key: from_secret: ssh_key port: 2203 timeout: 60s command_timeout: 2m script: - cd /home/www/xxxx - git fetch --all - git reset --hard origin/master - git pull origin master when: branch: - master - name: ssh-deploy-AWS_Stage image: appleboy/drone-ssh settings: host: - 192.168.1.1 username: root key: from_secret: ssh-key-stage port: 22 timeout: 60s command_timeout: 2m script: - cd /var/www/html/xxxx - git branch - git checkout stage - git fetch --all - git reset --hard origin/stage - git pull origin stage when: branch: - stage - name: telegram image: appleboy/drone-telegram pull: true settings: token: from_secret: tele_token to: from_secret: tele_to format: markdown message: > {{#success build.status}} ✅ Build #{{build.number}} of `{{repo.name}}` succeeded. 📝 Commit by {{commit.author}} on `{{commit.branch}}`: ``` {{commit.message}} ``` 🌐 {{ build.link }} {{else}} ❌ Build #{{build.number}} of `{{repo.name}}` failed. 📝 Commit by {{commit.author}} on `{{commit.branch}}`: ``` {{commit.message}} ``` 🌐 {{ build.link }} {{/success}} when: status: - failure - success trigger: event: - push - pull_request - tag ``` #### Drone Server 1. 在docker container目錄建立.env文件 2. 將剛剛從Bitbucket紀錄的Key, Secret紀錄到.env file ***TIPS:${DRONE_RPC_SECRET} 值可以用以下指令來產生 Token :*** `openssl rand -hex 16` 之後把 .env 檔案放在與docker-compose.yml同一層的目錄即可。 #### 參考設定 ##### .env file: (記得要放在跟docker-compose同一層目錄下) ```shell=yaml DRONE_SERVER_HOST=drone.domain:1234 DRONE_SERVER_PROTO=http DRONE_RPC_SECRET=111111111111 DRONE_BITBUCKET_CLIENT_ID=oooooooooooooo DRONE_BITBUCKET_CLIENT_SECRET=12345678qwertyuasfdghzxcv ``` ##### 安裝Drone Server 在設定Drone Server之前必須先安裝,安裝部份請參閱下個章節。 --- ## 建立Drone Server(Server) Drone Server主機安裝好Linux OS(本案例使用Core OS),並且安裝好docker-compose環境。 ### 安裝Docker-compose * docker安裝過程請參考 [這裡](https://hackmd.io/d__Zwa5JQR2U_DlqCyQFWQ#%E5%AE%89%E8%A3%9DDocker-%E7%9B%B8%E9%97%9C%E5%A5%97%E4%BB%B6) * docker-compose文件請參考 [這裡](https://docs.docker.com/compose/) ### 撰寫docker-compose.yml 本文件建立Drone Server以撰寫docker-compose.yml文件為啟動方式,yml文件內主要紀錄項目為: * DRONE_SERVER_HOST:Drone Server的IP或URL * DRONE_SERVER_PROTO:使用的協定,這裡使用http(亦可用https,但要開443 port) * DRONE_RPC_SECRET:與runner溝通的key(可自訂) * ==DRONE_BITBUCKET_CLIENT_ID:在Bitbucket,個人Setting的OAuth consumers顯示的Key值== * ==DRONE_BITBUCKET_CLIENT_SECRET:在Bitbucket,個人Setting的OAuth consumers顯示的Secret值== ![](https://i.imgur.com/tLcLhNs.png) #### 參考設定 Docker Server yaml file: ```shell=yaml version: '2' services: drone-server: container_name: drone-server image: drone/drone:1 ports: - 80:80 volumes: - ./:/data restart: always environment: - TZ=Asia/Taipei - DRONE_SERVER_HOST=${DRONE_SERVER_HOST} - DRONE_SERVER_PROTO=${DRONE_SERVER_PROTO} - DRONE_RPC_SECRET=${DRONE_RPC_SECRET} - DRONE_BITBUCKET_CLIENT_ID=${DRONE_BITBUCKET_CLIENT_ID} - DRONE_BITBUCKET_CLIENT_SECRET=${DRONE_BITBUCKET_CLIENT_SECRET} - DRONE_LOGS_TRACE=true - DRONE_LOGS_PRETTY=true - DRONE_LOGS_COLOR=true - DRONE_RUNNER_CAPACITY=10 ``` .env file: ```shell=yaml DRONE_RPC_SECRET=111111111111 DRONE_BITBUCKET_CLIENT_ID=oooooooooooooo DRONE_BITBUCKET_CLIENT_SECRET=12345678qwertyuasfdghzxcv ``` ### 啟動Docker-compose ``` docker-compose up -d #啟動Drone Server Container docker-compose logs #檢查log是否有出現錯誤 docker ps -a #檢查container運作情況 ``` ### Drone Server的頁面設定 若前面設定都沒有出現錯誤,輸入 drone.domain.com:1234 應該可以見到Drone Server的UI頁面,同時頁面會跟Bitbucket網站連結,輸入你在Bitbucket的帳號就可見到你有權限的專案列表。 ![](https://i.imgur.com/ogStDDK.png) 先點按Sync按鈕,讓Drone Server與Bitbucket同步。 #### 啟動專案 一開始所有專案都處於沒有Active狀態,可點進一個你需要使用Drone佈署的專案並且啟動它。 ![](https://i.imgur.com/sVfh7AX.png) #### Drone YAML檔名 在專案內頁面,Setting - Configuration欄位填入.drone.yml檔案名稱,此名稱可更改,唯必須以.檔名開頭。 ![](https://i.imgur.com/MoGPspD.png) ##### 寫入Drone Secrets 將key secret寫入至drone server * **注意!這部份是Drone能否成功推送的關鍵,必須將.drone.yml檔內引用的Key值寫入此欄位。** 1. **將Runner的root key(Private私鑰 ~/.ssh/id_rsa)填入此欄位,並且Secret Name要符合.drone.yml檔內的名稱** ![](https://i.imgur.com/4eDS92Q.png) * Secret Name為 .drone.yml的from_secrets值 * Secret Value為 Runner Server的私鑰值 **是否使用root key取決於你在.drone.yml使用的container image,因為我使用的是appleboy/drone-ssh,預設使用者是root,所以必須使用root的私鑰而非其他使用者。** 2. 將tele_token 與 tele_to 的Key值寫入(.drone.yml的Telegram Token) 3. 如果寫入內容錯誤,就Delete再次重作Add A Secret --- ## 建立Drone Runner Server(Agent) Runner Server主要負責處理codes佈署與測試,Drone Server與Github or Bitbucket連結並且Trigger,再將需求以Webhook方式丟給Runner處理。 同樣準備一台主機安裝好Linux OS(本案例使用AWS EC2),並且安裝好docker-compose環境, ### 安裝Docker-compose [參考上方安裝過程](https://hackmd.io/EPZwS2N1SeStTaEwTglMUw?both#%E5%AE%89%E8%A3%9DDocker-compose) ### 設定Yml文件 ***參考設定*** Docker Runner Server yaml file: ```shell=yaml version: '2' services: drone-runner: container_name: dr-runner image: drone/drone-runner-docker:1 restart: always volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - DRONE_RPC_HOST=${DRONE_RPC_HOST} - DRONE_RPC_PROTO=${DRONE_RPC_PROTO} - DRONE_RPC_SECRET=${DRONE_RPC_SECRET} - DRONE_RUNNER_CAPACITY=3 - DRONE_RUNNER_NETWORKS=drone-runner_default - DRONE_RUNNER_NAME=runner_dev ``` .env file: ```shell=yaml DRONE_RPC_HOST=drone.domain.com:1234 DRONE_RPC_PROTO=http DRONE_RPC_SECRET=111111111111 ``` * ${DRONE_RPC_HOST} 填入給Drone使用的URL * ${DRONE_RPC_SECRET} 填入跟Drone Server一樣的值,Server與Agent靠這個Key認證溝通 ### 啟動Drone Runner(Agent) ``` docker-compose up -d #啟動Drone Server Container docker-compose logs #檢查log是否有出現錯誤 docker ps -a #檢查container運行狀態 ``` --- ## 測試自動化佈署 ### 手動測試佈署 進入PD主機的專案資料夾,進行人工測試佈署: ```shell= $ git fetch --all $ git reset --hard origin master $ git push origin master ``` 確認可成功Pull之後,再更新程式Push到Bitbucket上,由版控端進行Drone自動化作業。 ### 更新程式 1. 確認要更新的專案已在Drone Server被Activate 2. 更新專案的程式 3. Push到Bitbucket 4. 會發現Bitbucket的專案頁面多了Builds欄位,綠色打勾就代表build成功 ![](https://i.imgur.com/5ojeCUE.png) ### 觀察Drone Server 一旦Bitbucket程式庫有更新,便會立即執行專案pipeline,這時進入drone server的頁面會發現顯示圖示改變了 變成黃色(寶貝球?),代表該專案正在running(CI/CD Process) 點進頁面可看到專案正在依照.drone.yml文件執行 ![](https://i.imgur.com/HpOY9q6.png) ### 觀察佈署結果 一旦佈署成功,會全部顯示綠燈 如果佈署失敗,查看佈署過程的log,再去檢查相關的設定 ![](https://i.imgur.com/y9CAuwj.png) **TIPS: 如果想要將佈署成功/失敗都發出通知,除了透過email以外也可以使用Telegram外掛,將通知發布到Telegram** **TIPS: 如果是主機之間的ssh or SSL Key設定問題,可透過手動執行指令,模擬自動化,便比較有可能找出問題原因** --- ## 參考文件 [git push 免帳號密碼 | ssh key](https://aben20807.blogspot.com/2018/03/1070302-git-push-ssh-key.html) [ssh-key添加之后依旧需要密码输入Bug的解决](https://www.cnblogs.com/marility/p/8400354.html) [drone.yml參考官方文件](https://docs.drone.io/) [Drone Secret 安全性管理](https://blog.wu-boy.com/2017/11/drone-secret-security/) [三分鐘學會Drone ,CI/CD輕鬆上手!](https://www.tpisoftware.com/tpu/articleDetails/1884)