參考影片:為你自己學GitLab CICD
為何選擇Jenkins?
目前市面上有三種CI/CD的工具,分別是
- Github Action
- GitLab CI/CD
- Jenkins
而他們各自的難易度如下:
Github Action Jenkins GitlabCICD 三者之比較
| Github Action | GitLab CI/CD | Jenkins |
---|
優點 | 簡單易用,可以透過組合 Actions 來設定 CI/CD 流程。 集成與 GitHub 相當良好,方便地與其他 GitHub 工具整合。
| 功能齊全,涵蓋了版本控制、需求管理、測試、打包、部署等。 內建了測試覆蓋率分析、版本回溯、網路推送等工具。 支援更多的發佈平臺和語言,可以支援更多不同的開發團隊。 | 功能強大,擁有豐富的插件系統,可以滿足多種 CI/CD 需求。 社區活躍,有大量社區插件可以使用。 可以自定義工作流程,靈活應對複雜需求。 |
缺點 | 設定複雜的流程可能會比較困難。 有些功能,比如說高級的權限管理,可能比較弱。 | 較為複雜,可能會花費一些時間來學習和設定。 有些功能,例如高級的安全性,可能會有額外的費用。 | 相對較難學習和使用,不如 GitHub Actions 和 GitLab CI/CD 簡單易用。 配置和管理相對複雜,需要一定的技術支持。 |
為什麼CI/CD重要,它做了哪些事情?
- 在還沒有CI/CD的流程之前,部屬一個web大概是這樣
- CI/CD建立完成後,開發人員只需要專注在任務的完成,而不需要做重複的部屬工作
名詞解析
Pipeline
就是腳本(script)的意思,用來設計CICD的流程,一個常見的pipeline如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
| # 稱之為階段,可以為每個Job分配階段,常見的比如說有測試階段、打包階段、部屬階段等等,每個job都屬於一個階段
stages:
- linter
- testing
- building
- deploy
# 工作流
workflow:
rules:
- if: $CI_COMMIT_BRANCH =="main" #若發生什麼事
when: always #則做什麼事
- when: never #不然則做什麼
# 變數,就是那個變數,可以寫在外層的就是全域變數,寫在Job裡面的就是Job變數
variables:
host_name: "hoxton"
# 稱之為Job
Helloworld: # Job名稱
image: ruby:3.1.2-alpine3.16 #指定要用什麼image來跑,等同於Executor
variables: # Job變數
my_name: "hello kitty"
stage: linter # 這個Job是什麼階段的
script: # 要執行什麼樣的腳本
- echo "hello world, GitLab! $my_name"
- echo "hello world, GitLab! $host_name"
- chmod +x ./run.sh
- ./run.sh
run_unit_tests: # Job名稱
stage: testing # 這個Job是什麼階段的
needs: # 決定Job的順序
- Helloworld # 在這些Job完成後才會去做run_unit_tests的Job
script: # 要執行什麼樣的腳本
- echo "執行單元測試"
before_script: #在執行腳本之前需要執行什麼腳本
- echo "安裝套件"
- echo "設定資料庫連線"
after_script :#在執行腳本之後需要執行什麼腳本
- echo "刪除不必要的檔案"
bad_job: # Job名稱
stage: testing # 這個Job是什麼階段的
script: # 要執行什麼樣的腳本
- echo "bad_job"
build_docker_images: # Job名稱
only: # 指定Job只會在什麼分支執行
- main
stage: building # 這個Job是什麼階段的
script: # 要執行什麼樣的腳本
- echo "building docker images"
deploy_to_production: # Job名稱
except: # 指定Job不在什麼分支執行
- dev # 分支名稱
stage: deploy # # 這個Job是什麼階段的
script: # 要執行什麼樣的腳本
- echo "deploy to production"
|
Runner
大概等同於「要用哪台電腦來執行Pipeline」,以下可以證明
欲執行的script
1
2
3
4
5
| print-location:
tags:
- euno
script:
- echo "$HOSTNAME"
|
若不指定要有用哪台電腦執行,則gitlab會提供,但這時候就是在使用gitlab所提供的服務,免費帳戶每月超過40小時即到達上限,因此需要去註冊一個Runner
可以參考GitLab的官方文件
https://docs.gitlab.com/runner/install/
在Ubuntu系統下
1
2
| curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
|
接著執行
1
| sudo apt-get install gitlab-runner
|
Executor
代表pipeline所運行的環境,可以是shell,也可以是Docker容器,端看目的而定,但千萬要記得,要執行指定的Executor,也要看自己的電腦或VM有沒有這個環境,之前有遇到一個問題是,我在本地起了一個runner,但一直說找不到pwsd的指令,此時要到gitlab-runner安裝的資料夾去調整toml檔案,將shell改成用powershell運行,因為window下沒有pwsd這個指定
如何使用GitLab的CI/CD工具
在專案底下新增.gitlab-ci.yml
的檔案,裡面的格式長這樣
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| # 稱之為狀態
stages:
- linter
- testing
- building
- deploy
# 稱之為Job
Helloworld:
stage: linter
script:
- echo "hello world, GitLab!"
run_unit_tests:
stage: testing
script:
- echo "執行單元測試"
before_script:
- echo "安裝套件"
- echo "設定資料庫連線"
after_script:
- echo "刪除不必要的檔案"
bad_job:
stage: testing
script:
- epaewjdqwe
build_docker_images:
stage: building
script:
- echo "building docker images"
deploy_to_production:
stage: deploy
script:
- echo "deploy to production"
|
把Image推上Gitlab
問題彙整
Got permission denied while trying to connect to the Docker daemon socket at unix:/// …
解決方法:
在vm中輸入
1
| usermod -aG docker gitlab-runner
|
“usermod -aG docker gitlab-runner” 這個指令是用來將 “gitlab-runner” 用戶加入 “docker” 群組。 “-a” 選項用於將用戶附加到指定的群組, “-G” 選項用於指定群組。
這通常是為了允許 “gitlab-runner” 用戶在 GitLab Runner 管理的 CI/CD 流程中執行 Docker 容器。 通過將用戶加入 “docker” 群組,用戶可以在不需要權限升級的情況下運行 Docker 指令。
請注意,“usermod” 指令的確切語法和行為可能因您使用的作業系統而異。 請查閱您的作業系統的文檔以獲取更多信息。
denied : requested access to the resource is denied.
八成是你的push沒有寫好,可以參考下面的樣子
runner會將target檔案刪掉,導致dokcer build不起來
GitLab CICD runner在執行每次作業時(Job),為了保持互相的獨立性,會將Job所產生的檔案,切換至下個檔案時刪除,例如
時會產生/target的資料夾,在下一個Job時就會被刪除,如下
此時可以在pipeline裡面加上這段
1
2
3
| artifacts:
paths:
- temp/*.jar
|
這樣就代表在下一次Job時,這個目錄底下的東西並不會被刪除