HashiCorp Configuration Language หรือ HCL เป็นภาษาที่ออกแบบมาเพื่ออธิบายโครงสร้างพื้นฐาน (infrastructure) ในรูปแบบประกาศ (declarative) อ่านง่ายทั้งคนและเครื่อง ใช้เป็นภาษาหลักใน Terraform, Vault, Consul และ Nomad ผู้ที่เพิ่งเริ่มต้นควรเข้าใจไวยากรณ์พื้นฐานก่อน เพราะทุก resource ที่เขียนในโปรเจกต์ล้วนอยู่ในรูปแบบเดียวกัน หากสะดุดกับ syntax ตั้งแต่ต้นจะแก้บั๊กยากขึ้นเมื่อโปรเจกต์ใหญ่ขึ้น
บทความนี้จะสรุปองค์ประกอบหลักของ HCL ได้แก่ block, argument, expression, type ข้อมูล การอ้างอิงข้ามทรัพยากร การใช้ comment และตัวอย่างที่พบในไฟล์ .tf จริง ผู้อ่านจะสามารถนำไปประยุกต์เขียน configuration ได้ทันที
โครงสร้างของ Block
Block คือหน่วยพื้นฐานที่สุด ประกอบด้วย type, label (อาจมีหนึ่งหรือหลายตัว) และ body ปีกกาครอบเนื้อหาไว้ด้านใน ตัวอย่างของ block ใน Terraform ได้แก่ terraform, provider, resource, variable, output, module เป็นต้น
resource "aws_instance" "web" {
ami = "ami-0abcdef1234567890"
instance_type = "t3.micro"
tags = {
Name = "web-server"
}
}
ในตัวอย่างนี้ resource คือ block type, "aws_instance" คือ resource type, "web" คือ local name ที่ใช้อ้างอิงภายในไฟล์ และภายในปีกกาคือ body ที่บรรจุ argument ของ resource
Argument และ Attribute
Argument คือการกำหนดค่าให้ identifier ในรูปแบบ name = value ค่าที่ส่งให้อาจเป็น literal (string, number, bool), list, map หรือ expression ที่อ้างถึงค่าที่คำนวณจากที่อื่น HCL อนุญาตให้จัดเรียงบรรทัดอย่างอิสระและใช้ comma หรือ newline เป็นตัวคั่น
# string
region = "ap-southeast-1"
# number
instance_count = 3
# boolean
enabled = true
# list
zones = ["a", "b", "c"]
# map
tags = {
Environment = "production"
Owner = "platform-team"
}
Type ข้อมูลหลัก
- Primitive: string, number, bool — ชนิดพื้นฐาน
- Collection: list, set, map — เก็บค่าหลายตัวเรียงหรือ key-value
- Structural: object, tuple — ใช้ผสมชนิดหลากหลายได้
- Null: ค่าว่างที่หมายถึง “ไม่ตั้งค่า” ใช้ omit argument ที่ไม่ต้องการส่ง
Expression และ Interpolation
Expression คือสูตรที่คำนวณค่าได้ขณะรัน plan/apply ใช้อ้างอิง variable, resource attribute, data source หรือ built-in function รูปแบบการอ้างอิง: var.ชื่อ สำหรับ input variable, local.ชื่อ สำหรับ local value, และ ประเภท.ชื่อ.attribute สำหรับ resource
variable "env" {
default = "dev"
}
resource "aws_s3_bucket" "logs" {
bucket = "logs-${var.env}-${random_id.suffix.hex}"
}
resource "aws_instance" "app" {
ami = data.aws_ami.ubuntu.id
instance_type = var.env == "prod" ? "t3.large" : "t3.micro"
}
รูปแบบ ${...} เรียกว่า string interpolation ใช้ฝัง expression ลงใน string ได้ตรง ๆ ส่วน ?: คือ conditional expression สำหรับเลือกค่าตามเงื่อนไข
Built-in Function ที่ใช้บ่อย
HCL มี function สำเร็จรูปจำนวนมาก ช่วยจัดการ string, collection, encoding, hash, filesystem และอื่น ๆ โดยไม่ต้องเขียนโค้ดเอง
upper("hello") # "HELLO"
join("-", ["web", "01"]) # "web-01"
length(["a", "b", "c"]) # 3
lookup(var.tags, "Env", "dev") # หา key "Env" ใน map
file("${path.module}/user.sh") # อ่านไฟล์ในโฟลเดอร์ module
jsonencode({name = "app"}) # สร้าง JSON
cidrsubnet("10.0.0.0/16", 8, 2) # "10.0.2.0/24"
Comment
HCL รองรับ comment สามแบบ: # และ // สำหรับ single line และ /* ... */ สำหรับ multi-line การเขียน comment สำคัญต่อทีมมาก เพราะ config ที่ซับซ้อนอาจต้องอธิบาย business logic ที่ code เองไม่สื่อ
# comment ลักษณะ shell-style
// comment ลักษณะ C-style
/*
* สามารถขยายได้หลายบรรทัด
* เหมาะกับอธิบาย header
*/
resource "aws_instance" "web" {
# ...
}
Heredoc String
เมื่อต้องใส่ text หลายบรรทัด เช่น user-data script หรือ policy JSON การใช้ heredoc จะสะดวกกว่าใส่ escape ทุกบรรทัด ใช้ <<EOT เปิด และ EOT ปิด (ใส่ชื่อ marker อะไรก็ได้) หากต้องการให้ตัด whitespace ต้นบรรทัด ใช้ <<-EOT แทน
user_data = <<-EOT
#!/bin/bash
apt-get update
apt-get install -y nginx
systemctl enable nginx
EOT
Reference ข้าม Resource
จุดแข็งหลักของ HCL คือ dependency graph อัตโนมัติ เมื่อ resource หนึ่งอ้างถึง attribute ของอีก resource Terraform จะสร้าง resource ที่ถูกอ้างก่อนให้เสร็จเสมอ ไม่ต้องกำหนดลำดับเอง
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "web" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
}
บรรทัด aws_vpc.main.id บอกให้สร้าง VPC ก่อน จึงนำ id ไปใส่ที่ subnet การใช้ graph แบบนี้ช่วยลดข้อผิดพลาดมากเมื่อมี resource หลายสิบตัวเกี่ยวข้องกัน
Meta-argument ที่สำคัญ
count— จำลอง resource เป็นจำนวน N ตัว เข้าถึงผ่าน indexfor_each— สร้าง resource ตาม key ของ map หรือ setdepends_on— ระบุ dependency แบบ explicit เมื่อไม่มี attribute referencelifecycle— ควบคุมพฤติกรรมเช่น create_before_destroy, prevent_destroyprovider— ระบุ provider alias เมื่อใช้หลาย region/account
แนวทางเขียน HCL ให้อ่านง่าย
- จัด indent 2 spaces เสมอ (Terraform convention) และรัน
terraform fmtก่อน commit - จัดกลุ่ม argument: ค่า required ด้านบน, ค่า optional ด้านล่าง, block ซ้อนอยู่ท้ายสุด
- หลีกเลี่ยงบรรทัดยาวเกิน 100 ตัวอักษร หากจำเป็นให้แยก expression เข้า local value
- ตั้งชื่อ resource เป็น snake_case และสั้น กระชับ อธิบายหน้าที่
- แยกไฟล์ตามหน้าที่:
main.tf,variables.tf,outputs.tf,providers.tf
สรุป
HCL เป็นภาษาที่อ่านง่ายแต่มีความสามารถสูงเพียงพอต่อการอธิบายโครงสร้างพื้นฐานจริงในระบบ production องค์ประกอบหลักคือ block ซึ่งมี argument ภายใน รองรับ type ข้อมูลหลากหลาย และ expression ที่อ้างอิงข้ามทรัพยากรได้โดยอัตโนมัติ ผู้เริ่มต้นควรฝึกเขียนตัวอย่างง่ายหลาย ๆ ไฟล์ และใช้ terraform fmt กับ terraform validate เพื่อให้โค้ดสะอาดและถูกไวยากรณ์ก่อน apply เมื่อคุ้นกับโครงสร้างเหล่านี้แล้ว การอ่าน configuration ของคนอื่นจะง่ายขึ้นมาก และการขยายโปรเจกต์ไปสู่ module, workspace หรือ multi-cloud จะไม่เป็นอุปสรรค

