Bài viết này mô tả cách sử dụng mô-đun AWS CDK Pipelines để tuân thủ mô hình phát triển Gitflow bằng cách sử dụng AWS Cloud Development Kit (AWS CDK). Các nhóm phát triển phần mềm thường tuân thủ một chiến lược branch nghiêm ngặt trong quá trình phát triển giải pháp. Các branch mới thường cần một bản sao cách ly của tài nguyên cơ sở hạ tầng của riêng họ để phát triển tính năng mới.
CDK Pipelines là một mô-đun thư viện xây dựng cho việc triển khai liên tục các ứng dụng AWS CDK. CDK Pipelines tự cập nhật: nếu bạn thêm các giai đoạn hoặc các ngăn xếp ứng dụng, thì pipeline sẽ tự động cấu hình lại để triển khai các giai đoạn và/hoặc các ngăn xếp mới đó.
Giải pháp sau đây tạo một pipeline AWS CDK mới trong tài khoản phát triển cho mỗi branch mới được tạo trong kho lưu trữ nguồn (AWS CodeCommit). Khi một branch bị xóa, pipeline và tất cả các tài nguyên liên quan cũng được hủy từ tài khoản. Mô hình GitFlow này cho việc triển khai cơ sở hạ tầng cho phép các nhà phát triển làm việc độc lập với nhau, đồng thời, ngay cả trong cùng một ngăn xếp của ứng dụng.
Tổng quan về giải pháp
Sơ đồ dưới đây cung cấp một cái nhìn tổng quan về giải pháp. Có một pipeline mặc định chịu trách nhiệm triển khai tài nguyên cho các môi trường ứng dụng khác nhau (ví dụ: Development, Pre-Prod và Prod). Mã nguồn được lưu trữ trong CodeCommit. Khi có sự thay đổi mới được đẩy lên branch mã nguồn CodeCommit mặc định, AWS CodePipeline chạy pipeline mặc định. Khi pipeline mặc định được triển khai, nó tạo ra hai hàm AWS Lambda.
Hai hàm Lambda này được gọi bởi sự kiện CloudWatch của CodeCommit khi một branch mới trong kho lưu trữ được tạo hoặc xóa. Hàm Lambda Create sử dụng mô-đun CodeBuild của boto3 để tạo một dự án AWS CodeBuild xây dựng pipeline cho feature branch. pipeline tính năng này bao gồm một giai đoạn xây dựng và một giai đoạn pipeline cập nhật tùy chọn cho chính nó. Hàm Lambda Destroy tạo một dự án CodeBuild khác để làm sạch tất cả các tài nguyên của feature branch và pipeline tính năng.
Hình 1. Sơ đồ kiến trúc.
Yêu cầu tiên quyết
Trước khi bắt đầu hướng dẫn này, bạn nên có các yêu cầu tiên quyết sau:
- Một tài khoản AWS
- AWS CDK đã được cài đặt
- Python3 đã được cài đặt
- Jq (trình xử lý JSON) đã được cài đặt
- Hiểu biết cơ bản về Continuous Integration/Continuous Development (CI/CD) Pipelines
Cài đặt ban đầu
Tải xuống kho lưu trữ từ GitHub:
# Command to clone the repository
git clone https://github.com/aws-samples/multi-branch-cdk-pipelines.git
cd multi-branch-cdk-pipelines
Tạo một kho lưu trữ CodeCommit mới trong Tài khoản AWS và khu vực mà bạn muốn triển khai pipeline và tải mã nguồn từ trên xuống kho lưu trữ này. Trong tệp config.ini, thay đổi các biến repository_name và region tương ứng.
Hãy chắc chắn rằng bạn đã thiết lập môi trường Python mới. Cài đặt các phần phụ thuộc:
pip install -r requirements.txt
Chạy tập lệnh initial-deploy.sh để khởi tạo các môi trường phát triển và sản xuất và triển khai pipeline mặc định. Bạn sẽ được yêu cầu cung cấp các tham số sau: (1) ID tài khoản phát triển, (2) Tên hồ sơ AWS tài khoản phát triển, (3) ID tài khoản sản xuất và (4) Tên hồ sơ AWS tài khoản sản xuất.
sh ./initial-deploy.sh –dev_account_id <YOUR DEV ACCOUNT ID> —
dev_profile_name <YOUR DEV PROFILE NAME> –prod_account_id <YOUR PRODUCTION
ACCOUNT ID> –prod_profile_name <YOUR PRODUCTION PROFILE NAME>
Pipeline mặc định
Trong pipeline CI/CD, chúng tôi thiết lập một điều kiện if để triển khai các tài nguyên của branch mặc định chỉ khi branch hiện tại là branch mặc định. branch mặc định được truy xuất theo cách tự động từ kho lưu trữ CodeCommit. Chúng tôi triển khai một Amazon Simple Storage Service (Amazon S3) Bucket và hai hàm Lambda. Bucket này chịu trách nhiệm lưu trữ các đoạn mã nguồn CodeBuild của các feature branch. Hàm Lambda đầu tiên được kích hoạt khi một branch mới được tạo trong CodeCommit. Hàm thứ hai được kích hoạt khi một branch bị xóa.
if branch == default_branch:
…
# Artifact bucket for feature AWS CodeBuild projects
artifact_bucket = Bucket(
self,
‘BranchArtifacts’,
encryption=BucketEncryption.KMS_MANAGED,
removal_policy=RemovalPolicy.DESTROY,
auto_delete_objects=True
)
…
# AWS Lambda function triggered upon branch creation
create_branch_func = aws_lambda.Function(
self,
‘LambdaTriggerCreateBranch’,
runtime=aws_lambda.Runtime.PYTHON_3_8,
function_name=’LambdaTriggerCreateBranch’,
handler=’create_branch.handler’,
code=aws_lambda.Code.from_asset(path.join(this_dir, ‘code’)),
environment={
“ACCOUNT_ID”: dev_account_id,
“CODE_BUILD_ROLE_ARN”: iam_stack.code_build_role.role_arn,
“ARTIFACT_BUCKET”: artifact_bucket.bucket_name,
“CODEBUILD_NAME_PREFIX”: codebuild_prefix
},
role=iam_stack.create_branch_role)
# AWS Lambda function triggered upon branch deletion
destroy_branch_func = aws_lambda.Function(
self,
‘LambdaTriggerDestroyBranch’,
runtime=aws_lambda.Runtime.PYTHON_3_8,
function_name=’LambdaTriggerDestroyBranch’,
handler=’destroy_branch.handler’,
role=iam_stack.delete_branch_role,
environment={
“ACCOUNT_ID”: dev_account_id,
“CODE_BUILD_ROLE_ARN”: iam_stack.code_build_role.role_arn,
“ARTIFACT_BUCKET”: artifact_bucket.bucket_name,
“CODEBUILD_NAME_PREFIX”: codebuild_prefix,
“DEV_STAGE_NAME”: f'{dev_stage_name}-{dev_stage.main_stack_name}’
},
code=aws_lambda.Code.from_asset(path.join(this_dir,
‘code’)))
Tiếp theo, kho lưu trữ CodeCommit được cấu hình để kích hoạt các hàm Lambda này dựa trên hai sự kiện:
(1) Tham chiếu được tạo
# Configure AWS CodeCommit to trigger the Lambda function when a new branch is created
repo.on_reference_created(
‘BranchCreateTrigger’,
description=”AWS CodeCommit reference created event.”,
target=aws_events_targets.LambdaFunction(create_branch_func))
(2) Đã xóa tham chiếu
# Configure AWS CodeCommit to trigger the Lambda function when a branch is deleted
repo.on_reference_deleted(
‘BranchDeleteTrigger’,
description=”AWS CodeCommit reference deleted event.”,
target=aws_events_targets.LambdaFunction(destroy_branch_func))
Lambda functions
Hai hàm Lambda xây dựng và phá hủy môi trường ứng dụng được ánh xạ vào từng feature branch. Một sự kiện Amazon CloudWatch kích hoạt hàm LambdaTriggerCreateBranch mỗi khi có một branch mới được tạo ra. Khách hàng CodeBuild từ boto3 tạo ra giai đoạn xây dựng và triển khai pipeline tính năng.
Tạo function
Hàm tạo triển khai một pipeline tính năng bao gồm một giai đoạn xây dựng và một giai đoạn pipeline cập nhật tùy chọn cho chính nó. Pipeline tải mã feature branch từ kho lưu trữ CodeCommit, khởi động hành động Xây dựng và Kiểm tra bằng cách sử dụng CodeBuild và lưu một cách an toàn các đối tượng đã xây dựng vào sổ lưu trữ S3.
Mã xử lý hàm Lambda có dạng sau:
def handler(event, context):
“””Lambda function handler”””
logger.info(event)
reference_type = event[‘detail’][‘referenceType’]
try:
if reference_type == ‘branch’:
branch = event[‘detail’][‘referenceName’]
repo_name = event[‘detail’][‘repositoryName’]
client.create_project(
name=f'{codebuild_name_prefix}-{branch}-create’,
description=”Build project to deploy branch pipeline”,
source={
‘type’: ‘CODECOMMIT’,
‘location’: f’https://git-codecommit.{region}.amazonaws.com/v1/repos/{repo_name}’,
‘buildspec’: generate_build_spec(branch)
},
sourceVersion=f’refs/heads/{branch}’,
artifacts={
‘type’: ‘S3’,
‘location’: artifact_bucket_name,
‘path’: f'{branch}’,
‘packaging’: ‘NONE’,
‘artifactIdentifier’: ‘BranchBuildArtifact’
},
environment={
‘type’: ‘LINUX_CONTAINER’,
‘image’: ‘aws/codebuild/standard:4.0’,
‘computeType’: ‘BUILD_GENERAL1_SMALL’
},
serviceRole=role_arn
)
client.start_build(
projectName=f’CodeBuild-{branch}-create’
)
except Exception as e:
logger.error(e)
Tạo nội dung tập tin buildspec.yaml cho dự án CodeBuild của branch:
version: 0.2
env:
variables:
BRANCH: {branch}
DEV_ACCOUNT_ID: {account_id}
PROD_ACCOUNT_ID: {account_id}
REGION: {region}
phases:
pre_build:
commands:
– npm install -g aws-cdk && pip install -r requirements.txt
build:
commands:
– cdk synth
– cdk deploy –require-approval=never
artifacts:
files:
– ‘**/*’
Destroy function
Lambda thứ hai chịu trách nhiệm về việc phá hủy tài nguyên của một feature branch. Khi một feature branch bị xóa, một sự kiện Amazon CloudWatch kích hoạt chức năng Lambda này. Chức năng tạo một Dự án CodeBuild để phá hủy đường ống tính năng và tất cả các tài nguyên liên quan được tạo ra bởi đường ống đó. Thuộc tính nguồn của Dự án CodeBuild là mã nguồn của feature branch được lưu trữ dưới dạng một tài sản trong Amazon S3.
Mã nguồn xử lý của chức năng Lambda như sau:
def handler(event, context):
logger.info(event)
reference_type = event[‘detail’][‘referenceType’]
try:
if reference_type == ‘branch’:
branch = event[‘detail’][‘referenceName’]
client.create_project(
name=f'{codebuild_name_prefix}-{branch}-destroy’,
description=”Build project to destroy branch resources”,
source={
‘type’: ‘S3’,
‘location’: f'{artifact_bucket_name}/{branch}/CodeBuild-{branch}-create/’,
‘buildspec’: generate_build_spec(branch)
},
artifacts={
‘type’: ‘NO_ARTIFACTS’
},
environment={
‘type’: ‘LINUX_CONTAINER’,
‘image’: ‘aws/codebuild/standard:4.0’,
‘computeType’: ‘BUILD_GENERAL1_SMALL’
},
serviceRole=role_arn
)
client.start_build(
projectName=f’CodeBuild-{branch}-destroy’
)
client.delete_project(
name=f’CodeBuild-{branch}-destroy’
)
client.delete_project(
name=f’CodeBuild-{branch}-create’
)
except Exception as e:
logger.error(e)
Nội dung `buildspec.yaml` của dự án CodeBuild để destroy:
version: 0.2
env:
variables:
BRANCH: {branch}
DEV_ACCOUNT_ID: {account_id}
PROD_ACCOUNT_ID: {account_id}
REGION: {region}
phases:
pre_build:
commands:
– npm install -g aws-cdk && pip install -r requirements.txt
build:
commands:
– cdk destroy cdk-pipelines-multi-branch-{branch} –force
– aws cloudformation delete-stack –stack-name {dev_stage_name}-{branch}
– aws s3 rm s3://{artifact_bucket_name}/{branch} –recursive
Tạo một feature branch
Trên bản sao cục bộ của kho lưu trữ trên máy tính của bạn, hãy tạo một feature branch mới bằng các lệnh git sau đây. Thay thế user-feature-123 bằng một tên duy nhất cho feature branch của bạn. Lưu ý rằng tên feature branch này phải tuân thủ các ràng buộc về tên của CodePipeline, vì nó sẽ được sử dụng để đặt tên cho một đường ống duy nhất sau này trong hướng dẫn này.
# Create the feature branch
git checkout -b user-feature-123
git push origin user-feature-123
Chức năng Lambda đầu tiên sẽ triển khai dự án CodeBuild, sau đó triển khai đường ống tính năng. Quá trình này có thể mất vài phút. Bạn có thể đăng nhập vào AWS Console và xem dự án CodeBuild đang chạy trong CodeBuild.
Hình 2. AWS Console – Dự án CodeBuild.
Sau khi quá trình xây dựng hoàn thành thành công, bạn có thể thấy đường ống tính năng đã triển khai trong CodePipelines.
Hình 3. AWS Console – Các đường ống CodePipeline.
Dự án kích hoạt S3 Lambda từ Mẫu AWS CDK được sử dụng làm các tài nguyên cơ sở hạ tầng để thực hiện giải pháp này. Nội dung được đặt trong thư mục src và được triển khai bởi đường ống. Khi truy cập trang điều khiển Lambda, bạn có thể thấy hai hàm: một bởi đường ống mặc định và một bởi đường ống tính năng của chúng tôi.
Hình 4. AWS Console – Các hàm Lambda.
Destroy một feature branch
Có hai cách phổ biến để loại bỏ các feature branch. Cách thứ nhất liên quan đến một yêu cầu kéo, còn được gọi là “PR”. Điều này xảy ra khi hợp nhất một feature branch trở lại branch mặc định. Khi nó được hợp nhất, feature branch sẽ tự động đóng cửa. Cách thứ hai là xóa feature branch một cách rõ ràng bằng cách chạy các lệnh git sau đây:
# delete branch local
git branch -d user-feature-123
# delete branch remote
git push origin –delete user-feature-123
Dự án CodeBuild chịu trách nhiệm về việc hủy diệt tài nguyên tính năng đang được kích hoạt. Bạn có thể xem nhật ký dự án trong quá trình hủy diệt tài nguyên trong CodeBuild, trong Lịch sử xây dựng.
Hình 5. AWS Console – Các dự án CodeBuild.
Dọn dẹp
Để tránh gánh chi phí trong tương lai, hãy đăng nhập vào bảng điều khiển AWS của các tài khoản khác nhau mà bạn đã sử dụng, điều hướng đến bảng điều khiển AWS CloudFormation của các Khu vực mà bạn đã chọn triển khai, và chọn và bấm vào Xóa trên các bảng điều khiển chính và branch.
Kết luận
Bài viết này đã chỉ ra cách bạn có thể làm việc với chiến lược dựa trên sự kiện và AWS CDK để triển khai luồng đường ống đa branch bằng cách sử dụng AWS CDK Pipelines. Các giải pháp được mô tả tận dụng Lambda và CodeBuild để cung cấp một sự triển khai động lực cho nhiều branch và đường ống.
Để biết thêm thông tin về CDK Pipelines và tất cả các cách mà nó có thể được sử dụng, hãy xem tài liệu tham khảo CDK Pipelines.