Giới thiệu
Cùng với sự phát triển của ngành công nghệ thông tin trong những năm gần đây, việc sử dụng các dịch vụ điện toán đám mây như Amazon Web Service (AWS) đã không còn quá xa lạ đối với các công ty nói chung và các lập trình viên nói riêng. Cùng với những lợi ích to lớn của việc sử dụng AWS mang lại như: khả năng mở rộng (scalability), tính tin cậy (reliability), tính linh hoạt (flexibility),… việc quản lí chi phí cũng là một vấn đề vô cùng quan trọng và khá đau đầu khi sử dụng các dịch vụ của AWS. Tối ưu chi phí cũng là một trong 6 khía cạnh quan trọng nhất khi chúng ta muốn xây dựng một kiến trúc tốt trên AWS.
Chuỗi bài viết này sẽ giới thiệu đến các bạn những công cụ giúp việc quản lý và tối ưu chi phí khi sử dụng AWS một cách hiệu quả hơn.
Trong bài đầu tiên, chúng ta sẽ cùng tìm hiểu AWS Budget, một công cụ giúp bản quản lý ngân sách sử dụng AWS hiệu quả
AWS Budget là gì?
AWS Budget là một dịch vụ miễn phí của AWS được thiết kế để giúp người dùng quản lý chi phí của họ trong môi trường đám mây của AWS. Dịch vụ này cho phép người dùng thiết lập và theo dõi các ngân sách chi phí và sử dụng tùy chỉnh, và cung cấp cảnh báo khi các ngưỡng ngân sách bị vượt quá hoặc dự báo sẽ vượt quá. Bằng cách này, người dùng có thể kiểm soát và quản lý chi phí của mình một cách hiệu quả, giúp họ tối ưu hóa việc sử dụng tài nguyên và đảm bảo rằng các dự án và ứng dụng của họ đang hoạt động trong phạm vi ngân sách.
Ngoài việc theo dõi ngân sách, bạn cũng có thể thêm các hành động vào ngân sách của mình để kiểm soát các tài nguyên AWS khi ngưỡng ngân sách bị hoặc được dự báo sẽ vượt quá.
Các loại budget:
- Cost budget: theo dõi chi phí của bạn so với số tiền được chỉ định và nhận thông báo khi đạt đến ngưỡng do người dùng xác định. Số tiền dự toán bạn đặt sẽ thể hiện mức chi tiêu dự kiến của bạn trên AWS.
- Usage budget: bạn có thể sử dụng ngân sách sử dụng để giám sát việc sử dụng một số dịch vụ nhất định như Amazon EC2 và Amazon S3.
- Savings Plans budget: Định nghĩa ngưỡng sử dụng và nhận thông báo khi mức sử dụng Savings Plans của bạn giảm xuống dưới ngưỡng đó.
- Reservation budget: Định nghĩa ngưỡng sử dụng và nhận thông báo khi mức sử dụng Reversed Instance của bạn giảm xuống dưới ngưỡng đó.
Tạo và kiểm soát tài nguyên với AWS Budget
Trong phần này chúng ta cùng thực hiện một ví dụ đơn giản sử dụng AWS budget để quản lý chi phí, đồng thời tự động tắt các dịch vụ khác khi vượt qua ngưỡng chi phí định trước. Các bước thực hiện bao gồm:
- Tạo một budget
- Sử dụng dịch vụ SNS để gửi thông báo và trigger các hành động.
- Tạo Lambda Function để tắt các dịch vụ khác như EC2 khi vượt ngưỡng budget
Ngoài ra, khác với những bài viết khác, bài viết này sẽ sử dụng Terraform để tạo và quản lý tài nguyên thay vì sử dụng AWS Console. Terraform là một công cụ mạnh mẽ giúp có việc quản lý tài nguyên bằng mã nguồn (Infrastructure as Code). Bạn có thể tìm hiểu thêm về những lợi ích của IaS tại đây.
Yêu cầu
- Cài đặt terraform: có xem hướng dẫn tại đây
- AWS credentials: bao gồm
access_key
vàsecret_key
. Chúng ta cần AWS credential khi cấu hình provider cho terraform
// filename: provider.tf
provider "aws" {
region = "us-east-1"
access_key = "xxxxxx"
secret_key = "xxxxxx"
}
Tiếp theo chúng ta sẽ định nghĩa cấu hình tài nguyên với terraform
Cấu hình Budget
// filename: budget.tf
resource "aws_budgets_budget" "monthly_cost_budget" {
name = "Monthly-Cost-Budget"
budget_type = "COST"
limit_amount = 100.0
limit_unit = "USD"
time_period_start = "2024-01-01_00:00"
time_period_end = "2024-12-31_23:59"
time_unit = "MONTHLY"
cost_filter {
name = "Service"
values = [
"Amazon Elastic Compute Cloud - Compute",
]
}
notification {
comparison_operator = "GREATER_THAN"
threshold = 90
threshold_type = "PERCENTAGE"
notification_type = "ACTUAL"
subscriber_email_addresses = ["test@example.com"]
}
notification {
comparison_operator = "GREATER_THAN"
notification_type = "ACTUAL"
threshold_type = "PERCENTAGE"
threshold = 80
subscriber_sns_topic_arns = [aws_sns_topic.budget_notifications.arn]
}
}
Trong đó, các thuộc tính của aws_budgets_budget
:
name
: Tên của budget.budget_type
: Loại budget, có thể làCOST
hoặcUSAGE
.limit_amount
: Ngưỡng giới hạn của budget. Ví dụ 100$.limit_unit
: Đơn vị tiền tệ của budget.time_period_start
andtime_period_end
: Khoảng thời gian bắt đầu và kết thúc của budget.time_unit
: đơn vị thời gian budget của bạn, theo thángMONTHLY
, theo quýQUARTERLY
, hoặcANNUALLY
.cost_filter
: Lọc theo một dịch vụ cụ thể. Ở đây, chúng ta quan tâm đến chi phí của EC2.notification
: Cài đặt thông báo khi vượt ngưỡng budget. Ở đây chúng ta sẽ gửi thông báo đến email chỉ định khi chi phí thực tếACTUAL
vượt quá 90% budget. Đồng thời, gửi thông báo đến SNS topicbudget_notifications
khi vượt quá 80% budget. SNS topic này sẽ được hướng dẫn tạo ngay sau đây.
Chi tiết định nghĩa các thuộc tính budget có thể tham khảo tại đây.
Cấu hình SNS topic
// filename: sns.tf
resource "aws_sns_topic" "budget_notifications" {
name = "budget-notifications"
}
resource "aws_sns_topic_subscription" "lambda_subscription" {
topic_arn = aws_sns_topic.budget_notifications.arn
protocol = "lambda"
endpoint = aws_lambda_function.instance_shutdown.arn
}
resource "aws_lambda_permission" "allow_sns" {
statement_id = "AllowExecutionFromSNS"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.instance_shutdown.function_name
principal = "sns.amazonaws.com"
source_arn = aws_sns_topic.budget_notifications.arn
}
Trong phần này, chúng ta định nghĩa 3 tài nguyên:
- SNS topic
budget_notifications
- SNS topic subscription: hàm Lambda
instance_shutdown
sẽ theo dõi và nhận trigger từ SNS topic - Lambda permission: quyền cho phép SNS topic
budget_notifications
gọi hàminstance_shutdown
Cấu hình hàm Lambda và IAM Role cho hàm
// filename: lambda.tf
resource "aws_lambda_function" "instance_shutdown" {
filename = "lambda_function.zip"
function_name = "instanceShutdown"
role = aws_iam_role.lambda_exec.arn
handler = "lambda_function.lambda_handler"
source_code_hash = filebase64sha256("lambda_function.zip")
runtime = "python3.8"
environment {
variables = {
INSTANCE_REGION = "us-east-1"
}
}
}
Các thuộc tính của lambda function instance_shutdown
:
filename
:đường dẫn đến tệp file ZIP chứa code hàm Lambda. Trong trường hợp này, mã được đóng gói tronglambda_function.zip
.function_name
: tên hàmrole
: IAM Role mà hàm Lambda sử dụng để thực hiện các hành động. Ví dụ, Lambda phải có quyền tắt các EC2 instances. Role này sẽ được tạo ngay sau đây.handler
: Điểm đầu vào của hàm Lambda. Trong ví dụ này,lambda_function.lambda_handler
tham chiếu đến hàmlambda_handler
bên trong tệplambda_function.py
.runtime
: Chỉ định môi trường runtime cho hàm Lambda- Ngoài ra, chúng ta định nghĩa mội biến môi trường
INSTANCE_REGION
, biến này sẽ được sử dụng trong hàm Lambda với mục đích là xóa các EC2 instance tại vùng này.
Cấu hình IAM Role cho hàm Lambda
// filename: iam.tf
resource "aws_iam_role" "lambda_exec" {
name = "lambda_exec_role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}
]
})
}
resource "aws_iam_policy" "lambda_ec2_policy" {
name = "lambda_ec2_policy"
description = "Policy to allow Lambda to stop EC2 instances"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"ec2:DescribeInstances",
"ec2:StopInstances"
]
Resource = "*"
}
]
})
}
resource "aws_iam_role_policy_attachment" "lambda_attach" {
role = aws_iam_role.lambda_exec.name
policy_arn = aws_iam_policy.lambda_ec2_policy.arn
}
resource "aws_iam_role_policy_attachment" "lambda_basic_attach" {
role = aws_iam_role.lambda_exec.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
Ở phần này, chúng ta khai báo IAM Role lambda_exec
sử dụng cho hàm Lambda, với 2 policy:
assume_role_policy
: Policy cho phép hàm Lambda sử dụng role nàylambda_ec2_policy
: Policy với 2 quyền là mô tảec2:DescribeInstances
và tắt EC2 Instancesec2:StopInstances
Mã nguồn hàm Lambda
Cuối cùng chúng ta cùng viết mã nguồn cho hàm Lambda như sau:
# filename: lambda_function.py
import boto3
import os
def lambda_handler(event, context):
region = os.environ['INSTANCE_REGION']
ec2 = boto3.client('ec2', region_name=region)
instances = ec2.describe_instances(Filters=[{'Name': 'instance-state-name', 'Values': ['running']}])
for reservation in instances['Reservations']:
for instance in reservation['Instances']:
instance_id = instance['InstanceId']
ec2.stop_instances(InstanceIds=[instance_id])
print(f'Stopped instance: {instance_id}')
Hàm này đơn giản chúng ta stop tất cả các EC2 instance tại vùng được lấy ra từ biến môi trường INSTANCE_REGION
Tạo tài nguyên trên AWS với Terraform
Bây giờ, chúng ta sẽ sử dụng các terraform command để tạo tài nguyên thực sự trên AWS, dựa vào các file cấu hình chúng ta định nghĩa phía trên.
Các terraform command cơ bản như sau:
terraform init
: Khởi tạo môi trườngterraform validate
: validate cú pháp của các file cấu hìnhterraform plan
: plan các thay đổi giữa các file cấu hình hiện tại và môi trường thựcterraform apply
: Tạo hoặc update tài nguyên trên môi trường thậtterraform destroy
: Xóa tài nguyên đã tạo trước đó
Sau khi thực hiện terraform apply
, chúng ta cùng kiểm tra các tài nguyên đã được tạo trên môi trường AWS:
Montly Cost Budget
SNS Budget notification topic
Hàm Lambda thực hiện dừng các EC2 instances khi vượt budget
Kết luận
Trong bài viết này, chúng ta đã cùng tìm hiểu về AWS Budget, một công cụ hiệu quả để quản lý ngân sách khi sử dụng AWS. Đồng thời, chúng ta đã cùng triển khai một ví dụ đơn giản để tắt các tài nguyên đang sử dụng khi đã vượt ngân sách.
Bạn có thể tham khảo toàn bộ source code trong bài viết tại đây.
Bình luận