Link Search Menu Expand Document

AWS CodeBuild

Nội dung

  1. Hoạt động CodeBuild
  2. Thực hành
    1. CodeBuild Project
    2. CodeBuild & CodeCommit
    3. CodeBuild & Unit Test

CodeBuild là dịch vụ AWS hỗ trợ quá trình tích hợp các thay đổi từ source code vào hệ thống một cách liên tục thông qua các hoạt động biên dịch, kiểm thử và đóng gói sản phẩm phần mềm để chuẩn bị cho giai đoạn triển khai kế tiếp. CodeBuild hỗ trợ công cụ biên dịch và môi trường thực thi cho hầu hết những ngôn ngữ lập trình phổ biến như .NET Core, Java, Ruby, Python, Go, Node.js, Android …Việc sử dụng CodeBuild giúp chúng ta không phải giành nhiều thời gian cho việc thiết lập build servers với cấu hình phức tạp, đồng thời còn hỗ trợ khả năng mở rộng và tối ưu khi thực hiện nhiều hoạt động build một cách đồng thời.


Hoạt động CodeBuild

Hình ảnh sau mô tả quá trình hoạt động của CodeBuild

CodeBuild Works Quá trình hoạt động của CodeBuild

Các bước thực hiện:

  1. Tạo một build project khai báo thông tin source code: cách thực hiện biên dịch / kiểm thử, vị trí lưu trữ của source code, vị trí lưu trữ kết quả biên dịch.

  2. CodeBuild sử dụng build project để taọ ra build environment dưới dạng Docker Container. Build environment kết hợp của hệ điều hành, trình biên dịch cùng các công cụ hỗ trợ khác.

  3. CodeBuild download source code từ một repository (CodeCommit, GitHub, S3) và đưa vào build environment. Tại đây, CodeBuild dựa trên các khai báo trong file buildspec.yaml để thực hiện quá trình build. File buildspec.yaml cung cấp thông tin về các lệnh biên dịch, kiểm thử cũng như những cấu hình liên quan.

  4. Khi hoạt động build thành công, kết quả đầu ra - artifacts có thể được lưu trữ trong nhiều hệ thống khác nhau: S3, Elastic Container Registry. Dựa trên thông tin trong buildspec.yaml, build environment có thể thực hiện thêm các hoạt động như gửi email, tin nhắn thông báo về kết quả build.

  5. Trong quá trình thực thi, build environment gửi các thông tin log ra CodeBuild console hoặc AWS CloudWatch.

  6. Sử dụng công cụ: AWS Console, AWS CLI, AWS SDK, AWS Pipeline điều khiển / giám sát quá trình build.


Thực hành

Phần thực hành sẽ chia thành các bước:

  • Sử dụng AWS Console / AWS CLI để tạo Build Project cho FriendReminders
  • Tích hợp CodeBuild và CodeCommit thông qua AWS Lambda Subscriber
  • Sử dụng CodeBuild thực thi Unit Tests

Chú ý:

Tại thời điểm hiện tại của bài viết này, CodeBuild không có khả năng trực tiếp giám sát thay đổi trên CodeCommit và kích hoạt build mỗi khi source code thay đổi. Vì vậy, một giải pháp phổ biến là tích hợp CodeBuild và CodeCommit thông qua AWS Lambda function mà chúng ta sẽ thực hành trong bài viết này. Việc thiết lập giải pháp này có đôi chút phức tạp nhưng có tính linh động và khả năng mở rộng cao do có thể tuỳ biến các logic bên trong Lambda function.

Một giải pháp khác là sử dụng dịch vụ AWS CodePipeline. Dịch vụ này dựa trên CloudWatch Event để xác định thời điểm mỗi khi source code được cập nhật trên CodeCommit và kích hoạt quá trình Build. Việc triển khai CodePipeline có thể thực hiện đơn giản qua AWS Console, kết hợp với CodeCommit Repository và CodeBuild Project.

CodeBuild Project

Các bước thực hiện:

  • Trong folder FriendReminders, tạo file buildspec.yml gồm các phases
    • pre_build: commands ECR login và khai báo biến sử dụng
    • build: docker build và docker tag commands
    • post_build: docker push commands
version: 0.2

phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - aws --version
      - $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
      - REPOSITORY_URI=729365137003.dkr.ecr.ap-southeast-2.amazonaws.com/remindersmgtservice
      - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
      - IMAGE_TAG=${COMMIT_HASH:=latest}
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...
      - echo Building for repository $REPOSITORY_URI
      - docker build -t $REPOSITORY_URI:latest ./Services/RemindersManagement/RemindersManagement.API
      - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker images...
      - docker push $REPOSITORY_URI:latest
      - docker push $REPOSITORY_URI:$IMAGE_TAG
  • Commit và Push buildspec.yml lên CodeCommit Repository FriendReminders.

  • Trên AWS Console Developer Tools -> CodeBuild, click button Create build project tạo build project với thông tin cấu hình:

    • Project Configuration:
      • Project Name: FriendRemindersBuild
      • Description: Build Project for FriendReminders Demo
    • Source:
      • AWS CodeCommit: AWS CodeCommit
      • Repository: FriendReminders
      • Reference Type: Branch
      • Branch: master
    • Environment:
      • Environment Image: Managed image
      • Operating System: Amazon Linux 2
      • Runtime(s): Standard
      • Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0
      • Environment Type: Linux
      • Privileged: Lựa chọn Select
      • Service role: New select role
      • Role name: codebuild-FriendRemindersBuild-service-role
    • Buildspec:
      • Build specifications: Use a buildspec file
      • Buildspec name - optional: sử dụng buildspec.yml khai báo trong project
    • Artifacts
      • Type: No artifacts
    • Logs:
      • CloudWatch logs - optional: Lựa chọn Select
      • Group name: /aws/codebuild/FriendReminders
      • Stream name: Build

CodeBuild Project Creation Cấu hình CodeBuild Project

Source Code Provider Lựa chọn Source Code Provider

Code Build Environment Settings Thiết lập môi trường thực hiện Build

Chú ý

Trong cấu hình của Environment, do FriendReminders sử dụng Docker Container để đóng gói microservices, chúng ta cần lựa chọn Select cho thuộc tính Privileged.

CloudWatch Log Group Settings Thiết lập CloudWatch Log Group

Click button Create build project.

Build Project của FriendRemindersBuild khi được tạo thành công:

CodeBuild Created Output Hiển thị Build Project trên AWS Console

Lựa chọn button Start build, AWS sẽ chuyển sang màn hình Start build. Giữ nguyên các thông tin cấu hình theo mặc định và click vào button Start build tại cuối màn hình.

Màn hình Build Report hiện ra thông báo trạng thái và kết quả build. Trong lần build đầu tiên, kết quả Failed. Sử dụng thông tin từ Build logs để kiểm tra chi tiết về nguyên nhân lỗi. Chúng ta có đoạn log sau:

[Container] 2020/09/05 02:34:06 Waiting for agent ping
2	[Container] 2020/09/05 02:34:08 Waiting for DOWNLOAD_SOURCE
3	[Container] 2020/09/05 02:34:13 Phase is DOWNLOAD_SOURCE
4	[Container] 2020/09/05 02:34:13 CODEBUILD_SRC_DIR=/codebuild/output/src448314659/src/git-codecommit.ap-southeast-2.amazonaws.com/v1/repos/FriendReminders
5	[Container] 2020/09/05 02:34:13 YAML location is /codebuild/output/src448314659/src/git-codecommit.ap-southeast-2.amazonaws.com/v1/repos/FriendReminders/buildspec.yml
6	[Container] 2020/09/05 02:34:13 Processing environment variables
7	[Container] 2020/09/05 02:34:13 No runtime version selected in buildspec.
8	[Container] 2020/09/05 02:34:13 Moving to directory /codebuild/output/src448314659/src/git-codecommit.ap-southeast-2.amazonaws.com/v1/repos/FriendReminders
9	[Container] 2020/09/05 02:34:13 Registering with agent
10	[Container] 2020/09/05 02:34:13 Phases found in YAML: 3
11	[Container] 2020/09/05 02:34:13  PRE_BUILD: 6 commands
12	[Container] 2020/09/05 02:34:13  BUILD: 5 commands
13	[Container] 2020/09/05 02:34:13  POST_BUILD: 4 commands
14	[Container] 2020/09/05 02:34:13 Phase complete: DOWNLOAD_SOURCE State: SUCCEEDED
15	[Container] 2020/09/05 02:34:13 Phase context status code:  Message: 
16	[Container] 2020/09/05 02:34:13 Entering phase INSTALL
17	[Container] 2020/09/05 02:34:13 Phase complete: INSTALL State: SUCCEEDED
18	[Container] 2020/09/05 02:34:13 Phase context status code:  Message: 
19	[Container] 2020/09/05 02:34:13 Entering phase PRE_BUILD
20	[Container] 2020/09/05 02:34:13 Running command echo Logging in to Amazon ECR...
21	Logging in to Amazon ECR...
22	
23	[Container] 2020/09/05 02:34:13 Running command aws --version
24	aws-cli/1.18.117 Python/3.8.3 Linux/4.14.186-110.268.amzn1.x86_64 exec-env/AWS_ECS_EC2 botocore/1.17.40
25	
26	[Container] 2020/09/05 02:34:19 Running command $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
27	
28	An error occurred (AccessDeniedException) when calling the GetAuthorizationToken operation: User: arn:aws:sts::729365137003:assumed-role/codebuild-FriendRemindersBuild-service-role/AWSCodeBuild-9cc98636-1b1c-47b5-9cc0-71d12e787771 is not authorized to perform: ecr:GetAuthorizationToken on resource: *
29	
30	[Container] 2020/09/05 02:34:20 Command did not exit successfully $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email) exit status 255
31	[Container] 2020/09/05 02:34:20 Phase complete: PRE_BUILD State: FAILED
32	[Container] 2020/09/05 02:34:20 Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email). Reason: exit status 255

Tại dòng 32, PRE_BUILD failed do service-role của FriendRemindersBuild không có quyền thực hiện lệnh aws ecr get-login.

  • Cập nhật codebuild-FriendRemindersBuild-service-role với Policy cho phép sử dụng ECR.

Kiểm tra Policies hiện tại trong service role:

aws iam list-attached-role-policies --role-name codebuild-FriendRemindersBuild-service-role

Output

{
    "AttachedPolicies": [
        {
            "PolicyName": "CodeBuildCloudWatchLogsPolicy-FriendRemindersBuild-ap-southeast-2",
            "PolicyArn": "arn:aws:iam::729365137003:policy/service-role/CodeBuildCloudWatchLogsPolicy-FriendRemindersBuild-ap-southeast-2"
        },
        {
            "PolicyName": "CodeBuildBasePolicy-FriendRemindersBuild-ap-southeast-2",
            "PolicyArn": "arn:aws:iam::729365137003:policy/service-role/CodeBuildBasePolicy-FriendRemindersBuild-ap-southeast-2"
        }
    ]
}

Service role gồm hai policies:

  • CodeBuildCloudWatchLogsPolicy...
  • CodeBuildBasePolicy...

Policies này tạo ra theo mặc định của AWS CodeBuild cho phép FriendRemindersBuild download source code từ CodeCommit Repository, ghi kết quả build log ra CloudWatch, và đưa output artifact lên AWS S3.

  • Bổ sung thêm policy cho phép FriendRemindersBuild truy cập ECR.
aws iam attach-role-policy --role-name codebuild-FriendRemindersBuild-service-role --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser

Có thể kiểm tra kết quả qua câu lệnh list-attached-role-policies.

  • Thực hiện start-build:
aws codebuild start-build --project-name "FriendRemindersBuild"

Build History của FriendRemindersBuild:

CodeBuild History Output Danh sách các kết quả của việc thực hiện Build

Trên AWS Console, ECR -> Repositories -> remindersmgtservice, xác nhận Docker Image

CodeBuild ECR Output Danh sách Docker Images từ quá trình Build trên ECR


CodeBuild & CodeCommit

Sử dụng Lambda function CodeBuildTriggerLambda được thiết lập trong bài AWS Lambda Subscriber, chúng ta sẽ kết nối hoạt động của hai dịch vụ CodeCommit và CodeBuild một cách tự động. Khi source code trên main branch của CodeCommit Repository thay đổi, SNS Topic sẽ gửi notification message để kích hoạt thực thi Lambda CodeBuildTriggerLambda, từ đó gọi đến dịch vụ CodeBuild để thực hiện việc biên dịch source code và tạo một Docker Image mới trên ECR.

CodeBuild CodeCommit Integration Tích hợp dịch vụ CodeCommit và CodeBuild qua Lambda function

Các bước thực hiện:

  • Cập nhật service-role CodeBuildTriggerLambdaRole cho phép Lambda function gọi đến CodeBuild service.
aws iam attach-role-policy --role-name CodeBuildTriggerLambdaRole --policy-arn arn:aws:iam::aws:policy/AWSCodeBuildDeveloperAccess 
  • Sau khi có permission, thay đổi logic Lambda function để gọi đến CodeBuild dựa trên Python SDK boto3

Trong file lambda_function.py:

import boto3

def entrypoint(event, context):
    print('Starting a new build ...')
    build = {
      'projectName': 'FriendRemindersBuild'
    }
    cb = boto3.client('codebuild')
    cb.start_build(**build)
    print('Successfully launched a new CodeBuild project build!')    
  • Zip file và cập nhật Lambda function.

Trong folder lambda-function:

zip function.zip lambda_function.py
aws lambda update-function-code --function-name CodeBuildTriggerLambda --zip-file fileb://function.zip
  • Để kiểm tra kết quả, tạo một thay đổi source code của FriendReminders và đưa lên CodeCommit.

Trong CloudWatch log group /aws/lambda/CodeBuildTriggerLambda, kiểm tra build log:

CodeBuild Trigger Output Dữ liệu Logs từ quá trình thực thi của CodeBuildTriggerLambda

Trong AWS Console, ECR -> Repositories -> remindersmgtservice, xác nhận Docker Images:

ECR Output Kết quả Docker Images từ quá trình Build tích hợp


CodeBuild & Unit Test

Folder Services\RemindersManagement của ứng dụng FriendReminders, chúng ta có hai projects:

  • RemindersManagement.API
  • RemindersManagement.UnitTests

Trong những phần trước, chúng ta sử dụng CodeBuild để thực hiện việc biên dịch và đóng gói Docker Image đối với source code trong project RemindersManagement.API. Tuy vậy, trước khi thực hiện điều này này, CodeBuild nên sử dụng RemindersManagement.UnitTests để thực thi Unit Test Cases đảm bảo tính đúng đắn của logic trong dịch vụ.

Để thực thi Unit Test với CodeBuild, cập nhật file buildspec.yml:

version: 0.2

phases:
  install:
    runtime-versions:
        dotnet: 3.1  
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - aws --version
      - $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
      - REPOSITORY_URI=729365137003.dkr.ecr.ap-southeast-2.amazonaws.com/remindersmgtservice
      - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
      - IMAGE_TAG=${COMMIT_HASH:=latest}
  build:
    commands:
      - echo Build started on `date`
      - echo Running unit tests
      - dotnet test -c Release ./Services/RemindersManagement/RemindersManagement.UnitTests/RemindersManagement.UnitTests.csproj --logger trx --results-directory ./TestResults /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=../../../TestResults/
      - echo Building the Docker image...
      - echo Building for repository $REPOSITORY_URI
      - docker build -t $REPOSITORY_URI:latest ./Services/RemindersManagement/RemindersManagement.API
      - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker images...
      - docker push $REPOSITORY_URI:latest
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      - docker writing image definitions file...

reports:
  GeneralTestsReport:
      file-format: VisualStudioTrx
      files:
          - '**/*'
      base-directory: './TestResults'
  CoverageTestsReport:
      file-format: CoberturaXml
      files:
          - '**/*'
      base-directory: './TestResults'

Những logic bổ sung trong file:

  • install: cài đặt .NET Runtime trên Docker Container của CodeBuild
  • build: thực thi Unit Test trước khi build Docker Image
  • reports: sử dụng outputs từ dotnet test để hiển thị Test Report

Lệnh dotnet test tạo ra hai files trong folder FriendReminders:

  • *.trx: (Vistual Unit Test) thông tin về kết quả thực hiện Test
  • overage.cobertura.xml: thông tin về mật độ thực hiện Test

Tương ứng với những files này, reports khai báo 2 loại Test Reports:

  • GeneralTestsReport
  • CoverageTestsReport

Push buildspec.yml lên AWS CodeCommit. Source code thay đổi kích hoạt thực hiện CodeBuild.

Trong AWS Console, CodeBuild -> ReportReport groups hiển thị Test Report Groups:

  • FriendRemindersBuild-GeneralTestsReport
  • FriendRemindersBuild-CoverageTestsReport

Test Report Groups Test Report Groups

FriendRemindersBuild-GeneralTestsReport cung cấp thông tin số lượng test, thời gian thực hiện, reports

Test Report Output Nội dung tổng kết của Test Report

FriendRemindersBuild-GeneralTestsReport cung cấp thông tin mật độ test, reports

Test Report Coverage Trend Test Report Coverage Trend

Trong Code coverage reports history, lựa chọn một report cụ thể, chúng ta có thông tin chi tiết về mật độ test của từng method

Test Report Output Nội dung chi tiết của Test Report


Tài liệu tham khảo


Copyright © 2019-2022 Tuan Anh Le.