← Tổng quan series

Kết hợp Ansible với Terraform

Phân biệt provisioning và configuration management, dùng provisioner đúng chỗ và chuyển sang Ansible khi máy đã tồn tại.

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 apply trướ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.