🐙 為什麼要使用 Dynamic Environments、Blue-Green 與 Canary?
大部分團隊在導入 GitLab CI/CD 初期,只是單純把程式 build、test、deploy 到一個固定環境(如 staging、production), 長期下來會遇到幾個痛點:
- 每個 Merge Request 都要手動佈署到「共同測試機」,容易打架。
- 上線都是「一次性切換」:一旦出錯,只能緊急 Rollback。
- 缺少漸進式(Canary)與 Blue-Green 機制,風險難以控制。
本篇會以實務角度說明如何在 GitLab CI 裏導入:
Dynamic Environments、Preview Apps、Blue-Green 部署、Canary Release,
並提供可直接改用的 .gitlab-ci.yml 範例。
📌 核心概念總整理
- Static Environment: 固定名稱,例如
staging、production。 - Dynamic Environments: 依
$CI_COMMIT_REF_SLUG或$CI_MERGE_REQUEST_IID等動態建立的環境。 - Review App: 每個分支 / MR 都有自己的測試網址,方便 PM、QA、設計 review。
- Blue-Green: 維持兩個 production 環境(blue / green),交替接手流量,降低部署風險。
- Canary Release: 逐步增加流量,例如 10% → 50% → 100%,過程中可隨時停止。
📌 基礎:在 GitLab CI 中定義環境(environment)
先從最基本的 static environment 開始:
deploy_staging:
stage: deploy
script:
- ./deploy.sh staging
environment:
name: staging
url: https://staging.example.com
deploy_production:
stage: deploy
script:
- ./deploy.sh production
environment:
name: production
url: https://www.example.com
on_stop: stop_production
GitLab UI 會自動建立「環境」頁籤,可看到每次部署狀態、URL 與 Rollback 紀錄。
📌 Dynamic Environments 與 Review Apps
1. 依分支建立 Dynamic Environment
review_app:
stage: deploy
script:
- ./deploy_review.sh "$CI_COMMIT_REF_SLUG"
environment:
name: review/$CI_COMMIT_REF_SLUG
url: https://$CI_COMMIT_REF_SLUG.review.example.com
on_stop: stop_review_app
rules:
- if: '$CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "main"'
2. 停用 Review App(on_stop Job)
stop_review_app:
stage: deploy
script:
- ./cleanup_review.sh "$CI_COMMIT_REF_SLUG"
environment:
name: review/$CI_COMMIT_REF_SLUG
action: stop
rules:
- if: '$CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "main"'
when: manual
這樣在 Merge Request 頁面會出現一顆「Open live environment」按鈕, Reviewer 可以直接點進去測試該分支的實際畫面。
3. 依 Merge Request 建立 Review App(推薦)
review_app:
stage: deploy
script:
- ./deploy_review.sh "mr-$CI_MERGE_REQUEST_IID"
environment:
name: review/mr-$CI_MERGE_REQUEST_IID
url: https://mr-$CI_MERGE_REQUEST_IID.review.example.com
on_stop: stop_review_app
rules:
- if: '$CI_MERGE_REQUEST_IID'
📌 Blue-Green Deployment:兩套 production 交替切換
常見做法是維持 production-blue 與 production-green 兩組環境,
實際流量由 Load Balancer / Gateway 控管(例如 Nginx、HAProxy、Cloud Load Balancer)。
1. 建立 Blue / Green 兩個環境
.deploy_production_template:
stage: deploy
script:
- ./deploy_prod.sh "$TARGET_SLOT"
environment:
name: $ENV_NAME
url: $ENV_URL
when: manual
allow_failure: false
deploy_blue:
extends: .deploy_production_template
variables:
TARGET_SLOT: blue
ENV_NAME: production-blue
ENV_URL: https://blue.example.com
deploy_green:
extends: .deploy_production_template
variables:
TARGET_SLOT: green
ENV_NAME: production-green
ENV_URL: https://green.example.com
2. 切換流量(由 LB / DNS 控制)
接著可以在 CI 裡加一個 Job 去呼叫 LB API 或 Ansible:
switch_to_blue:
stage: deploy
script:
- ./switch_traffic.sh blue # 例如修改 Nginx upstream 或 DNS
when: manual
needs: ["deploy_blue"]
switch_to_green:
stage: deploy
script:
- ./switch_traffic.sh green
when: manual
needs: ["deploy_green"]
實務上會先部署到另外一邊(如 blue),
確認沒問題後再執行 switch_to_blue 把流量切換過去;
遇到問題時,只要執行 switch_to_green 即可快速回復。
📌 Canary Release:10% → 50% → 100% 漸進式上線
Canary 发布重點在「分批」:
- 先讓一小部份使用者使用新版本(10%)。
- 觀察錯誤率、延遲、使用者回饋。
- 確認穩定後再逐步放大流量到 50%、100%。
在 GitLab 中可以用多個 Canary Job 表達不同階段, 實際流量比例交給 Kubernetes / Ingress / Service Mesh(如 Istio、NGINX Ingress)。
範例:三階段 Canary Pipeline
deploy_canary_10:
stage: deploy
script:
- ./deploy_canary.sh 10 # 10% 流量
environment:
name: production-canary
url: https://www.example.com
when: manual
deploy_canary_50:
stage: deploy
script:
- ./deploy_canary.sh 50 # 50% 流量
environment:
name: production-canary
when: manual
needs: ["deploy_canary_10"]
deploy_canary_100:
stage: deploy
script:
- ./deploy_canary.sh 100 # 100%:與正式版一致
environment:
name: production
url: https://www.example.com
when: manual
needs: ["deploy_canary_50"]
可以依團隊成熟度調整階段數量與條件, 例如在 10% 階段時必須由 SRE / PM 共同確認後才允許往 50%。
📌 自動清理 Dynamic Environments:避免爆炸成一堆環境
大量使用 Review Apps 之後,很快會有幾十甚至上百個環境, 因此一定要搭配:
on_stopJob: MR 關閉時自動清理。auto_stop_in: 過期自動停止環境。
範例:7 天後自動停止 Review App
review_app:
stage: deploy
script:
- ./deploy_review.sh "mr-$CI_MERGE_REQUEST_IID"
environment:
name: review/mr-$CI_MERGE_REQUEST_IID
url: https://mr-$CI_MERGE_REQUEST_IID.review.example.com
on_stop: stop_review_app
auto_stop_in: 7 days
rules:
- if: '$CI_MERGE_REQUEST_IID'
📌 與 Kubernetes / GitOps 整合的典型模式
若專案已經使用 Kubernetes,可將 GitLab CI 的 Deploy Job 改為:
- 直接
kubectl apply或 Helm - 或使用 Argo CD / Flux 做 GitOps,同步到 K8s
deploy_review_k8s:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl config use-context "$KUBE_CONTEXT"
- kubectl apply -f k8s/overlays/review/"$CI_COMMIT_REF_SLUG"
environment:
name: review/$CI_COMMIT_REF_SLUG
url: https://$CI_COMMIT_REF_SLUG.review.example.com
Canary / Blue-Green 的流量分配, 則可以交給 K8s Ingress、Service Mesh,或 External LB 管理。
📌 實務最佳做法清單
- 一開始先啟用 Review Apps,提升協作體驗。
- 已經有穩定 staging / production 再導入 Blue-Green。
- 高風險功能或核心系統才使用 Canary Release。
- 把部署腳本抽成共享 template(
.deploy_template),避免重複。 - 敏感資訊(Token、金鑰)全部放在 GitLab CI/CD Variables。
- 習慣在 deploy Job 設
when: manual+only / rules控管觸發條件。
📚 延伸閱讀
- 🐙 GitLab CI/CD 最佳實務(進階篇):Artifacts、Cache、Stages、與安全性策略
- 🐙 GitLab CI/CD 進階部署:Artifacts、Blue-Green 與 Canary 策略
- 🐙 GitLab 進階 CI/CD Template:Dynamic Env 與 GitOps 整合
- 🐙 GitLab CI + Docker:Runner、Registry 與 Compose 部署實戰
- 🐙 GitLab CI/CD 入門:Runner、Pipeline 與基本部署流程
- 🐙 GitLab CI/CD Best Practices:實務最佳做法總整理
💬 歡迎在下方留言討論!
你目前的 GitLab Pipeline 有使用 Dynamic Environments、Blue-Green 或 Canary 嗎?
歡迎分享你的實作方式、踩雷經驗或想優化的地方,一起交流 DevOps 實務!🚀
沒有留言: