Monday, January 20, 2025

[Terraform] Lesson 7 – Terraform Expressions

-

Terraform Expressions là cách để sử dụng các giá trị, biểu thức, hàm và toán tử trong các file cấu hình Terraform. Chúng ta có thể sử dụng các biểu thức để xác định các giá trị của các thuộc tính của các tài nguyên, tham chiếu đến các biến, đối tượng, hoặc giá trị đầu vào khác, và thực hiện các phép tính toán và điều kiện.

Cú pháp khai báo của Terraform Expression được đặt trong cặp ký tự ${} hoặc << >> (nếu được cấu hình như vậy) và có thể được sử dụng bất cứ đâu trong các file cấu hình Terraform.

Ví dụ về sử dụng biểu thức trong cấu hình Terraform:

resource "aws_instance" "example" {
  ami           = var.ami_id
  instance_type = "t2.micro"
  subnet_id     = aws_subnet.example.id

  tags = {
    Name = "example-instance"
    Environment = "${var.environment}"
  }

  ebs_block_device {
    device_name = "/dev/sdh"
    volume_type = "gp2"
    volume_size = "${var.volume_size * count.index}"
  }

  count = var.instance_count
}

Trong ví dụ trên, chúng ta định nghĩa một biến count với giá trị mặc định là 1. Sau đó, chúng ta sử dụng biến này trong khai báo của resource "aws_instance" "example" để chỉ định số lượng instance cần tạo.

Cụ thể, với cấu hình này, nếu không có giá trị nào được ghi đè lên biến count, Terraform sẽ tạo một instance duy nhất. Tuy nhiên, nếu giá trị được ghi đè lên biến count là 3 chẳng hạn, Terraform sẽ tạo ra 3 instance với tên là example-instance-0, example-instance-1example-instance-2. Bằng cách sử dụng biến count.index trong khai báo của thẻ tags, Terraform sẽ tự động thay thế index tương ứng của từng instance vào phần tên của instance.

Lưu ý rằng việc sử dụng biến count chỉ phù hợp khi chúng ta cần tạo nhiều instance có cùng cấu hình. Nếu mỗi instance có một cấu hình khác nhau, chúng ta nên sử dụng for_each thay vì count.

– Một số lưu ý khi sử dụng Terraform Expressions.

Dưới đây là các lưu ý khi sử dụng Terraform Expressions:

  • Độ ưu tiên toán học: Terraform tuân theo quy tắc độ ưu tiên toán học chuẩn (PEMDAS – Parentheses, Exponents, Multiplication and Division, Addition and Subtraction) để tính toán biểu thức.
  • Thứ tự đánh giá: Terraform sẽ đánh giá các biểu thức từ trái qua phải, vì vậy nếu bạn có một biểu thức phụ thuộc vào một tài nguyên khác, hãy đảm bảo rằng tài nguyên đó đã được khai báo trước.
  • Không thể sử dụng biến trong khai báo tên tài nguyên: Tên tài nguyên là một hằng số và chỉ có thể chứa các ký tự chữ cái, số và dấu gạch dưới. Không thể sử dụng biến hoặc biểu thức trong khai báo tên tài nguyên.
  • Tên biến phải là duy nhất: Terraform yêu cầu tên biến phải là duy nhất trong phạm vi module, không thể có hai biến cùng tên trong cùng một module.
  • Không sử dụng ký tự đặc biệt trong tên biến: Terraform không cho phép sử dụng các ký tự đặc biệt như dấu gạch chéo ngược hoặc dấu ngoặc kép trong tên biến.
  • Không sử dụng biểu thức bên trong các tên tài nguyên: Terraform không cho phép sử dụng biểu thức bên trong các tên tài nguyên, vì các tài nguyên phải có tên cố định để Terraform có thể quản lý.
  • Các expression hỗ trợ hầu hết các toán tử và hàm toán học: Terraform hỗ trợ hầu hết các toán tử và hàm toán học chuẩn như +, -, *, /, %, floor(), ceil(), min(), max(), abs(), sqrt(), log() và nhiều hơn nữa. Bạn cũng có thể sử dụng các hàm chuỗi như join(), format(), substr(), lower(), upper(), regex(), replace() và nhiều hơn nữa.
  • Tương thích với các hàm do người dùng định nghĩa: Terraform cho phép người dùng định nghĩa các hàm tùy chỉnh bằng cách sử dụng cú pháp function().
  • Sử dụng interpolation (${...}) để đặt giá trị của biến vào trong chuỗi. Chẳng hạn, nếu bạn muốn tạo tên tài nguyên từ biến environmentapp_name, bạn có thể sử dụng: resource_name = "${var.environment}-${var.app_name}".
  • Terraform cũng hỗ trợ một số hàm tích hợp, như format để định dạng chuỗi, coalesce để chọn giá trị đầu tiên không rỗng hoặc null trong danh sách các giá trị đầu vào, và try để thử một biểu thức và trả về giá trị mặc định nếu biểu thức đó bị lỗi.
  • Terraform cũng hỗ trợ các biểu thức điều kiện (if) và vòng lặp (for), cho phép bạn xử lý các giá trị và tài nguyên theo cách động.
  • Nếu bạn muốn sử dụng các biểu thức phức tạp hơn, bạn có thể sử dụng các module để phân chia các mảnh mã lớn hơn thành các đơn vị nhỏ hơn và dễ quản lý hơn.
  • Hãy luôn đảm bảo rằng các biểu thức của bạn đang hoạt động như mong đợi bằng cách sử dụng các lệnh terraform validateterraform plan để kiểm tra các file cấu hình trước khi triển khai chúng.
  • Terraform expressions phải luôn trả về một giá trị duy nhất và không được trả về một danh sách các giá trị.
  • Trong các biểu thức hàm, các tham số phải được truyền theo đúng thứ tự và có đủ số lượng.
  • Các hàm toán học sẽ tự động ép kiểu đầu vào thành cùng một kiểu. Tuy nhiên, nếu các kiểu không thể chuyển đổi được, Terraform sẽ trả về lỗi.
  • Khi sử dụng biểu thức trong các khai báo resource hoặc module, chúng ta cần chú ý rằng các giá trị được tính toán chỉ khi Terraform được chạy, do đó nếu các giá trị được sử dụng trong biểu thức thay đổi, chúng ta cần chạy lại Terraform để cập nhật các giá trị đó.
  • Nếu biểu thức quá phức tạp, nên xem xét chia nhỏ nó thành các biểu thức nhỏ hơn để dễ đọc và bảo trì hơn.
  • Khi sử dụng biểu thức trong các cấu trúc lặp lại (ví dụ: count, for_each), chúng ta cần chú ý rằng các biểu thức sẽ được tính toán một lần cho mỗi thực thể, do đó cần đảm bảo rằng các biểu thức đó không phụ thuộc vào các biểu thức khác mà chỉ được tính toán một lần.
  • Khi sử dụng các biểu thức phức tạp, nên chú ý đến thứ tự ưu tiên của các toán tử để đảm bảo kết quả tính toán đúng như mong đợi.
  • Nên sử dụng các hàm cung cấp sẵn trong Terraform để giảm thiểu lỗi và tăng tính hiệu quả của mã. Ví dụ, hàm cidrsubnet() trong Terraform hỗ trợ tính toán địa chỉ mạng dựa trên địa chỉ IP và subnet mask.
  • Không nên sử dụng các biểu thức quá phức tạp hoặc độc quyền vì nó sẽ làm cho mã khó hiểu và khó bảo trì. Nên sử dụng các biểu thức đơn giản và dễ đọc để tăng tính rõ ràng của mã.
  • Terraform hỗ trợ một số kiểu dữ liệu khác nhau cho biến và output. Nên chú ý kiểm tra kiểu dữ liệu của biến và output để đảm bảo tính đúng đắn của mã.
  • Một lưu ý quan trọng khi sử dụng Terraform Expressions là tối ưu hóa việc sử dụng chúng để tránh ảnh hưởng đến hiệu suất của Terraform. Khi bạn sử dụng nhiều expressions trong một file Terraform lớn, Terraform có thể mất nhiều thời gian để tính toán tất cả các giá trị đó. Do đó, nên sử dụng expressions một cách hợp lý và chỉ khi cần thiết, và cố gắng giảm thiểu số lượng expressions được sử dụng để giảm thiểu thời gian tính toán. Ngoài ra, nên sử dụng các hàm bên ngoài hoặc các thư viện Terraform được cung cấp bởi nhà phát triển để tối ưu hóa hiệu suất và giảm thiểu lỗi trong quá trình tính toán expressions.
  • Một lưu ý quan trọng khi sử dụng Terraform Expressions là các biểu thức phải đảm bảo độ thực thi của chúng trong tương lai. Điều này đặc biệt quan trọng khi sử dụng các biến môi trường, bởi vì chúng có thể thay đổi giá trị tùy thuộc vào môi trường.Ví dụ, nếu một biểu thức trong file cấu hình của bạn sử dụng một biến môi trường, nhưng sau đó bạn thay đổi giá trị của biến này trong quá trình triển khai, thì giá trị của biểu thức cũng sẽ thay đổi theo. Điều này có thể gây ra sự cố trong quá trình triển khai và dẫn đến các hành động không mong muốn. Do đó, bạn cần cẩn thận khi sử dụng các biểu thức trong Terraform và đảm bảo rằng chúng luôn được tính toán đúng và có giá trị chính xác tại thời điểm triển khai.
  • Một lưu ý nữa khi sử dụng Terraform Expressions là nên đặt tên biến sao cho có ý nghĩa và dễ hiểu. Đặt tên biến rõ ràng và mô tả đầy đủ tính chất và mục đích của biến sẽ giúp cho việc đọc mã nguồn của bạn trở nên dễ dàng hơn và giúp cho người khác hiểu rõ hơn về mã nguồn của bạn. Bên cạnh đó, nên tránh đặt tên biến quá ngắn hoặc quá dài, không nên sử dụng những ký tự đặc biệt hoặc chữ hoa trong tên biến.
  • Một lưu ý cuối cùng là Terraform expressions được sử dụng để tạo ra các giá trị trong tài nguyên, và các giá trị này có thể được sử dụng để đặt tên tài nguyên, các thuộc tính, hoặc bất kỳ nơi nào mà giá trị được yêu cầu trong Terraform. Việc sử dụng các biểu thức phức tạp có thể làm cho mã Terraform của bạn trở nên khó hiểu và khó bảo trì, vì vậy nên sử dụng các biểu thức một cách hợp lý và cẩn thận để giữ cho mã của bạn dễ đọc và dễ hiểu.

– Một vài ví dụ minh hoạ.

Dưới đây là một ví dụ về Terraform Expressions trong KVM:

resource "libvirt_domain" "example" {
  name   = "example"
  memory = "1024"

  network_interface {
    network_name = "default"
    mac          = "52:54:00:5a:aa:09"
    address      = "${cidrhost("192.168.122.0/24", count.index)}"
  }

  count = 2
}

Trong ví dụ này, chúng ta sử dụng expression ${cidrhost("192.168.122.0/24", count.index)} để tính toán địa chỉ IP cho các giao diện mạng. Cụ thể, chúng ta sử dụng hàm cidrhost để lấy địa chỉ IP của host trong một mạng CIDR đã cho, sử dụng mạng 192.168.122.0/24 và chỉ số count.index để tính toán các địa chỉ IP khác nhau cho các giao diện mạng trong count instances của domain.

Lưu ý rằng trong trường hợp này, chúng ta sử dụng expression bên trong chuỗi string bằng cách sử dụng các dấu ngoặc kép để bao quanh nó.

Dưới đây là một ví dụ về Terraform Expressions trong vsphere:

data "vsphere_datacenter" "dc" {
  name = var.datacenter_name
}

data "vsphere_network" "network" {
  name          = var.network_name
  datacenter_id = data.vsphere_datacenter.dc.id
}

resource "vsphere_virtual_machine" "example" {
  ...

  network_interface {
    network_id = data.vsphere_network.network.id
    adapter_type = var.adapter_type
  }

  ...
}

Trong ví dụ trên, Terraform sử dụng hai biến đầu vào var.datacenter_namevar.network_name để tìm và trích xuất thông tin về datacenter và network từ hệ thống vSphere. Các biến đầu vào này có thể được truyền từ một file variables.tf hoặc từ một command line argument.

Cụ thể, đoạn mã trên sử dụng hai resource của vsphere: vsphere_datacentervsphere_network. Resource vsphere_datacenter được sử dụng để tìm datacenter trong hệ thống vSphere với tên được chỉ định bởi biến var.datacenter_name. Resource này trả về một đối tượng data.vsphere_datacenter chứa các thuộc tính của datacenter tìm thấy, trong đó id được sử dụng để xác định datacenter.

Tương tự, resource vsphere_network được sử dụng để tìm network trong hệ thống vSphere với tên được chỉ định bởi biến var.network_name. Resource này cũng trả về một đối tượng data.vsphere_network chứa các thuộc tính của network tìm thấy, trong đó id được sử dụng để xác định network.

Sau khi có được id của network, nó được sử dụng trong khai báo của resource vsphere_virtual_machine thông qua Terraform Expression: data.vsphere_network.network.id. Điều này cho phép Terraform thực hiện kết nối giữa các resource và đảm bảo rằng virtual machine được tạo ra sẽ được kết nối với network tìm thấy.

Ví dụ về Terraform Expressions trong AWS:

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"

  tags = {
    Name = "example-instance"
  }

  subnet_id = var.subnet_id
  vpc_security_group_ids = [aws_security_group.example.id]

  root_block_device {
    volume_type = "gp2"
    volume_size = var.volume_size
    encrypted = true
  }

  ebs_block_device {
    device_name = "/dev/sdh"
    snapshot_id = aws_ebs_snapshot.snapshot.id
    volume_size = 10
    volume_type = "gp2"
    encrypted = true
  }

  lifecycle {
    ignore_changes = [
      ebs_block_device.snapshot_id,
    ]
  }
}

Giải thích:

  • var.subnet_id là một biến (variable) chứa ID của subnet mà instance sẽ được khởi tạo.
  • aws_security_group.example.id là ID của security group được tạo ra trước đó.
  • var.volume_size là một biến (variable) chứa kích thước của đĩa EBS được sử dụng cho instance.
  • aws_ebs_snapshot.snapshot.id là ID của snapshot được tạo ra trước đó, được sử dụng để tạo một đĩa EBS mới.
  • lifecycle block được sử dụng để quản lý vòng đời của resource, trong trường hợp này, chúng ta đang khai báo rằng Terraform nên bỏ qua các thay đổi của thuộc tính snapshot_id trong block ebs_block_device khi chúng ta thực hiện một lần apply mới.

Các Terraform expressions được sử dụng trong ví dụ này bao gồm:

  • var.subnet_id là một biến (variable) trong file cấu hình Terraform.
  • aws_security_group.example.id là ID của security group được tạo ra trước đó và được sử dụng trong khai báo của instance.
  • var.volume_size là một biến (variable) trong file cấu hình Terraform.
  • aws_ebs_snapshot.snapshot.id là ID của snapshot được tạo ra trước đó và được sử dụng để tạo một đĩa EBS mới.
  • lifecycle block được sử dụng để quản lý vòng đời của resource, trong trường hợp này, chúng ta đang khai báo rằng Terraform nên bỏ qua các thay đổi của thuộc tính snapshot_id trong block ebs_block_device khi chúng ta thực hiện một lần apply mới.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories