GitLab CI/CD 教學專案
GitLab CI/CD 十關
從第一條 pipeline 一路做到 k8s 實機部署。每一關一個資料夾,裡面有說明與可以直接執行的 .gitlab-ci.yml。Lv.1~Lv.9 在 gitlab.com 共享 runner 實跑通過;Lv.10 用正式網站同一套流水線,把課程網站建成映像、簽章,經 GitOps 部署到 homelab k8s。
- 課程網站:cicd-tutorial.yc-group.org
- 原始碼:GitLab
fjw08199999/cicd-tutorial(私有) - 2026-11-09 從零重建
- 2026-11-09 17:39 已上線
十關目錄
| 關卡 | 主題 | 類型 | 你會學到 |
|---|---|---|---|
| Lv.1 | 第一條 Pipeline | 基礎 | pipeline、job、runner 的關係;image、script |
| Lv.2 | Stages 與 Jobs | 基礎 | stages 順序、平行 job、default、before/after_script、allow_failure 指定結束碼、.pre/.post |
| Lv.3 | Artifacts | 基礎 | 產物傳遞、expire_in、dependencies、JUnit 測試報告 |
| Lv.4 | Variables | 基礎 | 內建變數、覆寫順序、手動執行表單、dotenv 在 job 間傳值、機密要放 Masked+Protected |
| Lv.5 | Cache | 進階 | cache key 依相依清單計算、policy: pull、extends、cache 與 artifacts 的分工 |
| Lv.6 | Rules 與 workflow | 進階 | workflow 避免重複 pipeline、rules:if/changes/exists、manual、delayed、never |
| Lv.7 | Needs 與 DAG | 進階 | needs 縮短 pipeline、needs 決定下載哪些產物、parallel:matrix、!reference |
| Lv.8 | Services | 進階 | Redis、PostgreSQL 整合測試、alias、等待服務就緒、entrypoint 覆寫 |
| Lv.9 | Environments | 進階 | review app、on_stop、auto_stop_in、resource_group、手動上 production、Rollback |
| Lv.10 | 實機部署到 k8s | 實機 | Harbor、Trivy、cosign、Kyverno、GitOps、Argo CD、Envoy Gateway、cert-manager |
每關的說明在各資料夾的 README.md,課程網站上每關一頁,含完整範例檔與複製按鈕。
技術棧
| 領域 | 工具 | 用途 |
|---|---|---|
| CI | GitLab CI/CD | Lv.1~Lv.9 用 gitlab.com 共享 runner;Lv.10 用 homelab 的 k8s-ci(掃描,沒有密鑰)與 k8s-release(只收受保護分支) |
| 安全掃描 | gitleaks、Trivy、Semgrep | 機密、相依套件與映像漏洞(有修補版的 CRITICAL 就擋)、程式寫法;映像產生 SBOM |
| 建置 | BuildKit | 無 root 建置映像 |
| 映像倉庫 | Harbor | sites/cicd-tutorial |
| 供應鏈 | cosign+Kyverno | 傳統 .sig 簽章,叢集准入時驗章 |
| 部署 | Argo CD(GitOps) | 以 homelab-k8s repo 的 apps/cicd-tutorial/values.yaml 為準 |
| 入口 | Envoy Gateway | 共用 Gateway,本站獨立 HTTPRoute;HSTS、壓縮、上傳上限 1Mi |
| 憑證 | cert-manager | Let's Encrypt HTTP-01,自動續期 |
| 網站 | Python 標準函式庫、nginx-unprivileged | 把各關 README 轉成靜態網頁;容器內 nginx 只送檔,非 root |
| 前端 | 原生 HTML/CSS/JavaScript | 卡片拖拉+群組(滑鼠、觸控長按、鍵盤)、深淺色、RWD,CSP 不允許 inline 腳本 |
部署方式
push 到 main(受保護分支)後自動部署,不手動操作主機:
- 掃描:gitleaks、Trivy、Semgrep;同時
site-check把網站產生一次並檢查。 - 建置映像:BuildKit 依
lv10-k8s-deploy/Dockerfile建置,推上 Harbor,標籤是 commit 前 8 碼。 - 映像檢查:Trivy 掃描、產生 SBOM。
- 簽章:cosign 傳統
.sig格式。 - 更新 GitOps:CI 把新標籤寫進 homelab-k8s 的
apps/cicd-tutorial/values.yaml。 - Argo CD 同步:約 3 分鐘內滾動更新
site-cicd-tutorial,Kyverno 驗章通過才會啟動。 - 對外:Envoy Gateway listener
https-cicd-tutorial-yc-group-org,cert-manager 簽發憑證。
| 網域 | cicd-tutorial.yc-group.org(需要 DNS A 紀錄指到主機公網 IP) |
|---|---|
| namespace | site-cicd-tutorial(Pod Security restricted、預設拒絕網路) |
| Deployment | cicd-tutorial-web,容器 8080,滾動更新不中斷 |
| Argo CD | site-cicd-tutorial(由 ApplicationSet 依 apps/ 目錄自動產生) |
| 回復 | 在 homelab-k8s git revert CI 的部署 commit,Argo CD 自動換回舊版 |
驗證:
kubectl -n site-cicd-tutorial get pods
kubectl -n site-cicd-tutorial get httproute cicd-tutorial -o jsonpath='{.status.parents[0].conditions}'
kubectl -n argocd get application site-cicd-tutorial -o jsonpath='{.status.sync.status} {.status.health.status}'
curl --resolve cicd-tutorial.yc-group.org:443:10.10.10.50 -I https://cicd-tutorial.yc-group.org/
2026-11-09 17:39 已上線:DNS(HiNet A → 114.32.115.113)生效後把網域加進 Envoy 的 hosts,Let's Encrypt 憑證約 20 秒簽好;Gateway、HTTPRoute、Argo CD 都正常。沒有 DNS 就先加 hosts 會讓共用 Gateway Degraded,這次第一次上線時實際發生過,已改正。
本機預覽:python3 lv10-k8s-deploy/site/build.py --out /tmp/cicd-site,再用 python3 -m http.server -d /tmp/cicd-site 8000 開啟。預覽完記得關掉。
更新紀錄
- 2026-11-09 17:39:已上線 cicd-tutorial.yc-group.org,Chrome 驗收首頁、Lv.1、Lv.10、說明文件(淺色與深色)與卡片拖拉保存。
- 2026-11-09:Lv.9 環境名稱帶斜線,
sed改用|分隔;網域等 DNS 建好才加進 Envoy。 - 2026-11-09:從零重建(舊專案已於 2026-08-27 刪除)。十關教材與總控 pipeline;課程網站含卡片拖拉+群組、深淺色、RWD、品牌資產與 CSP;Lv.10 接上 homelab k8s 共用流水線(Harbor、cosign、Argo CD、Envoy Gateway)。