Bài viết thuộc series “Chinh phục CDK”
Giới thiệu
Trong bài này chúng ta sẽ tìm hiểu sâu hơn về Stack và cách sử dụng tài nguyên ở một Stack này cho các Stack khác.
Mục lục
- Stack
- Sử dụng Construct giữa các Stack
- Áp dụng
- Kết luận
- Bài viết liên quan
Stack
Như ta đã tìm hiểu ở các bài trước, Stack là tập hợp các tài nguyên có liên quan với nhau, mục đích của Stack là ta giúp dễ dàng trong việc quản lý và cấu trúc mã nguồn.
Trong một ứng dụng AWS CDK có thể có một hay nhiều Stack, ví dụ:
app := awscdk.NewApp(nil)
MyFirstStack(app, "stack1")
MySecondStack(app, "stack2")
app.Synth(nil)Để liệt kê toàn bộ Stack ta sử dụng câu lệnh cdk ls:
stack1
stack2Khi ta chạy câu lệnh synth để tạo AWS CloudFormation cho ứng dụng nhiều Stack, truyền tên của Stack vào:
cdk synth stack1Với AWS CDK và Stack ta có thể dễ dàng cấu trúc các tài nguyên cần thiết cho các môi trường khác nhau. Ví dụ ta có một ứng dụng và cần triển khai hạ tầng cho môi trường dev và prod. Hạ tầng của ta gồm ba Stack sau: Application Stack, Monitoring Stack và CI/CD Stack.
Ở môi trường dev thông thường ta sẽ không cần Monitoring Stack để tiết kiệm chi phí. Để tạo được hạ tầng cho hai môi trường với yêu cầu trên khá dễ dàng trong CDK. Ví dụ như sau, ta tạo 3 hàm cho 3 Stack:
Tiếp theo ta viết thêm một hàm để kết hợp 3 Stack ở trên và dùng câu lệnh if để so sánh nếu là prod thì ta mới tạo Monitoring Stack:
func NewService(scope constructs.Construct, id string, props *ServiceProps) {
stack := awscdk.NewStage(scope, &id, &awscdk.StageProps{
Env: env(),
})
if props != nil && props.Prod {
NewMonitoringStack(stack, "monitoring")
}
NewAppStack(stack, "app")
NewCICDStack(stack, "cicd")
}Cập nhật lại hàm main():
Chạy câu lệnh ls để xem các Stack được tạo ra:
cdk lsdev/app
dev/cicd
prod/app
prod/cicd
prod/monitoringNhư ta thấy với CDK việc xây dựng hạ tầng cho các môi trường khác nhau rất dễ dàng.
Sử dụng Construct giữa các Stack
Một vấn đề khó về mặt tổ chức hay xảy ra khi ta sử dụng các công cụ IaC để tạo hạ tầng là: định nghĩa được các tài nguyên chung và sử dụng cho các hạ tầng khác nhau.
Ví dụ ta có một trường hợp sau: dự án của ta phát triển trên AWS với cấu trúc Microservices và ta quyết định sử dụng Terraform để làm công cụ tạo hạ tầng. Ta tạo một source code cho mỗi Service và viết code để tạo hạ tầng. Thông thường ta sẽ tạo AWS VPC (Virtual Private Cloud) trước và sau đó tạo các tài nguyên khác nằm trong VPC đó, mọi thứ đều ổn.
Tiếp theo dự án của ta mở rộng thêm và nó cần thêm Service. Ta tạo thêm một source code và viết code, nhưng ta phát hiện Service mới này ta cần nó nằm trong VPC cùng với Service trước đó. Lúc này vấn đề đã xảy ra, làm sao ta sử dụng được VPC ta đã tạo trước đó?
Với Terraform ta làm như sau:
data "aws_vpc" "vpc" {
id = var.vpc_id // Giá trị ID của VPC ta đã tạo
}Điều này không có gì sai, nhưng nó làm dự án của ta khó về mặt tổ chức source code và quản lý tài nguyên. Tài nguyên của source code này lại được để cứng với giá trị của source code khác. Mình sẽ không đề cập cách giải quyết vấn đề với Terraform ở bài này.
Với CDK ta có thể giải quyết vấn đề này khá đơn giản bằng cách truyền Construct giữa các Stack. Để hiểu rõ hơn ta làm một ví dụ tạo hạ tầng cho hệ thống Microservices gồm hai Service là User và Post.
Áp dụng
Tạo thư mục và khởi tạo ứng dụng
mkdir referencing && cd referencingcdk init --language go && go getTạo thêm thư mục stack với 3 tệp tin như sau:
└── stack
├── global.go
├── post-service-stack.go
└── user-service-stack.goTất cả các tài nguyên chung ta để trong tệp tin global.go:
Hai tệp tin còn lại ta viết code cho User Service và Post Service. Tệp tin user-service-stack.go:
Tệp tin post-service-stack.go:
Ở tệp tin referencing.go ta tạo Global Stack và truyền các tài nguyên liên quan cho các Stack còn lại.
Chạy câu lệnh cdk ls để liệt kê Stack:
GlobalStack
PostServiceStack
UserServiceStackTiếp theo chạy câu lệnh deploy để tạo tài nguyên. Lưu ý là vì UserServiceStack và PostServiceStack đều phụ thuộc vào tài nguyên của GlobalStack nên ta cần tạo GlobalStack trước.
Ta có thể chạy cdk --all để CDK tự động tạo hạ tầng theo thứ tự cho ta, nhưng trong môi trường thực tế ta nên chỉ định từng Stack cụ thể khi triển khai cho chắc ăn.
cdk deploy GlobalStackcdk deploy PostServiceStackcdk deploy UserServiceStackCác bạn nhớ xóa tài nguyên khi hoàn thành để tránh mất phí.
Kết luận
Vậy là ta đã tìm hiểu kĩ hơn về cách sử dụng Stack trong CDK. Với CDK thì việc tổ chức source code đơn giản hơn khá nhiều so với các công cụ IaC khác.
Tác giả Quân Huỳnh
First AI Journey for DevOps:
- PromptOps: From YAML to AI
- The DevOps AI Advantage
- The AIOps Book