Logo
Featured Image

Thực Hành Terraform AWS: Xây Dựng Hệ Thống 2-Tier HA (EC2, RDS, S3, ALB)

Author
Tobi 18/03/2026 16 views

Chào các bạn, chào mừng quay lại với blog com.quyenlt!

Hôm nay, chúng ta sẽ không thao tác "click chuột" thủ công trên giao diện AWS nữa. Thay vào đó, mình sẽ hướng dẫn các bạn dùng Terraform (Infrastructure as Code) để tự động hóa toàn bộ quá trình xây dựng một hạ tầng web thực tế.

Mô hình chúng ta hướng tới là 2-Tier Architecture (Hệ thống 2 tầng) có tính sẵn sàng cao (High Availability), bao gồm:

  • Application Load Balancer (ALB) chia tải.

  • Cụm máy ảo EC2 chạy Docker (Nginx) làm Web Server.

  • Database RDS MySQL tách biệt, được bảo vệ nghiêm ngặt.

  • S3 Bucket lưu trữ tĩnh, phân quyền bằng IAM Role thay vì Access Key.

Chuẩn Bị.

Cài Đặt Công Cụ (Prerequisites)

Để hệ thống máy tính cá nhân của bạn có thể "nói chuyện" và ra lệnh cho AWS, chúng ta cần cài đặt hai công cụ cốt lõi: AWS CLI (Giao diện dòng lệnh của AWS) và Terraform (Trình biên dịch hạ tầng).

1. Cài đặt AWS CLI (Phiên bản 2)

Dành cho macOS: Cách nhanh nhất là sử dụng Homebrew. Mở Terminal và chạy:

brew install awscli

(Nếu không dùng Homebrew, bạn có thể tải file .pkg trực tiếp từ trang chủ AWS).

Dành cho Windows: Mở Command Prompt (hoặc PowerShell) với quyền Administrator và chạy lệnh tải gói cài đặt:

msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi

Dành cho Linux (Ubuntu/Debian):

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

Kiểm tra lại xem AWS CLI đã được cài đặt thành công chưa:

aws --version
# Kết quả mong đợi: aws-cli/2.x.x Python/3.x.x ...

Bước 1.5: Tạo SSH Key Pair (Chìa Khóa Đăng Nhập Server)

Trong môi trường Cloud, chúng ta hạn chế tối đa việc đăng nhập vào server bằng mật khẩu (Password) vì rất dễ bị hacker dò quét (Brute-force attack). Thay vào đó, chúng ta sẽ dùng SSH Key Pair (Cặp khóa bảo mật).

Terraform sẽ lấy "ổ khóa" (Public Key) gắn lên máy ảo AWS, còn bạn sẽ giữ "chìa khóa" (Private Key) ở máy tính cá nhân.

Cách tạo SSH Key: Bạn mở Terminal (hoặc Command Prompt / Git Bash trên Windows) và chạy câu lệnh sau:

ssh-keygen -t rsa -b 4096 -f ~/.ssh/tobi-aws

Giải thích câu lệnh:

  • -t rsa -b 4096: Tạo khóa mã hóa chuẩn RSA với độ dài 4096 bit (cực kỳ bảo mật).

  • -f ~/.ssh/tobi-aws: Chỉ định nơi lưu file và tên file. Ở đây mình đặt tên là tobi-aws để khớp với đoạn code Terraform ở bước sau.

Khi hệ thống hỏi Enter passphrase (empty for no passphrase):, bạn có thể nhấn Enter 2 lần để bỏ qua (không đặt mật khẩu phụ cho file key này để thực hành cho nhanh).

Kết quả: Hệ thống sẽ tạo ra 2 file trong thư mục ~/.ssh/ của bạn:

  1. tobi-aws: Đây là Private Key (Tuyệt đối giữ bí mật, không gửi cho ai).

  2. tobi-aws.pub: Đây là Public Key (Đoạn mã này sẽ được Terraform đọc và mang lên AWS).

2. Cài đặt Terraform

Dành cho macOS: Tiếp tục tận dụng sức mạnh của Homebrew:

brew tap hashicorp/tap
brew install hashicorp/tap/terraform

Dành cho Windows: Nếu bạn dùng Chocolatey, chỉ cần một dòng lệnh:

choco install terraform

(Hoặc tải file .zip từ trang chủ HashiCorp, giải nén và đưa file terraform.exe vào thư mục biến môi trường PATH).

Dành cho Linux (Ubuntu/Debian): Cài đặt qua kho lưu trữ chính thức của HashiCorp:

sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg | \
gpg --dearmor | \
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \
sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update
sudo apt-get install terraform

Kiểm tra lại xem Terraform đã sẵn sàng làm việc chưa:

terraform -version
# Kết quả mong đợi: Terraform v1.x.x

Sau khi đã có đủ "vũ khí", chúng ta tiến hành cấp quyền cho hệ thống ở bước tiếp theo!

Thực Hành Triển Khai

Cấu Hình AWS CLI

Trước khi viết code Terraform, "máy tính của bạn" cần có quyền để nói chuyện với "đám mây AWS". Chúng ta sẽ tạo một tài khoản IAM (Identity and Access Management) thay vì dùng tài khoản Root.

1. Tạo IAM User trên AWS:

  • Đăng nhập vào AWS Console, tìm kiếm dịch vụ IAM.

  • Vào Users > Create user. Đặt tên user (ví dụ: terraform-admin).

  • Ở phần Permissions, chọn Attach policies directly và tích vào AdministratorAccess (Lưu ý: Trong thực tế bạn nên cấp quyền nhỏ nhất có thể, nhưng để làm Lab cho nhanh, chúng ta dùng quyền Admin).

  • Sau khi tạo xong, bấm vào tên User > chuyển sang tab Security credentials > Create access key.

  • Chọn Command Line Interface (CLI). Lưu lại Access Key IDSecret Access Key (Tuyệt đối không để lộ mã này).

2. Cấu hình AWS CLI trên máy cá nhân:

Mở Terminal (hoặc Command Prompt) và gõ lệnh:

aws configure

Hệ thống sẽ hỏi 4 thông tin, bạn điền lần lượt như sau:

  • AWS Access Key ID: Dán Access Key của bạn vào đây

  • AWS Secret Access Key: Dán Secret Key của bạn vào đây

  • Default region name: ap-southeast-1 (Vùng Singapore, gần Việt Nam nhất)

  • Default output format: json

Để kiểm tra xem đã kết nối thành công chưa, chạy lệnh:

aws sts get-caller-identity

Nếu màn hình in ra thông tin Account ID của bạn là xong bước chuẩn bị!

Tạo Cấu Trúc Thư Mục Terraform

Tạo một thư mục mới cho dự án (ví dụ: aws-terraform-lab). Trong thư mục này, chúng ta sẽ tạo 3 file chuẩn mực của DevOps: variables.tf, main.tf, và outputs.tf.

1. File variables.tf (Khai báo biến)

File này giúp code của chúng ta linh hoạt, dễ dàng thay đổi cấu hình mà không cần sửa logic.

variable "aws_region" {
  default = "ap-southeast-1"
}

variable "instance_type" {
  default = "t3.micro" # Nằm trong Free Tier
}

variable "instance_count" {
  description = "Số lượng máy ảo muốn tạo"
  type        = number
  default     = 2
}

variable "db_username" {
  description = "Username cho Database"
  type        = string
  default     = "admin"
}

variable "db_password" {
  description = "Password cho Database"
  type        = string
  sensitive   = true
  default     = "Tobi123456" # Thực tế nên dùng file .tfvars hoặc AWS Secrets Manager
}

2. File main.tf (Trái tim của hệ thống)

Đây là nơi chứa toàn bộ "bản vẽ" hạ tầng. Mình đã gộp các tài nguyên lại để bạn dễ dàng copy. Lưu ý: Đảm bảo bạn đã có file key public tại ~/.ssh/tobi-aws.pub trên máy (nếu chưa có, chạy lệnh ssh-keygen để tạo).

provider "aws" {
  region = var.aws_region
}

# 1. Tìm AMI Ubuntu 24.04 mới nhất
data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] 
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*"]
  }
}

# 2. Key Pair (Chìa khóa SSH)
resource "aws_key_pair" "tobi_key" {
  key_name   = "tobi-key-singapore"
  public_key = file("~/.ssh/tobi-aws.pub") 
}

# 3. Security Group cho EC2 (Mở port 22 và 80)
resource "aws_security_group" "web_sg" {
  name        = "tobi-allow-ssh-http"
  description = "Allow SSH and HTTP traffic"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  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"]
  }
}

# 4. IAM Role cho phép EC2 truy cập S3 không cần Access Key
resource "aws_iam_role" "ec2_s3_access_role" {
  name = "tobi-ec2-s3-access-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = { Service = "ec2.amazonaws.com" }
    }]
  })
}

resource "aws_iam_role_policy_attachment" "s3_full_access" {
  role       = aws_iam_role.ec2_s3_access_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}

resource "aws_iam_instance_profile" "ec2_s3_profile" {
  name = "tobi-ec2-s3-profile"
  role = aws_iam_role.ec2_s3_access_role.name
}

# 5. Tạo EC2 Instances (Nhân bản bằng vòng lặp count)
resource "aws_instance" "my_server" {
  count         = var.instance_count 
  ami           = data.aws_ami.ubuntu.id
  instance_type = var.instance_type
  key_name      = aws_key_pair.tobi_key.key_name
  
  iam_instance_profile   = aws_iam_instance_profile.ec2_s3_profile.name
  vpc_security_group_ids = [aws_security_group.web_sg.id]

  # Cài đặt Docker và chạy Nginx tự động lúc khởi động
  user_data = <<-EOF
              #!/bin/bash
              sudo apt-get update
              sudo apt-get install -y docker.io
              sudo systemctl start docker
              sudo systemctl enable docker
              sudo usermod -aG docker ubuntu
              
              echo "<h1>Welcome to com.quyenlt - Server Node ${count.index}</h1>" > /home/ubuntu/index.html
              sudo docker run -d -p 80:80 --name my-web -v /home/ubuntu/index.html:/usr/share/nginx/html/index.html:ro nginx
              EOF

  tags = { Name = "Tobi-DevOps-Server-${count.index}" }
}

# 6. Security Group & Instance cho RDS MySQL
resource "aws_security_group" "db_sg" {
  name        = "tobi-db-sg"
  description = "Cho phep EC2 ket noi vao MySQL"
  ingress {
    from_port       = 3306
    to_port         = 3306
    protocol        = "tcp"
    security_groups = [aws_security_group.web_sg.id] # Chỉ cho EC2 truy cập
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_db_instance" "mysql_db" {
  allocated_storage    = 20
  engine               = "mysql"
  engine_version       = "8.0"
  instance_class       = "db.t3.micro"
  db_name              = "orishop_db"
  username             = var.db_username
  password             = var.db_password
  parameter_group_name = "default.mysql8.0"
  skip_final_snapshot  = true
  publicly_accessible  = false 
  vpc_security_group_ids = [aws_security_group.db_sg.id]
}

# 7. S3 Bucket
resource "random_id" "bucket_suffix" { byte_length = 4 }

resource "aws_s3_bucket" "orishop_assets" {
  bucket        = "tobi-orishop-assets-${random_id.bucket_suffix.hex}"
  force_destroy = true 
}

resource "aws_s3_bucket_public_access_block" "orishop_assets_block" {
  bucket                  = aws_s3_bucket.orishop_assets.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# 8. Application Load Balancer (ALB)
data "aws_subnets" "default" {
  filter {
    name   = "vpc-id"
    values = [aws_security_group.web_sg.vpc_id]
  }
}

resource "aws_lb" "orishop_alb" {
  name               = "orishop-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.web_sg.id]
  subnets            = data.aws_subnets.default.ids
}

resource "aws_lb_target_group" "orishop_tg" {
  name     = "orishop-target-group"
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_security_group.web_sg.vpc_id
  health_check { path = "/" }
}

resource "aws_lb_listener" "front_end" {
  load_balancer_arn = aws_lb.orishop_alb.arn
  port              = "80"
  protocol          = "HTTP"
  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.orishop_tg.arn
  }
}

resource "aws_lb_target_group_attachment" "tg_attachment" {
  count            = var.instance_count
  target_group_arn = aws_lb_target_group.orishop_tg.arn
  target_id        = aws_instance.my_server[count.index].id
  port             = 80
}

3. File outputs.tf (Xuất kết quả)

File này sẽ in ra màn hình các thông số quan trọng sau khi Terraform chạy xong.

output "alb_dns_name" {
  description = "Truy cập trang web qua DNS này"
  value       = aws_lb.orishop_alb.dns_name
}

output "server_public_ips" {
  description = "IP của các máy ảo EC2"
  value       = aws_instance.my_server[*].public_ip
}

output "db_endpoint" {
  description = "Địa chỉ kết nối MySQL"
  value       = aws_db_instance.mysql_db.endpoint
}

output "s3_bucket_name" {
  description = "Tên Bucket chứa file tĩnh"
  value       = aws_s3_bucket.orishop_assets.id
}

4. File terraform.tfvars (Bảo Mật Thông Tin Nhạy Cảm)

Trong thực tế, chúng ta không bao giờ ghi trực tiếp mật khẩu Database hay các thông tin bảo mật vào file variables.tf hoặc main.tf để tránh việc vô tình đẩy cả mật khẩu lên GitHub.

Terraform cung cấp một cơ chế cực hay: File terraform.tfvars. Terraform sẽ tự động đọc file này và gán giá trị vào các biến tương ứng.

Bạn hãy tạo file terraform.tfvars và điền thông tin thực tế vào:

# Thông tin đăng nhập Database (Đừng chia sẻ file này cho ai)
db_username = "admin"
db_password = "Tobi_Super_Secret_Password_123!" 

# Bạn cũng có thể ghi đè các biến khác ở đây nếu muốn
instance_count = 2
aws_region     = "ap-southeast-1"

⚠️ Lưu Ý Sống Còn Về Bảo Mật (Dành cho người dùng Git): Nếu bạn định lưu trữ toàn bộ thư mục code này lên GitHub/GitLab, bạn BẮT BUỢC phải tạo một file tên là .gitignore (có dấu chấm ở đầu) và thêm file biến này vào để Git bỏ qua nó:

Nội dung file .gitignore:

# Bỏ qua file chứa mật khẩu
terraform.tfvars

# Bỏ qua các thư mục và file cấu hình nội bộ của Terraform
.terraform/
.terraform.lock.hcl
terraform.tfstate
terraform.tfstate.backup

Nhờ bước này, mã nguồn hạ tầng của bạn có thể public thoải mái trên mạng, nhưng mật khẩu Database thì chỉ một mình bạn biết!

Triển Khai Hạ Tầng (Deploy)

Mở Terminal tại thư mục chứa 3 file trên, chạy lần lượt các lệnh:

  1. Tải các plugin cần thiết:

    terraform init
    
  2. Xem trước kế hoạch xây dựng (Không bắt buộc nhưng nên làm):

    terraform plan
    
  3. Bắt đầu tạo tài nguyên:

    terraform apply -auto-approve
    

    Lưu ý: Quá trình này sẽ mất khoảng 5 - 10 phút, chủ yếu là thời gian chờ khởi tạo RDS Database.

Sau khi chạy xong, Terminal sẽ in ra thông tin trong phần Outputs. Hãy copy địa chỉ alb_dns_name dán lên trình duyệt.

F5 liên tục, bạn sẽ thấy thông báo luân phiên nhảy giữa Server Node 0Server Node 1. Bộ cân bằng tải (ALB) của bạn đã hoạt động hoàn hảo!

F5 lần nữa sẽ ra node 1.

Tới đây nếu bạn muốn dùng thực tế với tên miền thì chỉ cần cấu hình 1 bản ghi CNAME trên cloudflare trỏ domain thật về link này là xong !

Dọn Dẹp Chiến Trường (Nếu chỉ đang lab bạn nên xóa để tránh AWS tính phí nhé )

Đây là bước sống còn để bảo vệ thẻ tín dụng của bạn. Các dịch vụ như Load Balancer sẽ tính phí theo giờ nếu bạn không tắt nó đi.

Khi đã làm Lab xong, chỉ cần gõ một lệnh duy nhất để phá hủy toàn bộ hệ thống vừa tạo:

terraform destroy -auto-approve

Đợi khoảng 5 phút để Terraform xóa sạch EC2, Database, ALB và S3. Khi dòng chữ Destroy complete! hiện ra, bạn đã an toàn tuyệt đối.


Nhìn Lại Các Công Nghệ Sử Dụng

1.Khai Báo Biến Số (Variables & Secrets)

Tạo một thư mục dự án mới. Đầu tiên, chúng ta tạo file variables.tf để khai báo các tham số giúp code dễ tái sử dụng:

variable "aws_region" { default = "ap-southeast-1" }
variable "instance_type" { default = "t3.micro" }
variable "instance_count" { default = 2 } # Tự động tạo 2 máy ảo để làm HA
variable "db_username" { default = "admin" }
variable "db_password" { sensitive = true }

Bảo mật thông tin nhạy cảm: Tuyệt đối không ghi mật khẩu thẳng vào file variables.tf. Hãy tạo file terraform.tfvars để truyền giá trị thực tế:

# File: terraform.tfvars
db_password    = "MatKhauSieuKho123!"
instance_count = 2

Lưu ý quan trọng: Nhớ tạo file .gitignore và thêm dòng terraform.tfvars vào để không lỡ tay đẩy mật khẩu này lên GitHub!


2. Định Nghĩa Hạ Tầng (Code main.tf)

Đây là "trái tim" của hệ thống. Tạo file main.tf và chúng ta sẽ đi từng khối cấu hình.

2.1. Provider & Tìm kiếm hệ điều hành

Cấu hình kết nối vùng (Region) và yêu cầu Terraform tự động dò tìm mã ID của hệ điều hành Ubuntu 24.04 mới nhất.

provider "aws" { region = var.aws_region }

data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] 
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*"]
  }
}

resource "aws_key_pair" "tobi_key" {
  key_name   = "tobi-key-singapore"
  public_key = file("~/.ssh/tobi-aws.pub") 
}

2.2. Cấu hình Firewall (Security Groups)

Chúng ta cần 2 lớp Firewall ảo:

  1. Web SG: Cho phép Internet truy cập Web (Port 80) và Admin truy cập SSH (Port 22).

  2. DB SG: Chỉ cho phép kết nối MySQL (Port 3306) nếu nguồn truy cập đến từ chính Web SG. Đây là cốt lõi của bảo mật mạng 2-Tier.

resource "aws_security_group" "web_sg" {
  name        = "tobi-allow-ssh-http"
  ingress { from_port = 22, to_port = 22, protocol = "tcp", cidr_blocks = ["0.0.0.0/0"] }
  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"] }
}

resource "aws_security_group" "db_sg" {
  name        = "tobi-db-sg"
  ingress {
    from_port       = 3306
    to_port         = 3306
    protocol        = "tcp"
    security_groups = [aws_security_group.web_sg.id] # Ép buộc chỉ nhận traffic từ EC2
  }
}

2.3. Cụm Web Server (EC2) & Docker

Sử dụng tham số count để tạo ra bao nhiêu máy ảo tùy thích. Ở khối user_data, chúng ta nhúng một đoạn script Bash để EC2 tự động cài Docker và chạy Nginx ngay khi vừa khởi động.

resource "aws_instance" "my_server" {
  count                  = var.instance_count 
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = var.instance_type
  key_name               = aws_key_pair.tobi_key.key_name
  iam_instance_profile   = aws_iam_instance_profile.ec2_s3_profile.name
  vpc_security_group_ids = [aws_security_group.web_sg.id]

  user_data = <<-EOF
              #!/bin/bash
              sudo apt-get update && sudo apt-get install -y docker.io
              sudo systemctl start docker && sudo systemctl enable docker
              sudo usermod -aG docker ubuntu
              echo "<h1>Welcome to com.quyenlt - Server Node ${count.index}</h1>" > /home/ubuntu/index.html
              sudo docker run -d -p 80:80 --name my-web -v /home/ubuntu/index.html:/usr/share/nginx/html/index.html:ro nginx
              EOF
  tags = { Name = "Tobi-DevOps-Server-${count.index}" }
}

2.4. Database Nội Bộ (RDS MySQL)

Cấu hình publicly_accessible = false đảm bảo không ai trên Internet có thể ping đến Database của bạn. Thuộc tính skip_final_snapshot = true giúp xóa DB nhanh hơn khi làm Lab (trong thực tế production phải để là false).

resource "aws_db_instance" "mysql_db" {
  allocated_storage    = 20
  engine               = "mysql"
  engine_version       = "8.0"
  instance_class       = "db.t3.micro"
  db_name              = "orishop_db"
  username             = var.db_username
  password             = var.db_password
  skip_final_snapshot  = true
  publicly_accessible  = false 
  vpc_security_group_ids = [aws_security_group.db_sg.id]
}

2.5. Application Load Balancer (ALB)

ALB sẽ đóng vai trò "lễ tân", đứng ở mặt tiền nhận request từ khách hàng (Listener port 80), sau đó chia đều tải (Target Group) ném về phía sau cho các máy ảo EC2 xử lý.

data "aws_subnets" "default" {
  filter { name = "vpc-id", values = [aws_security_group.web_sg.vpc_id] }
}

resource "aws_lb" "orishop_alb" {
  name               = "orishop-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.web_sg.id]
  subnets            = data.aws_subnets.default.ids
}

resource "aws_lb_target_group" "orishop_tg" {
  name     = "orishop-target-group"
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_security_group.web_sg.vpc_id
}

resource "aws_lb_listener" "front_end" {
  load_balancer_arn = aws_lb.orishop_alb.arn
  port              = "80"
  protocol          = "HTTP"
  default_action { type = "forward", target_group_arn = aws_lb_target_group.orishop_tg.arn }
}

resource "aws_lb_target_group_attachment" "tg_attachment" {
  count            = var.instance_count
  target_group_arn = aws_lb_target_group.orishop_tg.arn
  target_id        = aws_instance.my_server[count.index].id
  port             = 80
}

2.6. Cấp quyền S3 bằng IAM Role

Thay vì copy Access Key bỏ vào EC2, chúng ta gán một Thẻ định danh (IAM Role) cho EC2. Nhờ đó, ứng dụng web có thể tự do upload ảnh lên S3 một cách cực kỳ bảo mật. Mình thiết lập force_destroy = true để khi làm xong lab, Terraform có thể xóa sạch Bucket dù bên trong có chứa file.

resource "random_id" "bucket_suffix" { byte_length = 4 }

resource "aws_s3_bucket" "orishop_assets" {
  bucket        = "tobi-orishop-assets-${random_id.bucket_suffix.hex}"
  force_destroy = true 
}

resource "aws_iam_role" "ec2_s3_access_role" {
  name = "tobi-ec2-s3-access-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17", Statement = [{ Action = "sts:AssumeRole", Effect = "Allow", Principal = { Service = "ec2.amazonaws.com" } }]
  })
}

resource "aws_iam_role_policy_attachment" "s3_full_access" {
  role       = aws_iam_role.ec2_s3_access_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}

resource "aws_iam_instance_profile" "ec2_s3_profile" {
  name = "tobi-ec2-s3-profile"
  role = aws_iam_role.ec2_s3_access_role.name
}

3.Lấy Kết Quả Output

Tạo file outputs.tf. Khối này giúp chúng ta lấy được địa chỉ mặt tiền của Web và Endpoint của Database ngay sau khi Terraform chạy xong, không cần phải mò mẫm trên giao diện AWS.

output "alb_dns_name" { value = aws_lb.orishop_alb.dns_name }
output "server_public_ips" { value = aws_instance.my_server[*].public_ip }
output "db_endpoint" { value = aws_db_instance.mysql_db.endpoint }

 

Kết Luận

Qua bài Lab này trên quyenlt.com, chúng ta đã thấy được sức mạnh khủng khiếp của Infrastructure as Code. Chỉ với một vài lệnh, chúng ta có thể dựng lên và phá hủy cả một trung tâm dữ liệu thu nhỏ. Hẹn gặp lại các bạn ở các bài viết đào sâu hơn về CI/CD và Docker nhé!

Bình luận (0)

+ =
Zalo