Terraform với Azure: Hướng dẫn Toàn diện
Tài liệu này sẽ hướng dẫn bạn sử dụng Terraform để quản lý hạ tầng Azure (Infrastructure as Code - IaC) từ những khái niệm cơ bản nhất đến các thực hành tốt nhất.
1. Giới thiệu về Terraform
Terraform là gì?
Terraform là một công cụ mã nguồn mở của HashiCorp, cho phép bạn định nghĩa và cung cấp hạ tầng trung tâm dữ liệu bằng ngôn ngữ cấu hình khai báo (Declarative Configuration Language) gọi là HCL (HashiCorp Configuration Language).
Thay vì click chuột trên Azure Portal để tạo từng VM, VNet, Database (dễ sai sót và khó tái tạo), bạn viết code mô tả hạ tầng đó. Terraform sẽ đọc code và tự động gọi API của Azure để tạo ra đúng như bạn mô tả.
Tại sao nên dùng Terraform với Azure?
- Tự động hóa: Tạo hàng trăm server chỉ với một lệnh.
- Phiên bản hóa (Version Control): Lưu code hạ tầng trên Git. Bạn có thể xem lịch sử thay đổi, ai đã sửa gì, và rollback khi cần.
- Nhất quán: Môi trường Dev, Staging, Prod sẽ giống hệt nhau, loại bỏ lỗi "It works on my machine".
- Đa nền tảng: Học một ngôn ngữ (HCL) nhưng dùng được cho Azure, AWS, GCP, Kubernetes, v.v.
2. Các khái niệm cốt lõi (Core Concepts)
Trước khi bắt đầu, bạn cần hiểu các thuật ngữ sau:
Provider
Là plugin giúp Terraform nói chuyện với API của Cloud Provider. Với Azure, chúng ta dùng provider tên là azurerm.
# Khai báo provider
provider "azurerm" {
features {}
}
Resource
Là các thành phần hạ tầng cụ thể bạn muốn tạo (VD: Virtual Network, Virtual Machine, Storage Account).
Cú pháp: resource "loại_resource" "tên_định_danh_trong_code" { ... }
# Ví dụ tạo một Resource Group
resource "azurerm_resource_group" "example" {
name = "my-resources"
location = "East US"
}
State File (terraform.tfstate)
Đây là "bộ nhớ" của Terraform. Nó là một file JSON lưu trữ ánh xạ giữa code của bạn và tài nguyên thực tế trên Azure.
- Khi bạn chạy lệnh, Terraform sẽ so sánh code hiện tại với file State để biết cần thêm/sửa/xóa gì.
- Quan trọng: File này chứa thông tin nhạy cảm (password, key). Không bao giờ commit file này lên Git công khai.
Workflow (Quy trình làm việc)
- Write: Viết code HCL.
- Init (
terraform init): Tải provider và khởi tạo dự án. - Plan (
terraform plan): Terraform tính toán xem nó sẽ làm gì (tạo mới, sửa đổi, hay xóa). Đây là bước kiểm tra an toàn. - Apply (
terraform apply): Thực thi thay đổi lên Azure.
3. Cài đặt và Cấu hình (Setup)
Bước 1: Cài đặt
- Cài đặt Terraform CLI.
- Cài đặt Azure CLI.
Bước 2: Đăng nhập Azure
Mở terminal và chạy:
az login
Trình duyệt sẽ bật lên để bạn đăng nhập tài khoản Azure.
Bước 3: Cấu hình Remote Backend (Quan trọng)
Mặc định, Terraform lưu file state (terraform.tfstate) trên máy tính của bạn (Local Backend). Điều này rủi ro nếu máy hỏng hoặc khi làm việc nhóm (người khác không có file state của bạn).
Giải pháp chuẩn là lưu state trên Azure Storage Account (Remote Backend).
Sơ đồ hoạt động:
Cấu hình trong block terraform:
terraform {
backend "azurerm" {
resource_group_name = "tfstate-rg"
storage_account_name = "tfstate12345"
container_name = "tfstate"
key = "prod.terraform.tfstate"
}
}
4. Cấu trúc dự án chuẩn (Project Structure)
Đừng viết tất cả trong 1 file main.tf. Hãy chia nhỏ để dễ quản lý:
my-project/
├── main.tf # Chứa các resource chính (VNet, VM)
├── variables.tf # Khai báo các biến đầu vào (Input variables)
├── outputs.tf # Khai báo các giá trị đầu ra (Output values - VD: IP của VM)
├── providers.tf # Cấu hình provider và version
├── terraform.tfvars # Gán giá trị cho biến (Không commit file này nếu chứa secret)
└── modules/ # Các module tái sử dụng (nâng cao)
5. Ví dụ thực tế: Tạo VNet và VM
Dưới đây là ví dụ tạo một mạng ảo và một máy ảo Ubuntu.
providers.tf
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
}
}
provider "azurerm" {
features {}
}
main.tf
# 1. Tạo Resource Group
resource "azurerm_resource_group" "rg" {
name = "example-resources"
location = "East US"
}
# 2. Tạo Virtual Network
resource "azurerm_virtual_network" "vnet" {
name = "example-network"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
}
# 3. Tạo Subnet
resource "azurerm_subnet" "subnet" {
name = "internal"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.1.0/24"]
}
# 4. Tạo Network Interface (Card mạng)
resource "azurerm_network_interface" "nic" {
name = "example-nic"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.subnet.id
private_ip_address_allocation = "Dynamic"
}
}
# 5. Tạo Virtual Machine
resource "azurerm_linux_virtual_machine" "vm" {
name = "example-vm"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
size = "Standard_F2"
admin_username = "adminuser"
network_interface_ids = [
azurerm_network_interface.nic.id,
]
admin_ssh_key {
username = "adminuser"
public_key = file("~/.ssh/id_rsa.pub") # Đọc key từ máy local
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "0001-com-ubuntu-server-jammy"
sku = "22_04-lts"
version = "latest"
}
}
6. Best Practices (Thực hành tốt nhất)
- Sử dụng
azapiProvider: Khi Azure ra mắt tính năng mới màazurermchưa kịp cập nhật, hãy dùngazapiprovider để "chữa cháy" thay vì chờ đợi. - Bảo mật State File: Luôn bật mã hóa (Encryption) trên Storage Account chứa state file. Hạn chế quyền truy cập (RBAC) tối đa.
- Không hardcode Secret: Đừng bao giờ viết password trực tiếp trong file
.tf. Hãy dùngvariablesvà truyền vào qua biến môi trườngTF_VAR_passwordhoặc dùng Azure Key Vault. - Review
terraform plan: Luôn đọc kỹ output của lệnhplantrước khiapply. Chú ý các dòng có dấu+(thêm mới),-(xóa bỏ),~(sửa đổi). Đặc biệt cẩn thận với các hành động Destroy (xóa bỏ).