熱門分類
載入中…
目錄0%

🐙 GitLab CI/CD 進階部署:Dynamic Environments、Preview App、Blue-Green 與 Canary 完整指南

    🐙 為什麼要使用 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: 固定名稱,例如 stagingproduction
    • 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-blueproduction-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_stop Job: 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 Pipeline 有使用 Dynamic Environments、Blue-Green 或 Canary 嗎?
    歡迎分享你的實作方式、踩雷經驗或想優化的地方,一起交流 DevOps 實務!🚀

    🔗 分享這篇 LINE Facebook X

    沒有留言:

    字級