iT邦幫忙

2026 iThome 鐵人賽

DAY 29
0
Software Development

學校沒教的後端生存指南:30 天打造非同步 S3 微服務,部署 K8s 實現 HA 架構系列 第 29 篇

[ Day 29 ] DevOps 自動化交付 - GitHub Actions + AWS ECR + K8s 一鍵 CI/CD 零人工干預部署

  • 分享至 

  • xImage
  •  

在前面的章節中,我們已經成功將非同步 S3 微服務搬上了 K8s,實作了雙探針自癒、HPA 自動水平擴充以及 PV/PVC 持久化掛載。

然而,在真實的軟體開發團隊中,隱藏著一個極度繁瑣且容易出錯的痛點:每次修改程式碼,都要手動 docker build、docker push,再連進 K8s 伺服器敲 kubectl apply,不僅耗時,還容易發生版控錯亂與人工操作失誤!

所以今天,我們要介紹現代雲端原生架構中不可或缺的一環持續整合與持續部署 CI/CD (Continuous Integration / Continuous Deployment)!帶大家建置 GitHub Actions 自動化流水線,搭配 AWS ECR (Elastic Container Registry),實現只需 git push,系統自動完成單元測試、鏡像打包、推送到 AWS ECR 的流程。

https://ithelp.ithome.com.tw/upload/images/20260925/20183864VUp10XC5AX.png

什麼是 CI/CD?為什麼需要自動化交付?

  • CI (Continuous Integration,持續整合): 當開發人員將程式碼提交至 GitHub 時,自動觸發語法檢查、單元測試(JUnit)與安全性掃描,確保新提交的 Code 不會破壞既存功能。
  • CD (Continuous Deployment,持續部署): 測試通過後,自動調用 Docker Multi-stage 進行打包,將帶有 Git Commit SHA 標籤的 Image 推送至 AWS ECR 鏡像庫,最後透過 K8s API 觸發無感滾動更新 (Rolling Update)!

在傳統手動部署模式下,開發與營運之間存在著龐大的溝通牆與操作風險:

https://ithelp.ithome.com.tw/upload/images/20260925/201838644kkvVOmOTR.png


【傳統手動部署 (Manual Deployment)】:
  修改 Code ──► 本地 Build ──► 手動 Docker Build ──► 手動 Tag ──► 手動 Apply K8s
  ⚠️ 痛點:耗時 15~30 分鐘、環境不一致 ("It works on my machine")、缺乏審核紀錄。

【自動化 CI/CD 流水線 (Automated Pipeline)】:
  git push ──► GitHub Actions ──► 跑測試 ──► 打包 ECR ──► 自動 K8s 滾動更新 (0.00% 錯誤)
  🚀 優勢:平均 2 分鐘完成上線、100% 稽核軌跡 (Audit Trail)、完全消滅人為失誤!

什麼是 AWS ECR?三種 Container Registry 方案對比

在 CI/CD 流水線中,Runner 打包出來的 Docker Image 必須推送到一個雲端鏡像倉庫 (Container Registry),供後續的 K8s 或伺服器拉取 (Pull) 部署。

常見的有以下三種方案:

方案名稱 費用與免費額度 優勢與特色 適用場景
GHCR (ghcr.io) 免費 (包含每月 500MB 儲存與私有庫) GitHub 內建,無需額外註冊,自動對接 GITHUB 個人開源專案、極簡測試
Docker Hub 免費版提供 1 個私有庫 + 無限公有庫 全球最普及、社群範例最多,但有每小時下載次數限制 (Rate Limit) 通用社群專案
AWS ECR AWS Free Tier 包含 500MB 免費私有儲存 AWS 雲端原生代管,整合 IAM 權限控管,企業級對接 EKS/EC2 首選 企業級生產環境

本次實作內容選擇 AWS ECR :因為 AWS 免費額度包含了 500MB 的免費 ECR 儲存空間,對於我們這次的實作綽綽有餘,JAR 鏡像只有約 130MB,體驗真實的 AWS 雲端生態!

CI/CD 自動化實戰

1. 建立 GitHub Repository 並推送程式碼

  1. 打開 GitHub 建立一個全新的私有倉庫(我為了示範是選擇public 看個人需求),命名為 2026-ithome-s3-service。

https://ithelp.ithome.com.tw/upload/images/20260924/20183864qAJm6Bqx9g.png

  1. 在本地 Terminal 執行 Git 初始化並推送到 GitHub:
git init
git add .
git commit -m "feat: initial commit for S3 async microservice with K8s YAMLs"
git remote add origin https://github.com/your-username/s3-async-microservice.git #剛剛複製的url
git push -u origin main

2. 在 AWS Console 建立 ECR 倉庫

  1. 登入 AWS Management Console,搜尋進入 Elastic Container Registry (ECR)服務。
  2. 點擊建立儲存庫:
    • aws 預設是 Private(私有倉庫,確保金鑰與架構不外洩)。
      -輸入namespace, repo-name
  3. 點擊建立,記下生成的 ECR URI(例如:<aws_account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/s3-app-service)。

https://ithelp.ithome.com.tw/upload/images/20260925/201838647DqFigWUp0.png

  1. IAM 新增一個ecr的使用者
  2. 選擇直接附加政策 並勾選AmazonEC2ContainerRegistryPowerUser

https://ithelp.ithome.com.tw/upload/images/20260925/20183864c3bhcTUBZk.png

  1. 點擊使用者建立金鑰

3. 在 GitHub 設定 Secrets 安全憑證

為了讓 GitHub Actions 能代表你登入 AWS ECR 推送鏡像,我們必須在 GitHub 填入剛剛取得的ECR角色的accessKey, secretKey,來讓我們後續產生的image可順利推上雲端:

  1. 進入 GitHub Repository 頁面 ➔ Settings ➔ Secrets and variables ➔ Actions。
  2. 點擊 New repository secret,新增以下金鑰名稱,並輸入你自己的ak,sk:
    • AWS_ACCESS_KEY_ID
    • AWS_SECRET_ACCESS_KEY

https://ithelp.ithome.com.tw/upload/images/20260925/201838643AuQxTfPmg.png

4. 撰寫 GitHub Actions Workflow 腳本

在專案根目錄下建立 .github/workflows/deploy.yml 檔案,貼入自動化腳本:

name: Deploy S3 Microservice to K8s

on:
  push:
    branches: [ "main" ]  # 當 main 分支有 git push 時自動觸發

env:
  ECR_REPOSITORY: 2026ithome/s3-service  # ECR URL 中 registry 後面的部分

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
    - name: 1. Checkout Code
      uses: actions/checkout@v3

    - name: 2. Set up JDK 21
      uses: actions/setup-java@v3
      with:
        java-version: '21'
        distribution: 'temurin'
        cache: maven

    - name: 3. Build & Package (skip tests - no test cases defined)
      # 如果之後補了測試,把 -DskipTests 拿掉改回 mvn test && mvn package -DskipTests
      run: mvn package -DskipTests
      working-directory: s3-service  # ← Dockerfile 和 pom.xml 都在這個子目錄

    - name: 4. Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@v2
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: us-east-1  # ECR 所在的 Region

    - name: 5. Login to AWS ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1

    - name: 6. Build & Push Docker Image to ECR
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        IMAGE_TAG: ${{ github.sha }}  # 使用 Git Commit SHA 作為唯一版號
      run: |
        docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f s3-service/Dockerfile s3-service
        docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
        echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT

5. 推上github並觀察cicd流程

  1. 將檔案打包上傳
git add .
git commit -m 'add cicd'
git push
  1. 打開 GitHub 頁面的 Actions 標籤,看到亮綠燈就代表從單元測試、Docker Multi-stage 瘦身打包、AWS ECR 上傳都成功啦

  2. 進入AWS ECR就可以看到github已經將build好的image上傳啦!
    https://ithelp.ithome.com.tw/upload/images/20260925/20183864rROg77rJx6.png

本地測試建立服務

剛剛已經透過cicd流程將檔案建立成image必且push上aws ecr上了,我們現在只完成cicd流程的一半,先回到本地端測試一下,能不能將雲端的image拉下來並且執行

1. 建立 ecr-secret(讓 Minikube 有權限下載 ECR 鏡像)

因為 AWS ECR 是私有倉庫,Minikube 預設連不進去。我們要先去aws申請憑證,才能從本地拉image下來

  1. 打開 AWS Web Console 網頁,點擊左下角工具列的 CloudShell 圖示
  2. 輸入 aws ecr get-login-password --region us-east-1 畫面上會印出一大串超長的亂碼字串(12 小時臨時 Token),將它完整複製起來

https://ithelp.ithome.com.tw/upload/images/20260925/20183864Fy3F8fJwJi.png

  1. 回到你本地電腦的 Terminal,手動貼上密碼執行:
kubectl create secret docker-registry ecr-secret \
  --docker-server=154993632692.dkr.ecr.us-east-1.amazonaws.com \
  --docker-username=AWS \
  --docker-password=貼上剛剛複製的那一大串Token

2. 修改 k8s/s3-app-deployment.yaml

在 YAML 中加上 imagePullSecrets 指向 ecr-secret,並更新 image 網址:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: s3-app-deployment
spec:
  # 💡 Day29:從 ECR 拉 image 需要 imagePullSecrets
  imagePullSecrets:
  - name: ecr-secret

  containers:
  - name: s3-service-container
    # 💡 Day29:ECR image(CI/CD 自動更新這行的 tag)
    # 本地測試時改回 image: my-app:latest 並移除 imagePullSecrets
    image: 154993632692.dkr.ecr.us-east-1.amazonaws.com/2026ithome/s3-service:your_tag
    imagePullPolicy: Always   # 使用 ECR 時必須 Always,確保每次都拉最新 tag

3. 套用 YAML 驗證滾動更新!

# 1. 套用最新的 Deployment YAML
kubectl apply -f k8s/s3-app-deployment.yaml

# 2. 觀察 K8s 從 AWS ECR 拉取鏡像並完成 0 停機滾動更新
kubectl rollout status deployment/s3-app-deployment

總結

透過 GitHub Actions 與 AWS ECR,我們縮短軟體交付週期,完成了現代 DevOps 架構中最重要的一塊拼圖:

  • 0 成本 CI/CD 流水線:結合 GitHub Actions 與 AWS ECR (500MB Free Tier),達成零手動打包。
  • 安全與憑證託管:透過 GitHub Secrets 與 IAM 權限控管,達成 0 金鑰洩漏

明天,我們將迎來 30 天鐵人賽的最終章!目前只是本地的測試,明天會教大家如何使用AWS EC2來做到完整的CICD部署,後許只要程式碼有修改調整,推上github後,就會有完整的驗證、建立image和部署流程!


上一篇
[ Day 28 ] Pod 重啟資料卻失蹤 : K8s Volume 與 ConfigMap / Secret 打造狀態與機密不崩潰的高可用微服務!
下一篇
[ Day 30 ] CICD 串接 AWS EC2 0 成本雲端發布、CloudWatch 監控真相與 30 天架構師畢業之旅!
系列文
學校沒教的後端生存指南:30 天打造非同步 S3 微服務,部署 K8s 實現 HA 架構 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言