主要是參考 這篇文件, 寫的非常完整.
部署用的工具是 envoy , 這是給 php 開發環境的. 如果是別的程式語言, 可以換成 ansible 或其他類似的工具.
這邊將主要說明上面那篇文件的做法與流程, 然後再補充實作時遇到的問題與處理/除錯方式.
文件提供的步驟, 剛開始看好像不是很直覺, 因為有些東西是後來要用到, 在較早的步驟就先準備好. 但是弄清楚整個 CI/CD 流程後, 會發現文件步驟其實是非常流暢的.
以 CI/CD 流程來說大致如下
- 將程式碼 push 到 gitlab
- gitlab-runner 依 .gitlab-ci.yml 設定的 stage 進行
- 第一個 stage 是 unit test
- 第二個 stage 是透過 envoy 來 deploy 到遠端的機器
從文件來看, 前面準備的項目用途如下:
- Unit Test Code : 供 phpunit 測試用的程式, 其實不寫也沒關係, laravel 有預設一個範例, 會讓 phpunit 回傳成功
- Configure the production server , 先準備好要部署的目標機器
a. create new user, 可以 ssh 登入的帳號, 並且對網頁 document root 有讀寫權限
b. add ssh key , 這有兩個地方會用到
一個是讓 enovy 不用密碼連到這台機器, 要將金鑰內容先以變數的方式放在 gitlab 設定裡, 然後在 .gitlab-ci.yml 裡透過變數取得金鑰內容
另一個是讓這台機器可以從 gitlab clone project
c. configuring nginx , 主要是將 document root 先指向預備要部署的路徑 - create container image , 以 php 官方的 image 為主, 再加上 php composer 及 envoy 的自訂 image, 作者連 Dockerfile 都提供了.
作者是將 image 放到 gitlab container register 裡, 這個非必要. 如果要放到 dockerhub 或其他地方, 記得修改 .gitlab-ci.yml 裡的 image 設定即可.
文件中提到一些 CI/CD 流程裡的小技巧蠻實用的 (對我這個新手來說), 例如說
- 將 ssh 金鑰以變數的方式存在 gitlab project 設定裡, 然後在 .gitlab-ci.yml 就可以透過變數取得內容, 避免將金鑰直接放在 git repo 裡.
- 測試用的 mysql 是透過 gitlab-runner 帶起來的, 所以可以另外指定測試用的連線資訊放在 .env.example , 就不會把實際的連線資訊放到 git repo 裡.
實作時的環境, 一台 google cloud engine (gcloud) , 一台 aws ec2 .
gcloud 上以 docker 環境執行 gitlab / gitlab-runner , ec2 則是直接跑 nginx + php-fpm
在過程中, 因為不瞭解以及環境的差異, 有遇到的問題如下
- gitlab-runner 會執行指定的 image 所跑起來的 container 內自動取得 project, 放置的路徑是在 /build/[gitlab 的 username]/[project name]
例如我的 gitlab user 是 duan , project name 是 MyFamily , 所以路徑就是 /build/duan/MyFamily
一開始不知道, 想說為什麼沒有在 .gitlab-ci.yml 做取得 code 的步驟, 就可以進行相關的動作如 composer install - 一開始流程想錯, 想在自訂的 php-fpm image 就先透過 git 取得 code , 後來發現這樣每次都要重新 build image , 還是依文件的流程才對.
- 因為我程式開發環境也是用 docker , 而且和 gitlab 放同一台. 原本想讓測試環境用現成的 mysql container , 但這樣會讓測試與開發環境使用的 database 混在一起, 應該不正確.
- 在 .gitlab-ci.yml 裡設定的 variable 是給測試環境裡執行 mysql container 用的, 而 .env.example 則是在測試時, 在跑 artisan migrate 時用的連線資訊.
因為我不是用官方的 mysql image, 和作者環境不太一樣, 在這邊遇到一些連線問題, 從 gitlab jobs 的資訊可以看到無法連上 mysql.
除錯方式就是自己手動跑一下 docker run -it mysql /bin/bash , 發現第一個問題是這個 image 的 mysql user 不能用 root 去執行, 會有錯誤.
修正後, container 跑起來後, 手動以 mysql 指令來登入, 發現第二個問題.
無法以 mysql user 變數裡指定的名稱做登入, 而是用 root 登入. - 在以 envoy 部署時, 因為之前沒用過 envoy, 看到在 git clone 的步驟出現連線錯誤資訊, 以為是連到目標機器時產生的, 後來才發現這是從目標機器要 clone project 時的權限錯誤.
除錯方式就是自己 docker run 測試用的 image , 然後一步步模擬 .gitlab-ci.yml 裡的動作, 才發現 ssh key 沒問題, 可以連到目標機器, 才發現可能是目標機器在 clone project 時的錯誤 (ssh key 沒設好, 直接改用 http 的 url 來 clone 就沒問題了).
其實還有不少小問題, 都是基於不瞭解整個流程而造成的, 而且一開始也因為不瞭解各流程的相關性, 而不知道該如何除錯, 導致每次改一點設定檔 , 就 push 到 gitlab 看結果, 這還蠻花時間的.
最後看到 CI/CD 整個流程完成, 感覺真是太爽了, 雖然這只是個新手入門的程度而已. QQ
之後近期目標放在幾個方向
- CI/CD 的部份:
a. 用 ansible 取代 envoy , 這樣可以處理其他程式語言的需求
b. 把部署目標的環境改成 docker . 不過這點我還在思考, 這樣做的目的是什麼. - php / Laravel 的部份:
a. 練習多寫 unit test , 這方面我很缺乏.
b. 除了 unit test 外的測試方式.
另外, 隨著程式架構開始複雜, 也會影響 CI/CD 流程上的處理方式, 這就要隨時間慢慢累積經驗了.
沒有留言:
張貼留言