Giới thiệu
Triển khai ứng dụng trên đám mây là một trong những xu hướng phổ biến nhất hiện nay. Amazon Elastic Container Service (ECS) cho phép bạn chạy các ứng dụng container mà không cần quản lý máy chủ, mang lại sự thuận tiện và khả năng mở rộng. Bài viết này sẽ hướng dẫn bạn cách triển khai một ứng dụng Node.js đơn giản trên ECS với Fargate và Terraform, sử dụng các module cộng đồng của AWS.
Kiến trúc tổng quan
Trong hướng dẫn này, chúng ta sẽ xây dựng một kiến trúc bao gồm:
- VPC với các subnet công cộng và riêng tư để đảm bảo tính khả dụng cao.
- ECS Cluster để chạy các nhiệm vụ ECS.
- Application Load Balancer (ALB) để tiếp nhận lưu lượng truy cập từ internet và chuyển tiếp đến các nhiệm vụ ECS.
Sơ đồ kiến trúc
Các bước triển khai
Bước 1: Tạo VPC và ECS Cluster với Terraform
Chúng ta sẽ sử dụng các module VPC và ECS từ cộng đồng AWS.
hcl
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = "${var.project_name}-vpc"
cidr = var.vpc_cidr
azs = var.availability_zones
private_subnets = var.private_subnets
public_subnets = var.public_subnets
enable_nat_gateway = true
single_nat_gateway = true
enable_dns_hostnames = true
enable_dns_support = true
tags = var.common_tags
}
module "ecs_cluster" {
source = "terraform-aws-modules/ecs/aws//modules/cluster"
version = "~> 5.0"
cluster_name = "${var.project_name}-cluster"
fargate_capacity_providers = {
FARGATE = {
default_capacity_provider_strategy = {
weight = 50
base = 20
}
}
FARGATE_SPOT = {
default_capacity_provider_strategy = {
weight = 50
}
}
}
tags = var.common_tags
}
Bước 2: Tạo IAM Roles cho ECS
Chúng ta cần các IAM roles để ECS có thể kéo hình ảnh từ ECR và ghi log.
hcl
resource "aws_iam_role" "ecs_execution_role" {
name = "${var.project_name}-ecs-execution-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ecs-tasks.amazonaws.com"
}
}]
})
tags = var.common_tags
}
resource "aws_iam_role_policy_attachment" "ecs_execution_role_policy" {
role = aws_iam_role.ecs_execution_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}
Bước 3: Tạo ALB và Target Group
ALB sẽ sống trong các subnet công cộng và định tuyến lưu lượng đến các nhiệm vụ ECS đang chạy trong các subnet riêng tư.
hcl
resource "aws_security_group" "alb" {
name_prefix = "${var.project_name}-alb"
vpc_id = module.vpc.vpc_id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = merge(var.common_tags, {
Name = "${var.project_name}-alb-sg"
})
}
resource "aws_lb" "main" {
name = "${var.project_name}-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = module.vpc.public_subnets
tags = var.common_tags
}
Bước 4: Định nghĩa nhiệm vụ ECS với hình ảnh Node.js
Chúng ta sẽ sử dụng hình ảnh ECR công khai của ứng dụng Node.js.
hcl
resource "aws_ecs_task_definition" "nodejs_app" {
family = "${var.project_name}-task"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = tostring(var.task_cpu)
memory = tostring(var.task_memory)
execution_role_arn = aws_iam_role.ecs_execution_role.arn
task_role_arn = aws_iam_role.ecs_task_role.arn
container_definitions = jsonencode([{
name = "nodejs-app"
image = var.ecr_repository_url
portMappings = [{
containerPort = var.app_port
protocol = "tcp"
}]
logConfiguration = {
logDriver = "awslogs"
options = {
"awslogs-group" = aws_cloudwatch_log_group.ecs_logs.name
"awslogs-region" = var.aws_region
"awslogs-stream-prefix" = "ecs"
}
}
environment = [{
name = "NODE_ENV"
value = "production"
}, {
name = "PORT"
value = tostring(var.app_port)
}]
essential = true
}])
tags = var.common_tags
}
Bước 5: Tạo dịch vụ ECS với Auto Scaling
Gắn dịch vụ ECS vào nhóm mục tiêu ALB và cấu hình auto scaling.
hcl
module "ecs_service" {
source = "terraform-aws-modules/ecs/aws//modules/service"
version = "~> 5.0"
name = "${var.project_name}-service"
cluster_arn = module.ecs_cluster.arn
task_definition_arn = aws_ecs_task_definition.nodejs_app.arn
desired_count = var.min_capacity
autoscaling_min_capacity = var.min_capacity
autoscaling_max_capacity = var.max_capacity
service_tags = var.common_tags
}
Truy cập ứng dụng
Sau khi triển khai, Terraform sẽ xuất ra tên DNS của ALB. Mở nó trong trình duyệt của bạn để kiểm tra ứng dụng.
Thực hành tốt nhất
- Sử dụng IAM Roles thích hợp: Đảm bảo rằng các IAM roles có quyền hạn cần thiết để ECS có thể hoạt động.
- Theo dõi chi phí: Sử dụng AWS Cost Explorer để theo dõi chi phí sử dụng Fargate Spot.
Những cạm bẫy thường gặp
- Quên cấu hình nhóm bảo mật: Đảm bảo rằng nhóm bảo mật cho ALB cho phép lưu lượng truy cập từ internet.
- Thiếu quyền ECR: Kiểm tra quyền truy cập IAM nếu ECS không thể kéo hình ảnh từ ECR.
Kết luận
Chúng ta đã thành công trong việc triển khai một ứng dụng Node.js trên ECS với Fargate và Fargate Spot bằng cách sử dụng Terraform. Thiết lập này đảm bảo khả năng mở rộng với các chính sách tự động mở rộng, hiệu quả chi phí và bảo mật khi chạy các nhiệm vụ trong các subnet riêng tư.
Câu hỏi thường gặp (FAQ)
H: ECS là gì?
Đ: ECS là dịch vụ của AWS cho phép bạn chạy và quản lý các container.
H: Fargate là gì?
Đ: Fargate là dịch vụ cho phép bạn chạy container mà không cần quản lý máy chủ.
H: Terraform là gì?
Đ: Terraform là công cụ để quản lý hạ tầng dưới dạng mã (Infrastructure as Code).