2026年6月4日 星期四

設定AWS Pipeline,將Github程式碼推到ECR並部屬到Lambda和S3

不用AWS創建的預設角色過一次流程,整理作業重點,避免以後忘記

1. 流程分為兩階段,AWS CodePipeline → AWS CodeBuild

AWS CodePipeline負責觸發,再由 AWS CodeBuild 負責跑所有指令

幾項前置作業準備
  • AWS CodeConnection 設定
  • CodePipeline S3 Bucket 建置
    • 建置一個 pipeline-image-<accountId>-ap-southeast-1-an Bucket,放所有image
  • CodeBuild S3 Bucket 建置
    • 建置一個 frontend-<accountId>-ap-southeast-1-an Bucket,放所有靜態頁面
  • AWS CodePipeline 角色建置
    參照上圖,CodePipeline需要以下權限,將其寫入policy,因為希望一個Role可套用在所有的Pipeline,所以Resource使用大量*號
  1. 對GitHub連線的權限
  2. CodePipeline S3 Bucket作業的權限
  3. 呼叫CodeBuilder作業的權限
  4. 寫入Log的權限
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "codestar-connections:UseConnection",
            "Resource": "<CodeConnection的ARN>",
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::pipeline-image-<accountId>-ap-southeast-1-an",
                "arn:aws:s3:::pipeline-image-<accountId>-ap-southeast-1-an/*"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "codebuild:BatchGetBuilds",
                "codebuild:StartBuild",
                "codebuild:StopBuild"
            ],
            "Resource": "arn:aws:codebuild:ap-southeast-1:<accountId>:project/*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:ap-southeast-1:<accountId>:log-group:/aws/codepipeline/*"
            ],
            "Effect": "Allow"
        }
    ]
}
  • CodeBuild ECR 建置
    • 幫本次Repo建立一個所屬ECR 
  • AWS CodeBuild 角色建置
參照上圖,CodeBuild需要以下權限,將其寫入policy
  1. 讀取CodePipeline S3 Bucket image的權限
  2. 登入ECR的權限
  3. 操作ECR的權限
  4. CodeBuilder S3 Bucket作業的權限
  5. 更新Lambda image的權限
  6. 寫入Log的權限
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:logs:ap-southeast-1:<accountId>:log-group:/aws/codebuild",
                "arn:aws:logs:ap-southeast-1:<accountId>:log-group:/aws/codebuild/*"
            ],
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ]
        },
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::pipeline-image-<accountId>-ap-southeast-1-an",
                "arn:aws:s3:::pipeline-image-<accountId>-ap-southeast-1-an/*",
                "arn:aws:s3:::frontend-<accountId>-ap-southeast-1-an",
                "arn:aws:s3:::frontend-<accountId>-ap-southeast-1-an/*"
            ],
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:ListBucket"
            ]
        },
        {
            "Action": [
                "ecr:BatchCheckLayerAvailability",
                "ecr:CompleteLayerUpload",
                "ecr:InitiateLayerUpload",
                "ecr:PutImage",
                "ecr:UploadLayerPart"
            ],
            "Resource": "arn:aws:ecr:ap-southeast-1:<accountId>:repository/*",
            "Effect": "Allow"
        },
        {
            "Action": "ecr:GetAuthorizationToken",
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Effect": "Allow",
            "Action": [
                "lambda:UpdateFunctionCode",
                "lambda:GetFunction"
            ],
            "Resource": "*"
        }
    ]
}

    2. 使用CodePipeline功能建立


    Step 1 選擇 [建置自訂管道]



    Step 2 選擇 [建置自訂管道]

        只有兩處要改
        1. 選擇 [現有的服務角色] ,選擇剛剛建立的CodePipeline角色

        2. 展開 進階設定 ,成品存放區選擇 [自訂位置] ,選擇要放image的Bucket

    完成後點選下一步

    Step 3 選擇Pipeline觸發方式

        來源供應商 選擇 Github (透過Github應用程式)
        連線 選擇剛剛建立的Github ARN
        儲存庫名稱 選擇要走Pipeline的Repo
        預設分支 選擇推送觸發的分支


    完成後點選下一步

    Step 4 選擇建置方式

        建置供應商 選擇其他建置供應商,選單選擇 AWS CodeBuild
        專案名稱 目前是空值,須點選 [建立專案] 跳到分頁建立 CodeBuild 流程
        

        跳轉至CodeBuilder分頁

            填寫專案名稱
        
    並選擇剛剛創建的 CodeBuilder 角色
        
    並填寫buildspec,點選 [切換至編輯器] 可以展開多行輸入框
       
     將部屬流程貼上,上方的env是可調整參數,分別對應
    • ImageName: repo要推送的ECR名稱
    • FUNCTIONS: image要更新的Lambda名稱,可填複數Lambda
    • BucketFolder: 靜態頁面放在S3的路徑
    version: "0.2"
    env:
      variables:
        ImageName: "<ECR名稱>"
        FUNCTIONS: "<LambdaName1> <LambdaName2>"
    BucketFolder: "<靜態頁面在S3的路徑>"
    phases: pre_build: commands: - aws ecr get-login-password --region ap-southeast-1 | docker login --username AWS --password-stdin <accountId>.dkr.ecr.ap-southeast-1.amazonaws.com
    build: commands: - docker build -t $ImageName -f ./Dockerfile . - docker images - echo "Preparing S3 upload files..." - | if [ -d "src/main/resources/static" ]; then mkdir -p s3-upload/$BucketFolder cp -r src/main/resources/static/* s3-upload/$BucketFolder/; echo "Static files copied successfully"; fi post_build: commands: - docker tag $ImageName:latest <accountId>.dkr.ecr.ap-southeast-1.amazonaws.com/$ImageName:latest
    - docker push <accountId>.dkr.ecr.ap-southeast-1.amazonaws.com/$ImageName:latest
    - | for FUNCTION in $FUNCTIONS do echo "Updating $FUNCTION" aws lambda update-function-code \ --function-name "$FUNCTION" \ --image-uri "<accountId>.dkr.ecr.ap-southeast-1.amazonaws.com/$ImageName:latest" \
    --region ap-southeast-1 done - | if [ -d "src/main/resources/static" ]; then echo "Syncing static files to S3..." aws s3 sync s3-upload/$BucketFolder/ s3://frontend-<accountId>-ap-southeast-1-an/$BucketFolder/ --delete --region ap-southeast-1
    fi - echo "Deployment completed successfully!"
      完成後點選 [更新專案] 回到CodePipeline 流程,選擇方才建立的專案名稱

      完成後點選下一步

      Step 5 測試流程
          本次無測試,點選 [跳過測試階段]
      Step 6 部屬流程
          因流程已寫在Step 4 ,因此點選 [跳過部屬階段]
      Step 7 檢視流程
          直接點選 [建立管道] 完成本次設定

      當完成後系統會先觸發一次,但正常會失敗,主因是ECR沒允許Lambda來抓取image

      這時切換到我們的ECR,點選 許可 > 編輯JSON

      將以下Policy貼上,允許Lambda資源來讀此ECR
      {
        "Version" : "2008-10-17",
        "Statement" : [ {
          "Sid" : "LambdaECRImageRetrievalPolicy",
          "Effect" : "Allow",
          "Principal" : {
            "Service" : "lambda.amazonaws.com"
          },
          "Action" : [ "ecr:BatchGetImage", "ecr:GetDownloadUrlForLayer", "ecr:SetRepositoryPolicy", "ecr:DeleteRepositoryPolicy", "ecr:GetRepositoryPolicy" ],
          "Condition" : {
            "StringLike" : {
              "aws:sourceArn" : "arn:aws:lambda:ap-southeast-1:<accountId>:function:*"
            }
          }
        } ]
      }
      完成後可再重新觸發部屬,進到CodePipeline > 發行變更

      即可成功部屬




      沒有留言:

      張貼留言