英文:
Best way to define dynamic block device selection in Terraform
问题
I'll provide the translated code portion as requested:
locals {
device_names = tolist([
"xvda",
"xvdb",
"xvdc",
"xvdd",
# (and so on for however many devices you expect to need to support,
# presumably up to "z" at the worst)
])
}
Please note that this is the translated code section from your provided text, and I won't answer any questions related to translation or provide additional information.
英文:
I'm trying to go off of the solution accepted in https://stackoverflow.com/questions/75257194/format-ascii-number-to-ascii-character-in-terraform but am still a bit confused how to go about the following:
Your example suggests that your goal is to map from an integer to a letter to use as a device name for an EC2 volume attachment. I think the most straightforward answer to meet that need with Terraform would be to hand-write (or, if you wish, use a one-off script to generate) a lookup table:
locals {
device_names = tolist([
"xvda",
"xvdb",
"xvdc",
"xvdd",
# (and so on for however many devices you expect to need to support,
# presumably up to "z" at the worst)
])
}
So, my situation is that I will have to use the same TF module to spin up EC2s that require different numbers of block devices. Some larger than others. So let's say I have a lookup table that has device names from "/dev/sda, /dev/sdb,
... all the way to /dev/sdz
." I'm still struggling to connect how to use an integer to say I want 6 block devices, and then get "/dev/sda, /dev/sdb, /dev/sdc, /dev/sdd, /dev/sde, /dev/sdf
" as a result.
My intention would be to have a *.tf
input file that would override default variables in order to get my desired result. So, for example, I might have a variable called data_file_count = 6
. With that, I would hope to get my six block devices provisioned. In a subsequent run of the same module, I may have a different *.tf
input file that sets data_file_count = 12
and get my 12 block devices provisioned for the EC2 instance...
Trying to find a lean and concise way to accomplish this... appreciate any help!
Thanks,
Steve
答案1
得分: 1
首先,正如原答案所说,你需要指定一个包含设备名称的列表。你必须确保列表中有足够的元素。如果你希望有12个设备,那么你必须在列表中至少指定12个名称:
locals {
device_names = tolist([
"/dev/sda",
"/dev/sdb",
"/dev/sdc",
"/dev/sdd",
"/dev/sde",
"/dev/sdf",
"/dev/sdg",
"/dev/sdh",
"/dev/sdi",
"/dev/sdj",
"/dev/sdk",
"/dev/sdl"
# (and so on for however many devices you expect to need to support,
# presumably up to "z" at the worst)
])
}
其次,正如你所说,你需要声明一个变量来表示你想要附加到实例的设备数量。我将称此变量为number_of_devices
,你可以随意命名。
variable "number_of_devices" {
type = number
default = 6 # 可选的默认值
}
现在,为了获取包含名称的子列表,我们可以使用terraform中的slice
函数。
例如:
output "devices" {
value = slice(local.device_names, 0, var.number_of_devices)
}
假设number_of_devices
的值是6
,我们将得到以下结果:
devices = tolist([
"/dev/sda",
"/dev/sdb",
"/dev/sdc",
"/dev/sdd",
"/dev/sde",
"/dev/sdf",
])
现在,最复杂的部分。为了使用这个子列表来实际获得所需数量的设备,你可以使用Terraform的dynamic
块。例如:
resource "aws_instance" "this" {
ami = ...
instance_type = "t4g.nano"
tags = {
Name = "test"
}
dynamic "ebs_block_device" {
for_each = slice(local.device_names, 0, var.number_of_devices) # 注意带有名称的子列表
content {
device_name = ebs_block_device.value
}
}
}
请记住,这段代码只是用来示范如何使用动态块的示例。为了创建一个EC2实例,你可能还需要配置很多其他内容,而且你可能需要避免与根设备的设备命名冲突。
英文:
First of all, as the original answer says, you have to specify a list with the device names. You have to make sure that you have enough elements in the list. If you expect 12 devices, you have to specify at least 12 names in the list:
locals {
device_names = tolist([
"/dev/sda",
"/dev/sdb",
"/dev/sdc",
"/dev/sdd",
"/dev/sde",
"/dev/sdf",
"/dev/sdg",
"/dev/sdh",
"/dev/sdi",
"/dev/sdj",
"/dev/sdk",
"/dev/sdl"
# (and so on for however many devices you expect to need to support,
# presumably up to "z" at the worst)
])
}
Second, as you said, you have to declare a variable for the number of devices you want to attach to an instance. I will call this variable number_of_devices
, you may call it however you want.
variable "number_of_devices" {
type = number
default = 6 # optional default value
}
Now, in order to get a sublist with the names, we can use the slice
function from terraform.
For example:
output "devices" {
value = slice(local.device_names, 0, var.number_of_devices)
}
Assuming the value for number_of_devices
is 6
, we will get the following result:
devices = tolist([
"/dev/sda",
"/dev/sdb",
"/dev/sdc",
"/dev/sdd",
"/dev/sde",
"/dev/sdf",
])
Now, the trickiest part. In order to use this sublist to actually have as many devices as you need, you can use a dynamic
block from Terraform. For example:
resource "aws_instance" "this" {
ami = ...
instance_type = "t4g.nano"
tags = {
Name = "test"
}
dynamic "ebs_block_device" {
for_each = slice(local.device_names, 0, var.number_of_devices) # notice the sublist with the names
content {
device_name = ebs_block_device.value
}
}
}
Keep in mind, this code was meant to be just an example of how to use the a dynamic block. In order to provision an EC2 instance, you may want to configure a bunch of other stuff and also you may want to avoid device naming collision with the root device.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论