[P3] CDK App Lifecycle & Synthesizing: Hiểu sâu về quá trình hoạt động của AWS CDK
AWS CDK (Cloud Development Kit) có một vòng đời phức tạp để chuyển đổi từ code thành infrastructure thực tế. Hiểu rõ về các giai đoạn này là nền tảng quan trọng để phát triển và debug ứng dụng CDK hiệu quả.
Mục đích : Định nghĩa và cấu hình các resource infrastructure.
Hoạt động chính :
__init__
.Ví dụ về Construction Phase:
# Python
class ApiLambdaConstruct(Construct):
def __init__(self, scope: Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
# Định nghĩa Lambda Function
self.handler = _lambda.Function(
self, 'ApiHandler',
runtime=_lambda.Runtime.PYTHON_3_9,
code=_lambda.Code.from_asset('lambda'),
handler='index.handler',
environment={
'ENVIRONMENT': 'dev'
}
)
# Định nghĩa API Gateway
self.api = apigw.RestApi(
self, 'SampleApi',
rest_api_name='Sample API',
description='API for demonstrating CDK lifecycle'
)
# Tích hợp Lambda với API Gateway
integration = apigw.LambdaIntegration(self.handler)
self.api.root.add_method('GET', integration
Thuật ngữ:
prepare()
(nếu có) trong constructs (đối với các phiên bản CDK cũ hơn, phiên bản mới đã loại bỏ prepare()
)Ví dụ về Aspects trong Preparation Phase:
# Python
class SecurityHeadersAspect(IAspect):
def visit(self, node: IConstruct) -> None:
if isinstance(node, apigw.RestApi):
# Thêm security headers cho API Gateway
node.add_gateway_response(
"DEFAULT_4XX",
response_parameters={
"gatewayresponse.header.Strict-Transport-Security": "'max-age=31536000; includeSubdomains; preload'",
"gatewayresponse.header.Content-Security-Policy": "'default-src https:'"
}
)
# Áp dụng Aspect
cdk.Aspects.of(self).add(SecurityHeadersAspect())
Giải thích chi tiết về Aspect:
Aspects trong AWS CDK là một cơ chế cho phép bạn áp dụng một hoạt động hoặc logic nào đó lên tất cả hoặc một nhóm constructs trong cây constructs của bạn.
Chúng hoạt động bằng cách duyệt qua toàn bộ cây construct và áp dụng phương thức visit
của Aspect lên mỗi construct.
Sử dụng Aspects, bạn có thể:
Ví dụ 1: Thêm Tags cho tất cả các tài nguyên
Giả sử bạn muốn thêm một tag chung cho tất cả các tài nguyên trong stack của bạn, ví dụ: Environment: Production
.
from aws_cdk import (
core as cdk,
aws_s3 as s3,
)
class TagAllResourcesAspect(cdk.IAspect):
def __init__(self, key: str, value: str):
self.key = key
self.value = value
def visit(self, node: cdk.IConstruct) -> None:
# Kiểm tra nếu node là một tài nguyên CloudFormation
if isinstance(node, cdk.CfnResource):
cdk.Tags.of(node).add(self.key, self.value)
# Sử dụng Aspect trong Stack
class MyStack(cdk.Stack):
def __init__(self, scope: cdk.Construct, id: str, **kwargs):
super().__init__(scope, id, **kwargs)
# Định nghĩa các tài nguyên, ví dụ: S3 Bucket
bucket = s3.Bucket(self, "MyBucket")
# Áp dụng Aspect để thêm tag
cdk.Aspects.of(self).add(TagAllResourcesAspect("Environment", "Production"))
Ví dụ 2: Kiểm tra tính năng mã hóa trên tất cả S3 Bucket
Bạn muốn đảm bảo rằng tất cả các S3 Bucket được tạo đều có bật tính năng mã hóa.
from aws_cdk import (
core as cdk,
aws_s3 as s3,
)
class EncryptBucketAspect(cdk.IAspect):
def visit(self, node: cdk.IConstruct) -> None:
if isinstance(node, s3.CfnBucket):
if node.bucket_encryption is None:
# Thêm cấu hình mã hóa mặc định
node.bucket_encryption = s3.CfnBucket.BucketEncryptionProperty(
server_side_encryption_configuration=[
s3.CfnBucket.ServerSideEncryptionRuleProperty(
server_side_encryption_by_default=s3.CfnBucket.ServerSideEncryptionByDefaultProperty(
sse_algorithm="AES256"
)
)
]
)
# Sử dụng Aspect trong Stack
class MyStack(cdk.Stack):
def __init__(self, scope: cdk.Construct, id: str, **kwargs):
super().__init__(scope, id, **kwargs)
# Tạo S3 Bucket mà không chỉ định mã hóa
bucket = s3.Bucket(self, "MyUnencryptedBucket")
# Áp dụng Aspect để đảm bảo mã hóa
cdk.Aspects.of(self).add(EncryptBucketAspect())
Lợi ích của việc sử dụng Aspects
Một số trường hợp sử dụng Aspects
Lưu ý : Trong các phiên bản AWS CDK mới hơn, phương thức prepare()
đã bị loại bỏ. Thay vào đó, bạn nên sử dụng Aspects hoặc các pattern khác để thực hiện các thao tác chuẩn bị.
Mục đích :Giai đoạn này đảm bảo tính hợp lệ của configuration:
Hoạt động chính :
validate()
trong constructs.Ví dụ về Validation:
# Python
def validate(self) -> List[str]:
errors = []
# Kiểm tra biến môi trường
if 'ENVIRONMENT' not in self.handler.environment:
errors.append('Lambda function must have ENVIRONMENT variable defined')
# Kiểm tra phương thức API
if not any(method.http_method == 'GET' for method in self.api.root.methods):
errors.append('API must have at least one GET method')
return errors
cdk synth
hoặc app.synth()
.cdk.out
.# Synthesis tất cả stacks
cdk synth
# Synthesis một stack cụ thể
cdk synth my-stack-name
# Synthesis và xuất output ra file
cdk synth --output=template.yaml
cdk.out/
├── my-stack.template.json # CloudFormation template
├── assets.json # Asset metadata
├── manifest.json # Deployment manifest
├── tree.json # Construct tree
└── asset.{hash}/ # Asset bundles (Lambda code, etc.)
__init__
VS Code extensions hữu ích:
class FullStackExample(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# Construction Phase
api_lambda = ApiLambdaConstruct(self, 'ApiLambda')
# Preparation Phase (Aspects)
cdk.Aspects.of(self).add(SecurityHeadersAspect())
# Thêm monitoring và alerting
alarm = cloudwatch.Alarm(
self, 'ApiErrors',
metric=api_lambda.api.metric_4xx_error(),
threshold=10,
evaluation_periods=3
)
# Outputs
CfnOutput(self, 'ApiUrl',
value=api_lambda.api.url,
description='API Gateway URL'
)
App
└── FullStackExample (Stack)
├── ApiLambda
│ ├── ApiHandler (Lambda)
│ └── SampleApi (API Gateway)
└── ApiErrors (CloudWatch Alarm)
Hiểu rõ về vòng đời của CDK app và quá trình synthesis là nền tảng quan trọng để:
Trong loạt bài tiếp theo, chúng ta sẽ đi sâu vào: