Nếu như bạn đang muốn tạo các resource giống nhau ví dụ như một máy ảo nhưng sẽ có nhiều disk hoặc nhiều card mạng bạn nên xem xét sử dụng Dynamic Block Terraform.
Ví dụ dưới đây cho thấy nếu bạn tạo vsphere_virtual_machine
với nhiều ổ đĩa thì dưới đây là đoạn code cho thấy bạn phải nhập thủ công 3 block thông tin về disk. Và rất tiếc bạn không thể sử dụng “for_each” hoặc “count” xử lý từ đoạn code dưới.
resource "vsphere_virtual_machine" "vm" {
name = "mytestvm1"
# first boot disk
disk {
label = "disk0"
unit_number = 0
size = 40
}
# second and third data disk
disk {
label = "disk1"
unit_number = 1
size = 10
}
disk {
label = "disk2"
unit_number = 2
size=20
}
Các Dynamic Block cung cấp cú pháp cho phép bạn thể hiện một block có thể thay đổi trong một resource. Dưới đây là cách mà mình thể hiện số lượng đĩa với dung lượng và tên ổ đĩa khác nhau trên cùng một resource của VM.
locals {
disks = [
{ "id":1, "dev":"sdb", "sizeGB":10 },
{ "id":2, "dev":"sdc", "sizeGB":20 }
]
}
resource "vsphere_virtual_machine" "vm" {
name = "mytestvm1"
disk {
label = "disk0"
unit_number = 0
size = 40
}
dynamic "disk" {
for_each = [ for disk in local.disks: disk ]
content {
label = "disk${disk.value.id}"
unit_number = disk.value.id
size = disk.value.sizeGB
}
}
Mình đang sử dụng một cấu trúc locals để tạo danh sách để sử dụng for_each lặp lại chúng.
for_each = [ for disk in local.disks: disk ]
Sau đây mình sẽ demo cho bạn thấy điều kỳ diệu của nó. Mình có 1 file main.tf đầy đủ như dưới đây.
provider "vsphere" {
user = var.vsphere_env.user
password = var.vsphere_env.password
vsphere_server = var.vsphere_env.server
allow_unverified_ssl = true
}
locals {
disks = [
{ "id":1, "dev":"sdb", "sizeGB":100 },
{ "id":2, "dev":"sdc", "sizeGB":100 },
{ "id":3, "dev":"sdd", "sizeGB":100 },
{ "id":4, "dev":"sde", "sizeGB":100 },
{ "id":5, "dev":"sdf", "sizeGB":100 },
]
}
resource vsphere_virtual_machine "allvms" {
for_each = var.vms
resource_pool_id = data.vsphere_compute_cluster.this[each.key].resource_pool_id
datastore_id = data.vsphere_datastore.this[each.key].id
name = each.value.vmname
num_cpus = each.value.vCPU
memory = each.value.vMEM
guest_id = data.vsphere_virtual_machine.template[each.key].guest_id
scsi_type = data.vsphere_virtual_machine.template[each.key].scsi_type
cdrom {
client_device = true
}
network_interface {
network_id = data.vsphere_network.this[each.key].id
adapter_type = data.vsphere_virtual_machine.template[each.key].network_interface_types[0]
}
wait_for_guest_net_timeout = 0
disk {
label = "disk0"
unit_number = 0
size = each.value.vDisk
}
dynamic "disk" {
for_each = [ for disk in local.disks: disk ]
content {
label = "disk${disk.value.id}"
unit_number = disk.value.id
size = disk.value.sizeGB
}
}
clone {
template_uuid = data.vsphere_virtual_machine.template[each.key].id
}
extra_config = {
"guestinfo.metadata" = base64encode(data.template_file.metadataconfig[each.key].rendered)
"guestinfo.metadata.encoding" = "base64"
"guestinfo.userdata" = base64encode(data.template_file.kickstartconfig[each.key].rendered)
"guestinfo.userdata.encoding" = "base64"
}
connection {
host = each.value.ip
type = "ssh"
user = "root"
private_key = "${file("./common/id_rsa")}"
timeout = "10m"
}
provisioner "file" {
source = "./scripts/packages.sh"
destination = "/usr/local/bin/packages"
}
provisioner "remote-exec" {
inline = [
"sudo chmod -R 777 /usr/local/bin/packages",
"sudo packages function",
"sudo sed -i 's|#PermitRootLogin.*|PermitRootLogin yes|' /etc/ssh/sshd_config",
"sudo sed -i 's|#PasswordAuthentication.*|PasswordAuthentication yes|' /etc/ssh/sshd_config",
"sudo sed -i 's|# PasswordAuthentication.*|PasswordAuthentication yes|' /etc/ssh/ssh_config",
"sudo service ssh restart || sudo systemctl restart sshd",
"sudo echo 'root:Hoanghd164' | chpasswd"
]
}
}
Bạn đừng quan tâm nhiều file trên, hãy chú ý đến 2 thành phần chính như sau:
Ở block locals mình sẽ tạo ra 1 list tên disks có chứa các thông tin các disk sẽ được tạo, ví dụ size, id, tên device,…
locals {
disks = [
{ "id":1, "dev":"sdb", "sizeGB":100 },
{ "id":2, "dev":"sdc", "sizeGB":100 },
{ "id":3, "dev":"sdd", "sizeGB":100 },
{ "id":4, "dev":"sde", "sizeGB":100 },
{ "id":5, "dev":"sdf", "sizeGB":100 },
]
}
Ở block tiếp theo mình sẽ khai báo một block disk có lable là disk0 dùng để chạy OS.
Block dynamic disk mình sẽ dùng vòng lặp for để lấy các data ở block locals gán thông tin cho các disk chứa data.
disk {
label = "disk0"
unit_number = 0
size = each.value.vDisk
}
dynamic "disk" {
for_each = [ for disk in local.disks: disk ]
content {
label = "disk${disk.value.id}"
unit_number = disk.value.id
size = disk.value.sizeGB
}
}
Sau khi chạy terraform apply thì mình sẽ có 1 máy ảo như hình dưới, với disk 1 có 50GB để chứa OS và các disk còn lại mỗi disk là 100GB như chúng ta đã khai báo trong file main.tf
Hãy ssh vào server là list các disk lên, ta có kết quả như hình dưới.
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
fd0 2:0 1 4K 0 disk
sda 8:0 0 50G 0 disk
├─sda1 8:1 0 49.9G 0 part /
├─sda14 8:14 0 4M 0 part
└─sda15 8:15 0 106M 0 part /boot/efi
sdb 8:16 0 100G 0 disk
sdc 8:32 0 100G 0 disk
sdd 8:48 0 100G 0 disk
sde 8:64 0 100G 0 disk
sdf 8:80 0 100G 0 disk
sr0 11:0 1 44K 0 rom
Việc sử dụng các Dynamic Block có thể rất đơn giản nó giúp thay đổi tài nguyên một cách đơn giản.
Đây là liên kết đến một ví dụ đầy đủ về việc tạo vsphere vm với một số lượng đĩa dữ liệu thay đổi bằng cách sử dụng các Dynamic Block.
Chúc các bạn thành công.