Bài viết thuộc series “Chinh phục CDK”
Giới thiệu
Trong bài trước, chúng ta đã tìm hiểu về AWS CDK và làm một ví dụ đơn giản. Trong bài này, chúng ta sẽ tìm hiểu chi tiết hơn về các bước để khởi tạo ứng dụng bằng CDK.
Để cung cấp hạ tầng mới sử dụng AWS CDK, ta sẽ làm theo các bước sau đây:
- Bootstrapping
- Khởi tạo ứng dụng với CDK
- Viết code
- Tạo AWS CloudFormation
- Triển khai hạ tầng
Ngoài ra, trong quá trình làm việc với CDK, còn hai bước nữa là:
- Thay đổi cấu hình
- Xóa hạ tầng
Để giúp các bạn hiểu rõ hơn về các bước trên, chúng ta sẽ cùng thực hiện ví dụ tạo S3 Bucket.
Bootstrapping
Đây là bước yêu cầu nếu bạn sử dụng CDK lần đầu để cung cấp hạ tầng cho một tài khoản ở vùng (AWS Region) mà bạn chưa từng sử dụng CDK để tạo hạ tầng trước đó.
Quá trình Bootstrapping sẽ tạo những tài nguyên cần thiết cho CDK có thể sử dụng cho việc cung cấp hạ tầng lên trên AWS. Ví dụ một số tài nguyên mà quá trình bootstrapping
tạo ra là:
- Amazon S3 Bucket để lưu tệp tin YAML trong quá trình cung cấp hạ tầng
- Các IAM Roles cần thiết để CDK có quyền tạo hạ tầng trên AWS
Tất cả các tài nguyên cần thiết đều được định nghĩa bên trong CloudFormation Stack tên là CDKToolkit. Do CloudFormation Stack tồn tại ở các Region khác nhau, nên khi cung cấp hạ tầng ở một Region mới, ta phải thực hiện quá trình bootstrapping
cho Region đó trước khi chạy CDK.
Ví dụ trong bài này ta sẽ tạo S3 Bucket ở us-west-2
với ACCOUNT-NUMBER
là Account ID của bạn.
cdk bootstrap aws://ACCOUNT-NUMBER/us-west-2
⏳ Bootstrapping environment aws://ACCOUNT-NUMBER/us-west-2
...
Đợi quá trình bootstrapping
chạy xong, mở CloudFormation Console ta sẽ thấy CloudFormation Stack là CDKToolkit.
Khởi tạo ứng dụng với CDK
Tiếp theo ta sẽ sử dụng CDK để khởi tạo ứng dụng với ngôn ngữ ta muốn.
mkdir s3-simple && cd s3-simple
cdk init app --language go
Cấu trúc thư mục sau khi chạy xong câu lệnh cdk init
.
.
├── README.md
├── cdk.json
├── go.mod
├── s3-simple.go
└── s3-simple_test.go
cdk.json
chứa câu lệnh CDK biết làm thế chạy CDK codego.mod
chứa thư viện cần thiết cho CDKs3-simple.go
tệp tin ta viết code
Sau khi khởi tạo ứng dụng, ta chạy câu lệnh sau để tải thư viện của CDK.
go get
Viết code
Đoạn code mặc định của tệp tin s3-simple.go
:
package main
import (
"github.com/aws/aws-cdk-go/awscdk/v2"
// "github.com/aws/aws-cdk-go/awscdk/v2/awssqs"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
)
type S3SimpleStackProps struct {
awscdk.StackProps
}
func NewS3SimpleStack(scope constructs.Construct, id string, props *S3SimpleStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
stack := awscdk.NewStack(scope, &id, &sprops)
// The code that defines your stack goes here
// example resource
// queue := awssqs.NewQueue(stack, jsii.String("S3SimpleQueue"), &awssqs.QueueProps{
// VisibilityTimeout: awscdk.Duration_Seconds(jsii.Number(300)),
// })
return stack
}
func main() {
defer jsii.Close()
app := awscdk.NewApp(nil)
NewS3SimpleStack(app, "S3SimpleStack", &S3SimpleStackProps{
awscdk.StackProps{
Env: env(),
},
})
app.Synth(nil)
}
// env determines the AWS environment (account+region) in which our stack is to
// be deployed. For more information see: https://docs.aws.amazon.com/cdk/latest/guide/environments.html
func env() *awscdk.Environment {
// If unspecified, this stack will be "environment-agnostic".
// Account/Region-dependent features and context lookups will not work, but a
// single synthesized template can be deployed anywhere.
//---------------------------------------------------------------------------
return nil
// Uncomment if you know exactly what account and region you want to deploy
// the stack to. This is the recommendation for production stacks.
//---------------------------------------------------------------------------
// return &awscdk.Environment{
// Account: jsii.String("123456789012"),
// Region: jsii.String("us-east-1"),
// }
// Uncomment to specialize this stack for the AWS Account and Region that are
// implied by the current CLI configuration. This is recommended for dev
// stacks.
//---------------------------------------------------------------------------
// return &awscdk.Environment{
// Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")),
// Region: jsii.String(os.Getenv("CDK_DEFAULT_REGION")),
// }
}
Có 3 hàm như sau:
main()
NewS3SimpleStack()
env()
Mình sẽ giải thích cấu trúc code ở các bài tiếp theo, hiện tại ta chỉ cần quan tâm tới hàm env()
.
Hàm env()
dùng để chỉ định tài khoản và AWS Region mà CDK sử dụng cho việc cung cấp hạ tầng. Có 3 lựa chọn sau.
- Sử dụng tài khoản mặc định
return nil
- Chỉ định chính xác tài khoản nào
return &awscdk.Environment{
Account: jsii.String("123456789012"),
Region: jsii.String("us-east-1"),
}
- Sử dụng tài khoản cấu hình bởi CLI
return &awscdk.Environment{
Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")),
Region: jsii.String(os.Getenv("CDK_DEFAULT_REGION")),
}
Hàm NewS3SimpleStack()
được sử dụng để chỉ định các tài nguyên cần tạo, như bạn có thể thấy trong đoạn code bị comment trong hàm:
// queue := awssqs.NewQueue(stack, jsii.String("S3SimpleQueue"), &awssqs.QueueProps{
// VisibilityTimeout: awscdk.Duration_Seconds(jsii.Number(300)),
// })
Đây là đoạn code ta dùng để tạo SQS (Simple Queue Service). Tiếp theo ta sẽ cập nhật lại tệp tin s3-simple.go
thêm vào đoạn code tạo S3 Bucket.
package main
import (
"github.com/aws/aws-cdk-go/awscdk/v2"
"github.com/aws/aws-cdk-go/awscdk/v2/awss3"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
)
type S3SimpleStackProps struct {
awscdk.StackProps
}
func NewS3SimpleStack(scope constructs.Construct, id string, props *S3SimpleStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
stack := awscdk.NewStack(scope, &id, &sprops)
awss3.NewBucket(stack, jsii.String("S3SimpleStack"), &awss3.BucketProps{
Versioned: jsii.Bool(false),
})
return stack
}
func main() {
defer jsii.Close()
app := awscdk.NewApp(nil)
NewS3SimpleStack(app, "S3SimpleStack", &S3SimpleStackProps{
awscdk.StackProps{
Env: env(),
},
})
app.Synth(nil)
}
func env() *awscdk.Environment {
return nil
}
Tạo AWS CloudFormation
Sau khi viết code xong ta cần chạy câu lệnh sau để chuyển CDK code thành CloudFormation, đây cũng là cách để ta xem trước các tài nguyên được tạo.
cdk synth
Kết quả hiển thị của câu lệnh synth
:
Resources:
S3SimpleStack1351D274:
Type: AWS::S3::Bucket
Properties:
BucketName: s3-simple-stack
UpdateReplacePolicy: Retain
DeletionPolicy: Retain
Metadata:
aws:cdk:path: S3SimpleStack/S3SimpleStack/Resource
CDKMetadata:
Type: AWS::CDK::Metadata
Properties:
Analytics: v2:deflate64:H4sIAAAAAAAA/yXITQ5AMBBA4bPYt+M3xJYbcACptmSUaaJtSMTdEav35WVQVpBE4nBcKsNXHOHqvZCGvWtwOVxNkEZ71k706/7YaWfDLvXn1pJCj5ZuNtsU0hqyeEUKZyw2VRbR4hD5HsjjpqH7+wDVL3ZTdwAAAA==
Metadata:
aws:cdk:path: S3SimpleStack/CDKMetadata/Default
Condition: CDKMetadataAvailable
...
Kết quả này được lưu trong thư mục cdk.out
, khi ta chạy câu lệnh deploy
thì CDK sẽ lấy kết quả từ thư mục cdk.out
này để cung cấp hạ tầng.
Triển khai hạ tầng
Cuối cùng ta chạy câu lệnh deploy
:
cdk deploy
Quá trình chạy của câu lệnh deploy
sẽ được hiển thị ở Terminal.
Runtime process exited abnormally: waitid: no child processes
✨ Synthesis time: 3.57s
S3SimpleStack: building assets...
[0%] start: Building eabf63606288f895f151db8ef023c76ee3e697658c028f1d77329ad7cc2c5d26:current_account-current_region
[100%] success: Built eabf63606288f895f151db8ef023c76ee3e697658c028f1d77329ad7cc2c5d26:current_account-current_region
S3SimpleStack: assets built
S3SimpleStack: deploying... [1/1]
[0%] start: Publishing eabf63606288f895f151db8ef023c76ee3e697658c028f1d77329ad7cc2c5d26:current_account-current_region
[100%] success: Published eabf63606288f895f151db8ef023c76ee3e697658c028f1d77329ad7cc2c5d26:current_account-current_region
S3SimpleStack: creating CloudFormation changeset...
[███████████████████▎······································] (1/3)
2:29:12 PM | CREATE_IN_PROGRESS | AWS::CloudFormation::Stack | S3SimpleStack
2:29:18 PM | CREATE_IN_PROGRESS | AWS::S3::Bucket | S3SimpleStack
Sau khi CDK chạy xong, truy cập CloudFormation Console ta sẽ thấy CloudFormation Stack tên là S3SimpleStack. Nhiệm vụ chính của CDK là tạo ra cấu hình của CloudFormation và dùng nó để tạo CloudFormation Stack. Còn lại quá trình tạo hạ tầng sẽ do CloudFormation đảm nhiệm.
Thay đổi cấu hình
Trong quá trình triển khai chắc chắn ta sẽ thay đổi hạ tầng liên tục, CDK có hỗ trợ ta sửa code và triển khai cấu hình thay bị đổi lên trên hạ tầng hiện tại.
Ví dụ ta sửa thuộc tính Versioned
của S3 thành true
:
awss3.NewBucket(stack, jsii.String("S3SimpleStack"), &awss3.BucketProps{
BucketName: jsii.String("s3-simple-stack"),
Versioned: jsii.Bool(true), // change here
})
CDK cung cấp câu lệnh diff
để so sánh khác biệt giữa code hiện tại và cấu hình đã được triển khai.
cdk diff
Resources
[~] AWS::S3::Bucket S3SimpleStack S3SimpleStack1351D274
└─ [+] VersioningConfiguration
└─ {"Status":"Enabled"}
Tiếp theo ta chạy deploy
thì CDK sẽ triển khai cấu hình ta vừa thay đổi lên hạ tầng hiện tại.
cdk deploy
...
S3SimpleStack: creating CloudFormation changeset...
✅ S3SimpleStack
✨ Deployment time: 51.16s
...
Xóa hạ tầng
Nếu ta muốn xóa hạ tầng hiện tại để tiết kiệm tiền thì ta sử dụng câu lệnh destroy
như sau:
$ cdk destroy
Are you sure you want to delete: S3SimpleStack (y/n)?
Chọn y
.
S3SimpleStack: destroying... [1/1]
✅ S3SimpleStack: destroyed
Lúc này tài nguyên trên AWS đã được xóa thành công.
Kết luận
Vậy là ta đã tìm hiểu xong về cách khởi tạo ứng dụng và các bước cần thiết để cung cấp hạ tầng trên AWS bằng CDK. Như bạn thấy thì các bước cần làm của CDK cũng khá giống với Terraform và khá dễ để sử dụng.
Tác giả Quân Huỳnh
Nếu bài viết có gì sai hoặc cần cập nhật thì liên hệ Admin.
Tham gia nhóm chat của DevOps VN tại Telegram.
Kém tiếng Anh và cần nâng cao trình độ giao tiếp: Tại sao bạn học không hiệu quả?