|
| 1 | +# The `cluster_service_cidr` is required when `create == true` |
| 2 | +# This is a hacky way to make that logic work, otherwise Terraform always wants a value |
| 3 | +# and supplying any old value like `""` or `null` is not valid and will silently |
| 4 | +# fail to join nodes to the cluster |
| 5 | +resource "null_resource" "validate_cluster_service_cidr" { |
| 6 | + lifecycle { |
| 7 | + precondition { |
| 8 | + # The length 6 is currently arbitrary, but it's a safe bet that the CIDR will be longer than that |
| 9 | + # The main point is that a value needs to be provided when `create = true` |
| 10 | + condition = var.create ? length(var.cluster_service_cidr) > 6 : true |
| 11 | + error_message = "`cluster_service_cidr` is required when `create = true`." |
| 12 | + } |
| 13 | + } |
| 14 | +} |
| 15 | + |
| 16 | +locals { |
| 17 | + is_al2 = startswith(var.ami_type, "AL2_") |
| 18 | + is_al2023 = startswith(var.ami_type, "AL2023_") |
| 19 | + |
| 20 | + # Converts AMI type into user data template path |
| 21 | + ami_type_to_user_data_path = { |
| 22 | + AL2_ARM_64 = "${path.module}/templates/al2_user_data.tpl" |
| 23 | + AL2_x86_64 = "${path.module}/templates/al2_user_data.tpl" |
| 24 | + AL2_x86_64_GPU = "${path.module}/templates/al2_user_data.tpl" |
| 25 | + |
| 26 | + AL2023_x86_64_STANDARD = "${path.module}/templates/al2023_user_data.tpl" |
| 27 | + AL2023_ARM_64_STANDARD = "${path.module}/templates/al2023_user_data.tpl" |
| 28 | + AL2023_x86_64_NEURON = "${path.module}/templates/al2023_user_data.tpl" |
| 29 | + AL2023_x86_64_NVIDIA = "${path.module}/templates/al2023_user_data.tpl" |
| 30 | + AL2023_ARM_64_NVIDIA = "${path.module}/templates/al2023_user_data.tpl" |
| 31 | + |
| 32 | + BOTTLEROCKET_ARM_64 = "${path.module}/templates/bottlerocket_user_data.tpl" |
| 33 | + BOTTLEROCKET_x86_64 = "${path.module}/templates/bottlerocket_user_data.tpl" |
| 34 | + BOTTLEROCKET_ARM_64_FIPS = "${path.module}/templates/bottlerocket_user_data.tpl" |
| 35 | + BOTTLEROCKET_x86_64_FIPS = "${path.module}/templates/bottlerocket_user_data.tpl" |
| 36 | + BOTTLEROCKET_ARM_64_NVIDIA = "${path.module}/templates/bottlerocket_user_data.tpl" |
| 37 | + BOTTLEROCKET_x86_64_NVIDIA = "${path.module}/templates/bottlerocket_user_data.tpl" |
| 38 | + |
| 39 | + WINDOWS_CORE_2019_x86_64 = "${path.module}/templates/windows_user_data.tpl" |
| 40 | + WINDOWS_FULL_2019_x86_64 = "${path.module}/templates/windows_user_data.tpl" |
| 41 | + WINDOWS_CORE_2022_x86_64 = "${path.module}/templates/windows_user_data.tpl" |
| 42 | + WINDOWS_FULL_2022_x86_64 = "${path.module}/templates/windows_user_data.tpl" |
| 43 | + |
| 44 | + CUSTOM = var.user_data_template_path |
| 45 | + } |
| 46 | + user_data_path = coalesce(var.user_data_template_path, local.ami_type_to_user_data_path[var.ami_type]) |
| 47 | + |
| 48 | + cluster_dns_ips = flatten(concat([try(cidrhost(var.cluster_service_cidr, 10), "")], var.additional_cluster_dns_ips)) |
| 49 | + |
| 50 | + user_data = var.create ? base64encode(templatefile(local.user_data_path, |
| 51 | + { |
| 52 | + # https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-custom-ami |
| 53 | + enable_bootstrap_user_data = var.enable_bootstrap_user_data |
| 54 | + |
| 55 | + # Required to bootstrap node |
| 56 | + cluster_name = var.cluster_name |
| 57 | + cluster_endpoint = var.cluster_endpoint |
| 58 | + cluster_auth_base64 = var.cluster_auth_base64 |
| 59 | + |
| 60 | + cluster_service_cidr = var.cluster_service_cidr |
| 61 | + cluster_ip_family = var.cluster_ip_family |
| 62 | + |
| 63 | + # Bottlerocket |
| 64 | + cluster_dns_ips = "[${join(", ", formatlist("\"%s\"", local.cluster_dns_ips))}]" |
| 65 | + |
| 66 | + # Optional |
| 67 | + bootstrap_extra_args = var.bootstrap_extra_args |
| 68 | + pre_bootstrap_user_data = var.pre_bootstrap_user_data |
| 69 | + post_bootstrap_user_data = var.post_bootstrap_user_data |
| 70 | + } |
| 71 | + )) : "" |
| 72 | + |
| 73 | + user_data_type_to_rendered = try(coalesce( |
| 74 | + local.is_al2 ? try(data.cloudinit_config.al2_eks_managed_node_group[0].rendered, local.user_data) : null, |
| 75 | + local.is_al2023 ? try(data.cloudinit_config.al2023_eks_managed_node_group[0].rendered, local.user_data) : null, |
| 76 | + local.user_data, |
| 77 | + ), "") |
| 78 | +} |
| 79 | + |
| 80 | +# https://github.com/aws/containers-roadmap/issues/596#issuecomment-675097667 |
| 81 | +# Managed node group data must in MIME multi-part archive format, |
| 82 | +# as by default, EKS will merge the bootstrapping command required for nodes to join the |
| 83 | +# cluster with your user data. If you use a custom AMI in your launch template, |
| 84 | +# this merging will NOT happen and you are responsible for nodes joining the cluster. |
| 85 | +# See docs for more details -> https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-user-data |
| 86 | + |
| 87 | +data "cloudinit_config" "al2_eks_managed_node_group" { |
| 88 | + count = var.create && local.is_al2 && var.is_eks_managed_node_group && !var.enable_bootstrap_user_data && var.pre_bootstrap_user_data != "" && var.user_data_template_path == "" ? 1 : 0 |
| 89 | + |
| 90 | + base64_encode = true |
| 91 | + gzip = false |
| 92 | + boundary = "//" |
| 93 | + |
| 94 | + # Prepend to existing user data supplied by AWS EKS |
| 95 | + part { |
| 96 | + content = var.pre_bootstrap_user_data |
| 97 | + content_type = "text/x-shellscript" |
| 98 | + } |
| 99 | +} |
| 100 | + |
| 101 | +# Scenarios: |
| 102 | +# |
| 103 | +# 1. Do nothing - provide nothing |
| 104 | +# 2. Prepend stuff on EKS MNG (before EKS MNG adds its bit at the end) |
| 105 | +# 3. Own all of the stuff on self-MNG or EKS MNG w/ custom AMI |
| 106 | + |
| 107 | +locals { |
| 108 | + nodeadm_cloudinit = var.enable_bootstrap_user_data ? concat( |
| 109 | + var.cloudinit_pre_nodeadm, |
| 110 | + [{ |
| 111 | + content_type = "application/node.eks.aws" |
| 112 | + content = base64decode(local.user_data) |
| 113 | + }], |
| 114 | + var.cloudinit_post_nodeadm |
| 115 | + ) : var.cloudinit_pre_nodeadm |
| 116 | +} |
| 117 | + |
| 118 | +data "cloudinit_config" "al2023_eks_managed_node_group" { |
| 119 | + count = var.create && local.is_al2023 && length(local.nodeadm_cloudinit) > 0 ? 1 : 0 |
| 120 | + |
| 121 | + base64_encode = true |
| 122 | + gzip = false |
| 123 | + boundary = "MIMEBOUNDARY" |
| 124 | + |
| 125 | + dynamic "part" { |
| 126 | + # Using the index is fine in this context since any change in user data will be a replacement |
| 127 | + for_each = { for i, v in local.nodeadm_cloudinit : i => v } |
| 128 | + |
| 129 | + content { |
| 130 | + content = part.value.content |
| 131 | + content_type = try(part.value.content_type, null) |
| 132 | + filename = try(part.value.filename, null) |
| 133 | + merge_type = try(part.value.merge_type, null) |
| 134 | + } |
| 135 | + } |
| 136 | +} |
0 commit comments