1) traditional FOR in terraform
Trong Terraform, for
không được sử dụng như vòng lặp thông thường trong các ngôn ngữ lập trình như Python, Java, hoặc JavaScript. Thay vào đó, for
trong Terraform được sử dụng chủ yếu để tạo ra các cấu trúc dữ liệu như danh sách hoặc từ điển từ các cấu trúc dữ liệu khác.
Dưới đây là một số ví dụ về cách sử dụng for
trong Terraform:
For để tạo ra danh sách: Ví dụ bạn có một danh sách tên và muốn thêm tiền tố “mr-” vào mỗi tên:
variable "names" { default = ["john", "doe", "smith"] } locals { prefixed_names = [for name in var.names : "mr-${name}"] }
Kết quả của local.prefixed_names
sẽ là ["mr-john", "mr-doe", "mr-smith"]
.
For để tạo ra từ điển: Ví dụ bạn có một danh sách tên và muốn tạo một từ điển với tên làm khóa và giá trị là tên có tiền tố:
variable "names" { default = ["john", "doe", "smith"] } locals { name_map = {for name in var.names : name => "mr-${name}"} }
Kết quả của local.name_map
sẽ là:
{ "john" = "mr-john" "doe" = "mr-doe" "smith" = "mr-smith" }
For với điều kiện: Bạn cũng có thể sử dụng if
kết hợp với for
để lọc dữ liệu:
variable "numbers" { default = [1, 2, 3, 4, 5, 6] } locals { even_numbers = [for n in var.numbers : n if n % 2 == 0] }
Kết quả của local.even_numbers
sẽ là [2, 4, 6]
.
Đây là một biểu thức for
được sử dụng trong Terraform để tạo ra một danh sách mới từ một danh sách đã tồn tại (var.numbers
).
- [for n in var.numbers : … ]: Điều này nghĩa là “đối với mỗi phần tử
n
trong danh sáchvar.numbers
, thực hiện một số hành động”. - … n …: Đây chỉ đơn giản là giá trị mà chúng ta muốn thêm vào danh sách mới. Trong trường hợp này, chúng ta chỉ muốn thêm giá trị hiện tại của
n
vào danh sách mới (chúng ta không muốn biến đổi nó bằng cách nào). - … if n % 2 == 0: Đây là phần điều kiện. Nó chỉ thêm giá trị của
n
vào danh sách mới nếu giá trị đó thỏa mãn điều kiện là số chẵn (chúng ta kiểm tra điều này bằng cách sử dụng phép toán modulo:n % 2
). Nếun % 2
trả về 0, điều này có nghĩa làn
là một số chẵn, vì vậy nó sẽ được thêm vào danh sách mới.
Do đó, kết quả của biểu thức này là một danh sách chỉ chứa các số chẵn từ var.numbers
.
Ví dụ: Nếu var.numbers
là [1, 2, 3, 4, 5, 6]
, thì even_numbers
sẽ trở thành [2, 4, 6]
.
Dynamic Node Group Configuration for EKS in Terraform
let’s modify the specific part of your Terraform configuration to implement a loop for creating multiple node groups based on a new variable that allows customers to declare the details for any number of node groups. I’ll keep the rest of your configuration as is and focus on updating the section for dynamic node group creation.
First, define a new variable in your Terraform configuration to replace var.extra_node_group
. This new variable will be a list of objects, where each object represents a node group configuration:
variable "custom_node_groups" { description = "List of custom node group configurations" type = list(object({ name = string platform = string instance_type = string key_name = string desired_size = number max_size = number min_size = number node_labels = string node_taints = string volume_size = number volume_type = string iops = number throughput = number })) default = [] }
Now, modify the self_managed_node_groups
section within your EKS module configuration to dynamically create node groups based on the new custom_node_groups
variable:
self_managed_node_groups = merge( { # Preserved node groups (linux and windows) linux = { platform = "linux" name = "linux" public_ip = false instance_type = var.lin_instance_type key_name = var.node_host_key_name desired_size = var.lin_desired_size max_size = var.lin_max_size min_size = var.lin_min_size ami_id = data.aws_ami.lin_ami.id bootstrap_extra_args = chomp( <<-EOT --kubelet-extra-args '--node-labels=apps=true' EOT ) ebs_optimized = true block_device_mappings = { xvda = { device_name = "/dev/xvda" ebs = { volume_size = 100 volume_type = "gp3" iops = 3000 throughput = 125 encrypted = true delete_on_termination = true } } } }, windows = { platform = "windows" name = "windows" public_ip = false instance_type = var.win_instance_type key_name = var.node_host_key_name desired_size = var.win_desired_size max_size = var.win_max_size min_size = var.win_min_size ami_id = data.aws_ami.win_ami.id enable_bootstrap_user_data = true bootstrap_extra_args = chomp( <<-EOT -KubeletExtraArgs '--node-labels=apps=true' EOT ) post_bootstrap_user_data = var.disable_windows_defender ? chomp( <<-EOT # Add Windows Defender exclusion Set-MpPreference -DisableRealtimeMonitoring $true EOT ) : "" ebs_optimized = true block_device_mappings = { xvda = { device_name = "/dev/sda1" ebs = { volume_size = 100 volume_type = "gp3" iops = 3000 throughput = 125 encrypted = true delete_on_termination = true } } } } }, { for ng in var.custom_node_groups : ng.name => { platform = ng.platform name = ng.name public_ip = false instance_type = ng.instance_type key_name = ng.key_name desired_size = ng.desired_size max_size = ng.max_size min_size = ng.min_size ami_id = ng.platform == "linux" ? data.aws_ami.lin_ami.id : data.aws_ami.win_ami.id subnet_ids = local.effective_win_subnet_ids bootstrap_extra_args = chomp( <<-EOT --kubelet-extra-args '--node-labels=${ng.node_labels} --register-with-taints=${ng.node_taints}' EOT ) ebs_optimized = true block_device_mappings = { xvda = { device_name = ng.platform == "linux" ? "/dev/xvda" : "/dev/sda1" ebs = { volume_size = ng.volume_size volume_type = ng.volume_type iops = ng.iops throughput = ng.throughput encrypted = true delete_on_termination = true } } } } } )
With these changes, your Terraform configuration will now support dynamic
creation of multiple node groups based on the custom_node_groups
variable. Users can define any number of node groups by specifying their configurations in this variable, and your Terraform code will automatically create the corresponding resources.
Here’s an example value for the custom_node_groups
variable that simulates two different node groups, one intended for general application workloads and another optimized for compute-intensive tasks. You would place this example configuration in your Terraform terraform.tfvars
file, or pass it directly when running Terraform commands:
custom_node_groups = [ { name = "app-nodes" platform = "linux" instance_type = "t3.large" key_name = "my-key-pair" desired_size = 3 max_size = 5 min_size = 2 node_labels = "type=application,team=dev" node_taints = "specialty=app:NoSchedule" volume_size = 50 volume_type = "gp3" iops = 3000 throughput = 125 }, { name = "compute-nodes" platform = "linux" instance_type = "c5.2xlarge" key_name = "my-key-pair" desired_size = 2 max_size = 4 min_size = 1 node_labels = "type=compute,team=data" node_taints = "specialty=compute:NoSchedule" volume_size = 100 volume_type = "gp3" iops = 3000 throughput = 125 } ]
In this example:
custom_node_groups
is a list containing two maps, each representing a node group configuration.- The first node group,
app-nodes
, is set up witht3.large
instances, intended for general application workloads. It starts with three nodes (scaling between two and five), uses GP3 volumes with 50 GB size, and has specific labels and taints for scheduling. - The second node group,
compute-nodes
, usesc5.2xlarge
instances for compute-intensive tasks. This group starts with two nodes (scaling between one and four), uses larger GP3 volumes with 100 GB size, and also has distinct labels and taints for workload segregation.
This configuration can be adjusted based on your workload requirements, instance preferences, volume needs, and Kubernetes scheduling configurations.