Hai công cụ, hai trách nhiệm
Terraform biết tạo VPC, subnet, security group, EC2 và load balancer. Ansible mạnh ở việc vào máy, cài package, render config, restart service và chạy playbook lặp lại. Đừng biến Terraform thành một shell script khổng lồ.
Provisioner: dùng được nhưng có mùi cảnh báo
resource "aws_instance" "app" {
ami = data.aws_ami.amazon_linux.id
instance_type = "t3.micro"
provisioner "remote-exec" {
inline = [
"sudo dnf install -y docker",
"sudo systemctl enable --now docker",
]
connection {
type = "ssh"
user = "ec2-user"
host = self.public_ip
private_key = file(var.ssh_private_key)
}
}
}
Provisioner chạy từ máy Terraform runner, phụ thuộc SSH/network và khó retry chính xác. Nếu command chạy xong nhưng Terraform mất kết nối, lần sau có thể không biết phần nào đã hoàn thành. Tốt hơn là bake AMI, dùng cloud-init/user data cho bootstrap ngắn, hoặc gọi Ansible từ pipeline sau khi Terraform output IP/instance ID.
Luồng Terraform -> Ansible
terraform apply -auto-approve
terraform output -raw app_ip > app_ip.txt
ansible-playbook -i "$(cat app_ip.txt)," playbook.yml
Playbook ví dụ:
- hosts: all
become: true
tasks:
- name: Cài Docker
ansible.builtin.package:
name: docker
state: present
- name: Bật Docker
ansible.builtin.service:
name: docker
state: started
enabled: true
Tốt hơn nữa, tạo inventory động từ AWS hoặc dùng SSM để không mở SSH public. Secret nên nằm trong Ansible Vault/secret manager, không trong command line dễ bị lộ ở log.
Creation-time và destroy-time
Provisioner mặc định chạy lúc resource được tạo. when = destroy chạy lúc destroy, nhưng destroy-time provisioner có giới hạn tham chiếu và dễ thất bại nếu network đã bị xóa trước. Không dùng nó để backup database quan trọng; backup phải có quy trình độc lập.
Quy tắc thực dụng
- Terraform tạo hạ tầng.
- Image/user data chuẩn bị baseline.
- Ansible cấu hình state của OS/app.
- CI orchestration gọi theo thứ tự và lưu log.
- Nếu provisioner thất bại, đọc kỹ
terraform applytrước khi chạy lại mù quáng.
Idempotency là bài kiểm tra bắt buộc
Chạy playbook hai lần không nên cài lại hoặc phá cấu hình mỗi lần. Trước khi nối vào CI, hãy kiểm tra:
ansible-playbook -i inventory playbook.yml --check --diff
ansible-playbook -i inventory playbook.yml
ansible-playbook -i inventory playbook.yml
Lần chạy thứ hai nên có ít thay đổi. Nếu app restart liên tục hoặc file config bị rewrite dù nội dung không đổi, deployment sẽ gây downtime và khó debug. Terraform cũng cần tính idempotent: plan lần hai sau khi apply nên gần như no-op.
Trong môi trường private, ưu tiên SSM/Ansible connection plugin hoặc runner đặt trong VPC. Mở SSH 0.0.0.0/0 chỉ để lab là một rủi ro cần đóng ngay sau khi thử.
Bản chuyển thể từ Ansible with Terraform.