I. HCL (HashiCorp Configuration Language) Block

HashiCorp Configuration Language (HCL) là ngôn ngữ cấu hình được tạo  HashiCorp. HCL được sử dụng với các cloud infrastructure automation tools của HashiCorp, chẳng hạn như Terraform. Ngôn ngữ này được tạo ra với mục tiêu thân thiện với cả con người và máy móc. Nó cũng có khả năng tương thích với JSON, có nghĩa là nó có thể tương tác với các hệ thống khác ngoài dòng sản phẩm Terraform.

Trong Terraform, block là đơn vị cơ bản được sử dụng để xác định và định cấu hình các khía cạnh khác nhau của cơ sở hạ tầng. Các block được viết bằng HashiCorp Configuration Language (HCL) và cho phép bạn khai báo resources, providers, variables, outputs và các thành phần cấu hình khác trong Terraform. Trong bài viết này chúng ta sẽ tìm hiểu các loại block trong HCL và mục đích sử dụng của chúng.

Block có nhiều loại (block_type), có thể có 0 hoặc nhiều label bắt buộc, theo sau là dấu ngoặc { } chứa nội dung của khối. Các khối có thể được lồng vào nhau. Đây là cách format chung của một block:

block_type "label_1" "label_2" {
  argument_1 = value_1
  argument_2 = value_2
}

Hãy cùng phân tích vị dụ về một block có block_typeresource :

resource "aws_instance" "app_server" {
  ami           = "ami-830c94e3"
  instance_type = "t2.micro"

  tags = {
    Name = "PathToTerraformCertInstance"
  }
}

Ở đây chúng ta có một block loại resource. Vì chúng ta đang sử dụng AWS provider nên chúng ta có thể  tài liệu tại đây.

aws_instancelabel đầu tiên trỏ đến loại resource cung cấp bởi AWS provider và app_serverlabel thứ hai đại diện cho tên của resource. Terraform hỗ trợ truy cập các phần tử bằng cách sử dụng ký hiệu dấu chấm như sau: aws_instance.app_server.tags

Một số resource có thể có các required arguments. Bạn nên kiểm tra các official docs để biết required arguments. Trong trường hợp của chúng ta, aws_instance có 2 đối số bắt buộc: amiinstance_type.

Đối với tags block, bạn nên tập thói quen gắn tag các resource  của mình.

Bây giờ chúng ta đã có cái nhìn tổng quát về Terraform block, hãy cùng khám phá loại block nào chúng ta có thể sử dụng trong cấu hình.

II. Terraform Block Types

Bài viết sẽ đề cập đến các loại block dưới đây:

  1. terraform block
  2. provider block
  3. resource block
  4. variable block
  5. locals block
  6. data block
  7. module block
  8. output block
  9. provisioner block

Chúng ta sẽ xem xét cấu trúc cơ bản và mục đích của từng block. Khi đã quen với các block này, chúng ta có thể bắt đầu xây dựng cơ sở hạ tầng thực tế.

Terraform Block

terraform block được sử dụng để thiết lập phiên bản của terraform mà chúng ta muốn. Nó cũng có thể chứa require_providers block bên trong chỉ định phiên bản của các providers mà chúng ta cần, cũng như nơi Terraform nên tải xuống các providers này. terraform block thường được đặt trong một file riêng biệt được gọi là terraform.tf như một cách để tách các settings thành file riêng.

Dưới đây là một ví dụ về terraform block :

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 2.0"
    }
  }
  required_version = ">= 1.0.1"
}

Provider Block

Các provider block chỉ định loại module đặc biệt cho phép Terraform tương tác với nhiều cloud-hosting platforms hoặc data centers khác nhau. provider block phải được định cấu hình bằng thông tin xác thực phù hợp trước khi chúng ta có thể sử dụng chúng (ví dụ: AWS thì cần cấu hình secret_key và access_key). Các phiên bản và vị trí tải xuống của Provider thường được chỉ định bên trong terraform block, nhưng bạn cũng có thể chỉ định nó bên trong block này.

provider "aws" {
  version = "~> 3.0"
  region = "us-east-1"
}

Resource Block

Các resource block được sử dụng để quản lý các resources như compute instances, virtual networks, databases, buckets, hoặc DNS resources. Loại block này là xương sống của bất kỳ terraform configuration nào vì nó đại diện cho các resources thực tế.

resource "aws_instance" "example_resource" {
  ami           = "ami-005e54dee72cc1d00" # us-west-2
  instance_type = "t2.micro"
  credit_specification {
    cpu_credits = "unlimited"
  }
}

Variable Block

block này thường được gọi là input variable block. variable block cung cấp các tham số cho các module terraform và cho phép người dùng tùy chỉnh dữ liệu được cung cấp cho các module terraform khác mà không cần sửa đổi source code.

Các variable thường nằm trong tập tin riêng của chúng có tên là variables.tf. Để sử dụng một variable, nó cần được khai báo dưới dạng một block. Một variable block sẽ như sau:

variable "example_variable" {
  type = var_type
  description = var_description 
  default = value_1 
  sensitive = var_boolean_value 
} 

Terraform có thứ tự ưu tiên nghiêm ngặt cho việc cài đặt các biến, đây là từ cao nhất đến thấp nhất:

  1. Command line (-varvar-file)
  2. *.auto.tfvars hoặc *auto.tfvars.json
  3. terraform.tfvars.json
  4. terraform.tfvars file
  5. Env variables
  6. Variable defaults

Locals Block

Thường được gọi là local variables block(biến cục bộ), block này được sử dụng để giữ các giá trị hoặc biểu thức được tham chiếu thường xuyên nhằm giữ cho code sạch sẽ và gọn gàng.

local block có thể chứa nhiều biến bên trong. Các biểu thức trong giá trị cục bộ không giới hạn ở các hằng số bằng chữ. Chúng cũng có thể tham chiếu các giá trị khác trong module để biến đổi hoặc kết hợp chúng. Các biến này có thể được gọi bằng cú pháp local.var_name, lưu ý rằng nó được định nghĩa là locals nhưng khi gọi thì sẽ chuyển thành local. (không có s).

locals {
  service_name = "forum"
  owner        = "Community Team"
  instance_ids = concat(aws_instance.blue.*.id, aws_instance.green.*.id)
}

Data Block

Mục đích chính của data block là load hoặc query dữ liệu từ các API không phải của Terraform. data block có thể được sử dụng để mang lại sự linh hoạt cho cấu hình của bạn hoặc để kết nối các workspaces việc khác nhau. Một cách mà chúng ta sẽ sử dụng data block là truy vấn API AWS để có được một danh sách các active Availability Zones để deploy resources.

Data được truy cập với format data.<TYPE>.<NAME>.<ATTRIBUTE>

# Find the latest available AMI that is tagged with Component = web
data "aws_ami" "web" {
  filter {
    name   = "state"
    values = ["available"]
  }

  filter {
    name   = "tag:Component"
    values = ["web"]
  }

  most_recent = true
}
resource "aws_instance" "web" {
  ami           = data.aws_ami.web.id
  instance_type = "t1.micro"
}

Module Block

Module là nơi chứa nhiều resources được sử dụng cùng nhau. Một module bao gồm các files .tf và/hoặc .tf.json được lưu trữ trong một thư mục. Đây là cách chính để đóng gói và tái sử dụng các tài nguyên trong Terraform.

Mỗi cấu hình Terraform đều có ít nhất một model (root module) chứa các resources được định nghĩa trong tệp .tf.

Đây là  ví dụ về một module:

Output Block

Đây là một block hầu như luôn có mặt trong tất cả các cấu hình. Nó cho phép Terraform xuất structured data về cấu hình của bạn. Người dùng có thể sử dụng output này để xem dữ liệu như IP hoặc tên resources ở terminal. Một trường hợp sử dụng khác liên quan đến việc sử dụng dữ liệu này trong Terraform workspace khác hoặc chia sẻ dữ liệu giữa các mudule.

output "test_server_public_ip" {
  description = "My test output for EC2 public IP"
  value = aws_instance.test_web_server.public_ip
  sensitive = true
}

output "public_url" {
  description = "Public URL for my web server"
  value = "https://${aws_instance.test_web_server.public_ip}:8000/index.html"
}

Provisioner Block

Provisioners cho phép chúng ta chỉ định các hành động sẽ được thực hiện trên các local hoặc remote machines để chuẩn bị resources cho các service.

Có hai loại  Terraform provisioners: local-execremote-exec.

local-exec được thực thi sau khi tài nguyên được tạo. Nó chạy các process trên máy chạy Terraform, nghĩa là máy mà bạn chạy ứng dụng terraform. Đây rất có thể là máy tính của riêng bạn.

remote-exec được thực thi từ xa, giống như EC2 instance trên AWS.

Đây là ví dụ về provisioner cho EC2 instance. Ví dụ này chứa cả local-execremote-exec:

resource "aws_instance" "web_server" {
  # ...

  provisioner "local-exec" {
    command = "Get-Date > completed.txt"
    interpreter = ["PowerShell", "-Command"]
  }
  provisioner "remote-exec" {
    inline = [
      "chmod +x /tmp/script.sh",
      "/tmp/script.sh args",
    ]
  }
}

III. Kết:

Đây là phần cuối của bài viết khá dài về các Terraform block. Bây giờ chúng ta đã biết mình có những công cụ nào để sử dụng, chúng ta có thể bắt đầu tạo cơ sở hạ tầng thực tế.

IV. Tham Khảo:

  1. https://developer.hashicorp.com/terraform/language
  2. https://devopsvn.tech/terraform-series/terraform/bai-0-infrastructure-as-code-va-terraform
  3. https://www.geeksforgeeks.org/different-types-of-blocks-in-terraform/
  4. https://www.linode.com/docs/guides/introduction-to-hcl/