iT邦幫忙

2025 iThome 鐵人賽

DAY 20
0
Cloud Native

從 Docker 到 K8s:我的 30 天雲原生筆記系列 第 20

Day 20: 撰寫 .gitlab-ci.yml:打造第一條 Pipeline

  • 分享至 

  • xImage
  •  

哈囉大家好,歡迎來到 CI/CD 自動化的第三天!

在昨天的 Day 19,我們成功地在 Kubernetes 叢集中,部署並註冊了一位隨時待命的 GitLab Runner。它現在正等待著,準備接收來自 GitLab 的任何指令。

今天,我們的任務就是為它提供一份清晰的工作指示。這份指示,就是我們專案中最重要的自動化藍圖 —— .gitlab-ci.yml 檔案。

我們今天會學習設定檔內的語法,先專注於實現 CI (持續整合) 的部分:

  1. Test Stage:自動為前端和後端執行測試與檢查。
  2. Build Stage:自動將前端和後端的程式碼,建置成標準化的 Docker Image。

Part 1:.gitlab-ci.yml 的基本結構

.gitlab-ci.yml 是一個放置在你專案根目錄下的 YAML 檔案。GitLab 會在每一次 git push 時,自動讀取這個檔案,並根據裡面的內容來執行 CI/CD 流程。

我們先來看看這份設定檔的整體結構與一些重要的「全域設定」。

# .gitlab-ci.yml

# --- 全域變數定義 ---
variables:
  # Harbor Registry 設定
  HARBOR_REGISTRY: "harbor.rehearaudio.com"
  HARBOR_PROJECT: "rehear-dev"

  # Docker Image 名稱模板
  BACKEND_IMAGE: "${HARBOR_REGISTRY}/${HARBOR_PROJECT}/ota-backend"
  FRONTEND_IMAGE: "${HARBOR_REGISTRY}/${HARBOR_PROJECT}/ota-frontend"

  # 使用 GitLab 預定義變數,讓每個 commit 都有唯一的 Image Tag
  IMAGE_TAG: "${CI_COMMIT_SHORT_SHA}"

# --- Pipeline 階段定義 ---
stages:
  - test
  - build
  - deploy:dev
  - deploy:staging
  - deploy:prod
# ... 後續是各個 Job 的定義 ...
  • variables:定義了可以在所有 Job 中共用的全域變數。這讓我們可以集中管理 Image 名稱、倉庫位址等資訊,非常方便。$CI_COMMIT_SHORT_SHA 是 GitLab 提供的預定義變數,代表當次 commit 的前 8 位 hash 值。
  • stages:我們定義了 test, build, deploy:dev 等多個階段,並規定了它們的執行順序。今天,我們將專注於前兩個階段。

Part 2:第一階段:撰寫 Test Jobs

現在,我們在 stages 定義的下方,加入我們的 test 任務。一個好的 CI 流程,第一步永遠是確保程式碼的品質。

# .gitlab-ci.yml (接續)

# --- 測試階段 ---
test:backend:
  stage: test
  image: golang:1.21 # 為 Go 專案選擇合適的執行環境
  tags:
    - docker # 選擇我們在 K8s 中設定的 Runner
  before_script: # 在主要 script 執行前的前置作業
    - cd backend
  script:
    - go mod download
    - go test -v ./...
  rules: # 定義此 Job 何時被觸發
    - if: $CI_COMMIT_REF_NAME == "main" || $CI_COMMIT_REF_NAME == "develop"

test:frontend:
  stage: test
  image: node:18-alpine
  tags:
    - docker
  before_script:
    - cd frontend
  script:
    - npm ci
    - npm run lint
    - npm run type-check
  rules:
    - if: $CI_COMMIT_REF_NAME == "main" || $CI_COMMIT_REF_NAME == "develop"

這段設定很直觀:

  • image: 我們為不同任務選擇了最合適的 Docker Image 作為執行環境 (golang vs. node)。
  • script: 定義了該任務需要執行的核心指令,例如跑測試或語法檢查。
  • rules: 讓我們可以精確控制 Job 的觸發時機。這裡我們設定為:只有當程式碼被推送到 maindevelop 分支時,才執行這些任務。如果測試失敗,Pipeline 就會中止,確保有問題的程式碼不會被建置。

Part 3:第二階段:撰寫 Build Jobs 與 Kaniko

當所有測試都通過後,下一步就是將我們的程式碼,建置成可部署的 Docker Image。

YAML

`# .gitlab-ci.yml (接續)

# --- 建置階段 ---
build:backend:
  stage: build
  image:
    name: gcr.io/kaniko-project/executor:v1.19.0-debug # 使用 Kaniko 來建置 Image
    entrypoint: [""] # 覆寫預設的 entrypoint
  tags:
    - docker
  script:
    # 準備 Kaniko 需要的 Docker 認證檔,指向我們的 Harbor
    - mkdir -p /kaniko/.docker
    - echo "{\"auths\":{\"${HARBOR_REGISTRY}\":{\"auth\":\"$(echo -n ${HARBOR_USERNAME}:${HARBOR_PASSWORD} | base64)\"}}}" > /kaniko/.docker/config.json
    # 執行 Kaniko executor
    - /kaniko/executor
      --context ${CI_PROJECT_DIR}/backend
      --dockerfile ${CI_PROJECT_DIR}/backend/Dockerfile
      --destination ${BACKEND_IMAGE}:${IMAGE_TAG} # 推送到 Harbor
      --cache=true # 啟用快取
  rules:
    - if: $CI_COMMIT_REF_NAME == "main" || $CI_COMMIT_REF_NAME == "develop"`

build:frontend 的任務與此類似,只是 contextdestination 不同。

為什麼要用 Kaniko?

你可能會問,為什麼不直接用 docker build 指令?

  • 問題:在 K8s Pod 中執行 docker build,會涉及到複雜的 Docker-in-Docker (dind) 設定,既不安全也不高效。
  • Kaniko,是一個由 Google 開發的、專門用來在非特權容器(例如 K8s Pod)中安全、高效地建置 Docker Image 的工具。
  • script:我們不再執行 docker build,而是執行 Kaniko 的 /kaniko/executor。我們透過參數告訴它 Dockerfile 的位置 (-dockerfile)、建置上下文 (-context),以及最重要的——建置完成後要將 Image 推送到哪裡 (-destination)。
  • 認證echo "..." > /kaniko/.docker/config.json 這一長串指令,其實只是在動態地產生一個讓 Kaniko 可以登入我們私有 Harbor 倉庫的認證檔案。$HARBOR_USERNAME$HARBOR_PASSWORD 是我們需要在 GitLab 專案中設定的受保護的 CI/CD 變數

Part 4:觸發你的第一條 Pipeline

設定檔寫好了,現在就是見證奇蹟的時刻!

  1. 設定 CI/CD 變數
    • 前往 GitLab 專案的 Settings > CI/CD > Variables
    • 新增兩個變數:HARBOR_USERNAMEHARBOR_PASSWORD,並填入你登入 Harbor 的帳號密碼。建議將它們設定為 ProtectedMasked,增加安全性。
  2. Commit & Push
    • .gitlab-ci.yml 檔案 commit 並 push 到 developmain 分支。
  3. 前往 GitLab UI
    • 打開 GitLab 專案,點擊 Build > Pipelines,會看到一條新的 Pipeline 已經被觸發!

結論

我們的自動化生產線,現在已經成功地將我們的程式碼,轉化成了存放在 Harbor 倉庫中的、可隨時部署的 Docker Images。

我們已經完成了 CI 的部分。在接下來的文章中,我們就要來完成 CD 的最後一哩路:學習如何撰寫 deploy 階段的 Job,讓 GitLab Runner 自動地使用 Helm,將這些熱騰騰的新版 Image,部署到我們的 Kubernetes 叢集中! 明天見!


上一篇
Day 19: 設定 GitLab Runner on K8s
下一篇
Day 21: Harbor Registry:建立我們自己的私有映像檔倉庫
系列文
從 Docker 到 K8s:我的 30 天雲原生筆記21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言