Danh sách bài viết trong series Hành Trình Làm Chủ Terraform
- Bài 1. Học Terraform Cơ Bản: Terraform Là Gì? Cài Đặt Và Viết Mã Đầu Tiên
- Bài 2. Học Terraform Với AWS: 5 Bước Tạo Máy Chủ EC2 Đầu Tiên
- Bài 3. Tạo VPC Với Terraform: Xây Dựng Hạ Tầng Mạng Trên AWS
- Bài 4. Quản Lý Tài Nguyên Với Terraform: Sử Dụng Variables Và Outputs
- Bài 5. Tự Động Hóa Triển Khai Với Terraform: Tạo Load Balancer Và Auto Scaling Group
- Bài 6. Sử Dụng Terraform Modules: Tái Sử Dụng Mã Để Quản Lý Hạ Tầng Hiệu Quả
- Bài 7. Terraform Workspaces: Quản Lý Nhiều Môi Trường Hiệu Quả Trên AWS
- Bài 8. Terraform State: Quản Lý Trạng Thái Hạ Tầng Với S3 Và DynamoDB
- Bài 9. Terraform Provisioners: Tự Động Hóa Cấu Hình Web Server Trên EC2
- Bài 10. Terraform CI/CD: Tự Động Triển Khai Hạ Tầng Với GitHub Actions
Tại Sao Cần Sử Dụng Terraform Provisioners?
Terraform provisioners là công cụ mạnh mẽ để tự động hóa các tác vụ sau khi tài nguyên được tạo, giúp bạn cấu hình máy chủ hoặc triển khai ứng dụng mà không cần can thiệp thủ công. Trong các bài trước, chúng ta đã làm quen với Terraform cơ bản (bài 1), tạo máy chủ EC2 (bài 2), xây dựng hạ tầng mạng VPC (bài 3), sử dụng variables/outputs (bài 4), tự động hóa triển khai với Load Balancer và Auto Scaling Group (bài 5), sử dụng Terraform modules (bài 6), quản lý nhiều môi trường với Terraform workspaces (bài 7), và quản lý trạng thái với Terraform state (bài 8).
Tuy nhiên, sau khi tạo EC2, bạn thường cần thực hiện các bước cấu hình như cài đặt phần mềm, copy file, hoặc chạy script. Terraform provisioners cho phép bạn thực hiện những tác vụ này ngay trong mã Terraform, đảm bảo tính tự động và nhất quán. Trong bài này, mình sẽ hướng dẫn bạn 5 bước để sử dụng Terraform provisioners, tự động cài đặt và cấu hình web server Nginx trên EC2, sau đó kiểm tra kết quả bằng cách truy cập web server.
Terraform Provisioners: Hướng Dẫn Từng Bước
Bước 1: Chuẩn Bị Môi Trường Và Cấu Hình AWS CLI
- Hành động:
- Đảm bảo bạn đã cài đặt Terraform 1.11.2 và AWS CLI. Nếu chưa, tham khảo bài 1 và bài 2 để cài đặt.
- Kiểm tra cấu hình AWS CLI:
aws configure
Đảm bảo bạn đã nhập đúng Access Key, Secret Key, và vùng (VD:
us-east-1
). - Tạo hoặc đảm bảo bạn đã có SSH key pair trên AWS:
- Truy cập AWS Console > EC2 > Key Pairs.
- Tạo key pair mới (VD:
my-key
) và tải file.pem
(VD:my-key.pem
). - Đặt quyền cho file
.pem
:chmod 400 my-key.pem
- Kết quả thực tế:
- Nếu AWS CLI đã được cấu hình từ trước, bạn có thể kiểm tra bằng lệnh:
aws sts get-caller-identity
Output sẽ là:
{ "UserId": "AIDAXYZ1234567890", "Account": "123456789012", "Arn": "arn:aws:iam::123456789012:user/your-user-name" }
(Xác nhận AWS CLI đã được cấu hình đúng).
- Kiểm tra file
my-key.pem
:ls -l my-key.pem
Output sẽ là:
-r-------- 1 user user 1696 Mar 23 12:00 my-key.pem
(Quyền 400 xác nhận file đã được bảo mật).
- Nếu AWS CLI đã được cấu hình từ trước, bạn có thể kiểm tra bằng lệnh:
Bước 2: Tạo Thư Mục Dự Án Và Viết Mã Terraform
-
Hành động:
- Tạo một thư mục mới cho dự án:
mkdir terraform-provisioners-example cd terraform-provisioners-example
-
Tạo file
main.tf
:touch main.tf
Mở file
main.tf
trong VS Code và dán nội dung sau:terraform { required_providers { aws = { source = "hashicorp/aws" version = "5.0.0" } } } provider "aws" { region = "us-east-1" } # Tạo Security Group cho EC2 resource "aws_security_group" "web_sg" { name_prefix = "web-sg-" 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"] } tags = { Name = "WebSG" } } # Tạo EC2 với provisioner resource "aws_instance" "web_server" { ami = "ami-0c55b159cbfafe1f0" # Amazon Linux 2 in us-east-1 instance_type = "t2.micro" key_name = "my-key" # Thay bằng tên key pair của bạn vpc_security_group_ids = [aws_security_group.web_sg.id] associate_public_ip_address = true tags = { Name = "WebServer" } # Sử dụng provisioner để cài đặt Nginx provisioner "remote-exec" { inline = [ "sudo yum update -y", "sudo yum install -y nginx", "sudo systemctl start nginx", "sudo systemctl enable nginx", "echo '<h1>Welcome to Nginx - Deployed by Terraform!</h1>' | sudo tee /usr/share/nginx/html/index.html" ] connection { type = "ssh" user = "ec2-user" private_key = file("my-key.pem") # Đường dẫn đến file .pem của bạn host = self.public_ip } } } # Output public IP của EC2 output "web_server_public_ip" { description = "Public IP of the web server" value = aws_instance.web_server.public_ip }
Giải thích:
aws_security_group
: Tạo Security Group cho phép truy cập SSH (port 22) và HTTP (port 80).aws_instance
: Tạo EC2 với key pairmy-key
và gán Security Group.provisioner "remote-exec"
: Sử dụng provisioner để SSH vào EC2 và chạy các lệnh cài đặt Nginx, khởi động dịch vụ, và tạo fileindex.html
.connection
: Cấu hình kết nối SSH với EC2 bằng userec2-user
, filemy-key.pem
, và public IP của instance.output
: Xuất public IP của EC2 để truy cập web server.
- Tạo một thư mục mới cho dự án:
- Kết quả thực tế:
- Cấu trúc thư mục sẽ là:
terraform-provisioners-example/ ├── main.tf └── my-key.pem
(Kiểm tra bằng lệnh
ls
, bạn sẽ thấy filemain.tf
vàmy-key.pem
nếu bạn đã copy file .pem vào thư mục).
- Cấu trúc thư mục sẽ là:
Bước 3: Khởi Tạo Dự Án Terraform
- Hành động:
- Trong thư mục
terraform-provisioners-example
, chạy lệnh:terraform init
- Trong thư mục
-
Kết quả thực tế:
-
Terminal sẽ hiển thị:
Initializing the backend... Initializing provider plugins... - Finding hashicorp/aws versions matching "5.0.0"... - Installing hashicorp/aws v5.0.0... - Installed hashicorp/aws v5.0.0 (signed by HashiCorp) Terraform has been successfully initialized!
(Dòng “Terraform has been successfully initialized!” xác nhận quá trình khởi tạo thành công).
-
Bước 4: Triển Khai Hạ Tầng Và Kiểm Tra Web Server
- Hành động:
- Triển khai hạ tầng:
terraform apply
Khi được hỏi “Do you want to perform these actions?”, gõ
yes
và nhấn Enter. - Truy cập web server qua public IP của EC2.
- Triển khai hạ tầng:
-
Kết quả thực tế:
-
Sau khi chạy
terraform apply
, terminal sẽ hiển thị:Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # aws_instance.web_server will be created + resource "aws_instance" "web_server" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t2.micro" + key_name = "my-key" + tags = { + "Name" = "WebServer" } } # aws_security_group.web_sg will be created + resource "aws_security_group" "web_sg" { + name_prefix = "web-sg-" + tags = { + "Name" = "WebSG" } } Plan: 2 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes aws_security_group.web_sg: Creating... aws_security_group.web_sg: Creation complete after 2s [id=sg-0123456789abcdef0] aws_instance.web_server: Creating... aws_instance.web_server: Still creating... [10s elapsed] aws_instance.web_server: Creation complete after 15s [id=i-0123456789abcdef0] aws_instance.web_server: Provisioning with 'remote-exec'... aws_instance.web_server (remote-exec): Connecting to remote host via SSH... aws_instance.web_server (remote-exec): Host: 54.123.45.67 aws_instance.web_server (remote-exec): User: ec2-user aws_instance.web_server (remote-exec): Private key: true aws_instance.web_server (remote-exec): Connected! aws_instance.web_server (remote-exec): Loaded plugins: extras_suggestions, langpacks, priorities, update-motd aws_instance.web_server (remote-exec): No packages marked for update aws_instance.web_server (remote-exec): Resolving Dependencies aws_instance.web_server (remote-exec): --> Running transaction check aws_instance.web_server (remote-exec): ---> Package nginx.x86_64 1:1.20.0-1.amzn2 will be installed aws_instance.web_server (remote-exec): --> Finished Dependency Resolution aws_instance.web_server (remote-exec): Installed: aws_instance.web_server (remote-exec): nginx.x86_64 1:1.20.0-1.amzn2 aws_instance.web_server (remote-exec): Complete! aws_instance.web_server (remote-exec): Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service. Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Outputs: web_server_public_ip = "54.123.45.67"
(Dòng “Apply complete! Resources: 2 added, 0 changed, 0 destroyed” xác nhận EC2 đã được tạo và provisioner đã chạy thành công để cài đặt Nginx).
- Truy cập public IP của EC2 (VD:
http://54.123.45.67
) trên trình duyệt, bạn sẽ thấy:<h1>Welcome to Nginx - Deployed by Terraform!</h1>
- Kiểm tra trên AWS Console (EC2 Dashboard):
- Một instance với tag
Name: WebServer
, trạng tháiRunning
.
-
Bước 5: Xóa Tài Nguyên Để Dọn Dẹp
- Hành động:
- Xóa tài nguyên:
terraform destroy
Khi được hỏi “Do you really want to destroy all resources?”, gõ
yes
và nhấn Enter.
- Xóa tài nguyên:
-
Kết quả thực tế:
-
Sau khi chạy
terraform destroy
, terminal sẽ hiển thị:Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: - destroy Terraform will perform the following actions: # aws_instance.web_server will be destroyed - resource "aws_instance" "web_server" { - ami = "ami-0c55b159cbfafe1f0" -> null - instance_type = "t2.micro" -> null - id = "i-0123456789abcdef0" -> null } # aws_security_group.web_sg will be destroyed - resource "aws_security_group" "web_sg" { - name_prefix = "web-sg-" -> null - id = "sg-0123456789abcdef0" -> null } Plan: 0 to add, 0 to change, 2 to destroy. Do you really want to destroy all resources? Terraform will destroy all your managed infrastructure, as shown above. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes aws_instance.web_server: Destroying... [id=i-0123456789abcdef0] aws_instance.web_server: Still destroying... [10s elapsed] aws_instance.web_server: Destruction complete after 15s aws_security_group.web_sg: Destroying... [id=sg-0123456789abcdef0] aws_security_group.web_sg: Destruction complete after 2s Destroy complete! Resources: 2 destroyed.
(Dòng “Destroy complete! Resources: 2 destroyed” xác nhận EC2 và Security Group đã bị xóa).
- Kiểm tra lại trên AWS Console, instance
WebServer
không còn tồn tại.
-
Kết Quả Đạt Được
- Bạn đã học cách sử dụng Terraform provisioners để tự động hóa tác vụ sau khi tạo tài nguyên, cụ thể là cài đặt và cấu hình Nginx trên EC2.
- Bạn đã triển khai một EC2, tự động cài đặt web server, và truy cập public IP để kiểm tra kết quả.
- Bạn đã xóa tài nguyên để dọn dẹp, tránh phát sinh chi phí không cần thiết.
Lưu Ý Quan Trọng
- Hạn chế của provisioners: Terraform khuyến nghị sử dụng provisioners như giải pháp cuối cùng, vì chúng có thể làm mã phức tạp và khó bảo trì. Nên ưu tiên sử dụng
user_data
hoặc công cụ quản lý cấu hình như Ansible/Chef nếu có thể. - Chi phí AWS: Instance
t2.micro
trong bài này nằm trong Free Tier, nhưng nếu bạn dùng loại instance khác, có thể phát sinh chi phí. Luôn chạyterraform destroy
sau khi thử nghiệm. - Bảo mật: Security Group trong bài cho phép SSH (port 22) và HTTP (port 80) từ
0.0.0.0/0
. Trong môi trường production, hãy giới hạn CIDR block hoặc sử dụng VPN. - Tài liệu tham khảo: Xem thêm về Terraform provisioners trong tài liệu chính thức (Terraform Provisioners).