iT邦幫忙

2025 iThome 鐵人賽

DAY 28
0
GitHub Push → GitHub Actions 觸發 → OIDC 驗證 → Assume Role → Deploy Lambda

流程已經只剩下最後一步:部署 Lambda
前篇已經成功讓 GitHub Actions 透過 OIDC 登入 AWS,接下來只需要撰寫一個 自動部署 Lambda 的 workflow 定義檔。

GitHub Actions 會依照 .yml 的指令逐步執行:
打包程式碼、上傳至 AWS、再透過 CLI 呼叫 update-function-code 完成部署。


部署 Lambda 的 YAML 設定檔

# ==========================================================
# GitHub Actions workflow:自動部署 AWS Lambda
# ----------------------------------------------------------
# 當 develop 分支有 push 時,自動:
#   1. 取得 OIDC 驗證登入 AWS
#   2. 打包整個專案成 zip
#   3. 更新指定的 Lambda 函數程式碼
# ==========================================================

name: Deploy Lambda         # 工作流程名稱,會顯示在 Actions 頁面上

on:
  push:
    branches:
      - develop             # 僅當推送到 develop 分支時觸發部署流程

jobs:
  deploy:                   # Job 名稱,可自訂(例如 deploy、build 等)
    runs-on: ubuntu-latest  # 使用 GitHub 提供的 Ubuntu Runner 執行環境

    permissions:
      id-token: write  # 允許 Actions 產生 OIDC token 以登入 AWS
      contents: read   # 允許讀取 Repository 內容

    steps:
      # Step 1. 取出最新的原始碼
      - name: Checkout source
        uses: actions/checkout@v4 # 官方 action,用來抓取專案內容到 Runner

      # Step 2. 使用 OIDC 登入 AWS
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4  # AWS 官方 action
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}   # 要 Assume 的 IAM Role
          aws-region: ${{ secrets.AWS_REGION }}         # 目標 AWS 區域

      # Step 3. 打包 Lambda 原始碼
      - name: Zip Lambda function
        run: |
          zip -r function.zip .      # 將目前資料夾內容壓縮成 function.zip

      # Step 4. 確認壓縮結果
      - name: List files after zip
        run: ls -R                  # 列出所有檔案,確認 zip 包含的內容

      # Step 5. 更新 Lambda 函數程式碼
      # Lambda 函數名稱(從 Secrets 讀取)
      # 指定上傳 zip 作為新版本程式碼
      - name: Deploy to Lambda
        run: |
          aws lambda update-function-code \
            --function-name ${{ secrets.LAMBDA_FUNCTION_NAME }} \
            --zip-file fileb://function.zip
  • push 到 develop 分支
    https://ithelp.ithome.com.tw/upload/images/20251012/20168437OnhBUAFGG9.png
  • 直接到 GitHub 上看執行狀態:專案 Repository > Actions 分頁
    https://ithelp.ithome.com.tw/upload/images/20251012/20168437RlNa0qiFCb.png
  • 最後到 AWS Console 上確認程式是否部署完成 → 執行成功!
    https://ithelp.ithome.com.tw/upload/images/20251012/20168437miQ1lBNYTK.png

改善部署流程

雖然現在的版本已經可以使用,但在部署及檢視 Log 的過程中,發現還有許多改善空間。

  • zip 包含非必要的檔案
    Run zip -r function.zip .      # 將目前資料夾內容壓縮成 function.zip
      adding: .git/ (stored 0%)
      adding: .git/HEAD (stored 0%)
      adding: .git/shallow (stored 0%)
      adding: .git/refs/ (stored 0%)
      adding: .git/refs/remotes/ (stored 0%)
      adding: .git/refs/remotes/origin/ (stored 0%)
      adding: .git/refs/remotes/origin/develop (stored 0%)
      adding: .git/refs/tags/ (stored 0%)
      ...
    

從 Log 發現 zip 打包時居然包含了 80 多個檔案... 這是因為 YAML 中沒有指定排除路徑,所以才把 .git/.github/ 通通打包進去了。

調整方式:加入 .lambdaignore

  • 在專案結構中加入打包 Lambda 時要忽略的檔案清單
    ITHome-ironman-2025/        # 專案資料夾
    ├── .lambdaignore           # 打包 Lambda zip 時要略過的檔案清單
    ├── lambda_function.py      # 程式碼
    ├── bedrock_service.py      
    ├── ....py
    ├── requirements.txt        # 引入套件清單
    └── .github/                # GitHub 用設定檔路徑
        └── workflows/          # GitHub Actions workflow 的預設讀取路徑
            └── deploy-lambda.yml   # yaml 設定檔案
    
  • .lambdaignore
    # Git / GitHub
    .git/*
    .github/*
    .gitignore
    
    # Python build / cache
    __pycache__/
    *.pyc
    *.pyo
    *.pyd
    *.egg-info/
    build/
    dist/
    
    # Local environment
    .env
    venv/
    .venv/
    
    # System files
    .DS_Store
    Thumbs.db
    
    # IDE configs
    .vscode/
    .idea/
    
    # Logs
    *.log
    
    # 壓縮檔本身
    *.zip
    
  • 接著再調整壓縮的指令
          # Step 3. 打包 Lambda 原始碼
          - name: Zip Lambda function
            run: |
    -         zip -r function.zip .
    +         zip -r function.zip . -x@.lambdaignore
    
  • 測試
    https://ithelp.ithome.com.tw/upload/images/20251012/20168437BIe8zOIOYw.png

這樣就乾淨多啦!


加入方便 Debug 的 Log

不管系統開發、部署、測試,環境變數設定錯誤都可以算是常見問題。
在 workflow 中加入適當的 Log,有助於開發人員迅速確認是否有設定變數值。

     steps:
+      # Step 0. 輸出參數設定
+      - name: check deploy infos
+        run: |
+          if [ -z "${{ secrets.AWS_ROLE_ARN }}" ]; then
+            echo "AWS_ROLE_ARN is missing!"
+          else
+            echo "AWS_ROLE_ARN is set (value masked)."
+          fi
+          if [ -z "${{ secrets.AWS_REGION }}" ]; then
+            echo "AWS_REGION is missing!"
+          else
+            echo "AWS_REGION is set (value masked)."
+          fi
+          if [ -z "${{ secrets.LAMBDA_FUNCTION_NAME }}" ]; then
+            echo "LAMBDA_FUNCTION_NAME is missing!"
+          else
+            echo "LAMBDA_FUNCTION_NAME is set (value masked)."
+          fi
  • 測試
    https://ithelp.ithome.com.tw/upload/images/20251012/20168437vU2Z6oayRg.png

重複部署

目前這個 workflow 會在每次對 develop 分支做 push 時觸發,但實務上,遇到只是修改 README 或調整說明文件,並不需要對 Lambda 做重新部署。
如果想避免重複部署的問題,可以在條件式中加入檔案篩選:

on:
  push:
    branches:
      - develop
    paths:
      - 'lambda_function.py'
      - 'bedrock_service.py'
      # 總之就是直接列出有異動就需要部署的檔案

那加了新檔案卻沒有列進 path 清單,自動部署不就會失效了嗎?

對!所以還有另一種更保險的作法:
利用 paths-ignore 屬性,列出異動也不需要部署的檔案就可以了。

on:
  push:
    branches:
      - develop             # 僅當推送到 develop 分支時觸發部署流程
    paths-ignore:
      - 'README.md'
      - '.gitignore'
      - '.lambdaignore'
      - '.github/**'

這樣設定後,如果 commit 只修改了被列在 paths-ignore 的檔案,就不會觸發整個自動部署流程。
就算少列了檔案,最多只是重複部署,而不會影響服務的可用性。


資訊補充

  • 其實調整 yaml file 不只節省空間
    在部署的時候,避免打包不需要的檔案除了可以加快速度外,還有一個額外的好處。
    部署至 Lambda 的 ZIP 檔案是有大小限制的。
    根據官方文件:Lambda 配額,zip 的檔案大小不能 > 50 MB。
    畢竟 Lambda 本來就是為了快速且短期運算的任務設計,天生就不適用於一整套的複雜系統。

  • 為什麼輸出 Log 的時候,不直接把 secret 設定值印出來就好?
    我也想...所以一開始的 yaml 調整其實是這樣的:

         steps:
    +      # Step 0. 輸出參數設定
    +      - name: deploy infos
    +       run: |
    +          echo "Deploying to Lambda: ${{ secrets.LAMBDA_FUNCTION_NAME }}"
    +          echo "Region: ${{ secrets.AWS_REGION }}"
    
           # Step 1. 取出最新的原始碼
           - name: Checkout source
             uses: actions/checkout@v4 # 官方 action,用來抓取專案內容到 Runner
    
  • 執行結果
    https://ithelp.ithome.com.tw/upload/images/20251012/20168437TMSIzkbzqO.png

被遮蔽啦!
然而,官方文件 Using secrets in GitHub Actions 中其實有提及這個情形。
https://ithelp.ithome.com.tw/upload/images/20251012/20168437GG5ThPyMoC.png

為了避免機敏資料被意外輸出,GitHub 會自動遮掉 Log 中的 secrets 資訊喔!


上一篇
Day 27. 一個巴掌拍不響
系列文
科學的盡頭是玄學?AI占卜小助手與知識庫驗證28
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言