← Tổng quan series

IaC và Terraform: bắt đầu từ vấn đề thật

Hiểu Infrastructure as Code, Terraform state và quy trình tạo một EC2 đầu tiên mà không phải click thủ công trong AWS Console.

Mục tiêu của bài

Nếu hôm nay một người trong team nghỉ việc, người mới có thể dựng lại môi trường staging trong bao lâu? Nếu câu trả lời là “phải nhớ từng lần click trong AWS Console”, ta đang có một hạ tầng khó kiểm soát. Infrastructure as Code (IaC) giải quyết việc đó bằng cách biến hạ tầng thành code có thể review, version-control và chạy lại.

Terraform là công cụ IaC theo kiểu declarative: ta mô tả trạng thái mong muốn, Terraform tự tính các bước cần làm để đi từ trạng thái hiện tại đến trạng thái đó. Terraform dùng provider để giao tiếp với AWS, Azure, GCP và nhiều dịch vụ khác.

Luồng hoạt động cần nhớ

HCL -> terraform plan -> review -> terraform apply -> state

File terraform.tfstate là bản ghi Terraform dùng để biết resource trong code tương ứng với resource nào ngoài cloud. State không phải “log”, cũng không nên commit bừa vào Git vì nó có thể chứa thông tin nhạy cảm.

Terraform khác Ansible ở trọng tâm: Terraform tạo và quản lý hạ tầng, còn Ansible phù hợp hơn cho việc cấu hình máy chủ sau khi máy đã tồn tại. Một pipeline thực tế có thể là Terraform tạo network/EC2, Ansible cài Docker, sau đó Docker hoặc Kubernetes chạy ứng dụng.

Ví dụ đầu tiên: tạo EC2

Giả sử đã cài AWS CLI và cấu hình profile. Với tài khoản cá nhân, hãy dùng sandbox hoặc giới hạn quyền; EC2, EBS và Elastic IP có thể phát sinh phí.

aws configure
terraform version
mkdir terraform-hello && cd terraform-hello

Tạo main.tf:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

provider "aws" {
  region = "ap-southeast-1"
}

data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}

resource "aws_instance" "hello" {
  ami           = data.aws_ami.amazon_linux.id
  instance_type = "t3.micro"

  tags = { Name = "terraform-hello" }
}

data chỉ đọc dữ liệu đã có (ở đây là AMI mới nhất); resource là thứ Terraform sẽ tạo. Cú pháp aws_instance.hello là địa chỉ để Terraform theo dõi resource đó.

terraform fmt
terraform init
terraform validate
terraform plan
terraform apply
# Khi thử xong, xóa tài nguyên:
terraform destroy

Ở bước apply, hãy gõ yes sau khi đọc plan. -auto-approve tiện trong CI nhưng nguy hiểm khi chạy tay.

Cách tự kiểm chứng, không chỉ nhìn thấy “Apply complete!”

Sau apply, hãy lấy ID từ state và đối chiếu với AWS:

terraform state show aws_instance.hello
terraform output
aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=terraform-hello" \
  --query 'Reservations[].Instances[].{Id:InstanceId,State:State.Name}'

Sau đó sửa tag Name, chạy plan và quan sát Terraform đề xuất ~ thay vì tạo thêm EC2. Đây là bài kiểm tra quan trọng: nếu mỗi lần chạy lại đều thấy +, cấu hình hoặc identity resource đang không ổn định.

Không dùng terraform destroy trên account có resource khác nếu bạn chưa đọc plan. Thử thói quen plan -> review -> apply ngay từ bài đầu.

Checklist sau bài

  • Biết phân biệt resource, data, provider và state.
  • Đã chạy fmt, init, validate, plan trước apply.
  • Đã kiểm tra AWS Console và chạy terraform destroy.
  • Không commit .terraform/, *.tfstate hay credentials vào Git.

Đây là bản chuyển thể thực hành bằng tiếng Việt, không phải bản dịch nguyên văn. Xem bài nguồn và mã mẫu tại DevOps VN.