feat: Add support for AL2023 nodeadm user data (#2942)

This commit is contained in:
Bryant Biggs
2024-02-29 19:12:50 -05:00
committed by GitHub
parent e6c3e90a02
commit 7c99bb19cd
18 changed files with 599 additions and 38 deletions

View File

@@ -26,6 +26,7 @@ No modules.
| Name | Type |
|------|------|
| [cloudinit_config.al2023_eks_managed_node_group](https://registry.terraform.io/providers/hashicorp/cloudinit/latest/docs/data-sources/config) | data source |
| [cloudinit_config.linux_eks_managed_node_group](https://registry.terraform.io/providers/hashicorp/cloudinit/latest/docs/data-sources/config) | data source |
## Inputs
@@ -33,6 +34,8 @@ No modules.
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_bootstrap_extra_args"></a> [bootstrap\_extra\_args](#input\_bootstrap\_extra\_args) | Additional arguments passed to the bootstrap script. When `platform` = `bottlerocket`; these are additional [settings](https://github.com/bottlerocket-os/bottlerocket#settings) that are provided to the Bottlerocket user data | `string` | `""` | no |
| <a name="input_cloudinit_post_nodeadm"></a> [cloudinit\_post\_nodeadm](#input\_cloudinit\_post\_nodeadm) | Array of cloud-init document parts that are created after the nodeadm document part | <pre>list(object({<br> content = string<br> content_type = optional(string)<br> filename = optional(string)<br> merge_type = optional(string)<br> }))</pre> | `[]` | no |
| <a name="input_cloudinit_pre_nodeadm"></a> [cloudinit\_pre\_nodeadm](#input\_cloudinit\_pre\_nodeadm) | Array of cloud-init document parts that are created before the nodeadm document part | <pre>list(object({<br> content = string<br> content_type = optional(string)<br> filename = optional(string)<br> merge_type = optional(string)<br> }))</pre> | `[]` | no |
| <a name="input_cluster_auth_base64"></a> [cluster\_auth\_base64](#input\_cluster\_auth\_base64) | Base64 encoded CA of associated EKS cluster | `string` | `""` | no |
| <a name="input_cluster_endpoint"></a> [cluster\_endpoint](#input\_cluster\_endpoint) | Endpoint of associated EKS cluster | `string` | `""` | no |
| <a name="input_cluster_name"></a> [cluster\_name](#input\_cluster\_name) | Name of the EKS cluster | `string` | `""` | no |

View File

@@ -1,65 +1,49 @@
locals {
int_linux_default_user_data = var.create && var.platform == "linux" && (var.enable_bootstrap_user_data || var.user_data_template_path != "") ? base64encode(templatefile(
coalesce(var.user_data_template_path, "${path.module}/../../templates/linux_user_data.tpl"),
template_path = {
al2023 = "${path.module}/../../templates/al2023_user_data.tpl"
bottlerocket = "${path.module}/../../templates/bottlerocket_user_data.tpl"
linux = "${path.module}/../../templates/linux_user_data.tpl"
windows = "${path.module}/../../templates/windows_user_data.tpl"
}
user_data = base64encode(templatefile(
coalesce(var.user_data_template_path, local.template_path[var.platform]),
{
# https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-custom-ami
enable_bootstrap_user_data = var.enable_bootstrap_user_data
# Required to bootstrap node
cluster_name = var.cluster_name
cluster_endpoint = var.cluster_endpoint
cluster_auth_base64 = var.cluster_auth_base64
# Optional
cluster_service_ipv4_cidr = var.cluster_service_ipv4_cidr != null ? var.cluster_service_ipv4_cidr : ""
bootstrap_extra_args = var.bootstrap_extra_args
pre_bootstrap_user_data = var.pre_bootstrap_user_data
post_bootstrap_user_data = var.post_bootstrap_user_data
}
)) : ""
))
platform = {
al2023 = {
user_data = var.create ? try(data.cloudinit_config.al2023_eks_managed_node_group[0].rendered, local.user_data) : ""
}
bottlerocket = {
user_data = var.create && var.platform == "bottlerocket" && (var.enable_bootstrap_user_data || var.user_data_template_path != "" || var.bootstrap_extra_args != "") ? base64encode(templatefile(
coalesce(var.user_data_template_path, "${path.module}/../../templates/bottlerocket_user_data.tpl"),
{
# https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-custom-ami
enable_bootstrap_user_data = var.enable_bootstrap_user_data
# Required to bootstrap node
cluster_name = var.cluster_name
cluster_endpoint = var.cluster_endpoint
cluster_auth_base64 = var.cluster_auth_base64
# Optional - is appended if using EKS managed node group without custom AMI
# cluster_service_ipv4_cidr = var.cluster_service_ipv4_cidr # Bottlerocket pulls this automatically https://github.com/bottlerocket-os/bottlerocket/issues/1866
bootstrap_extra_args = var.bootstrap_extra_args
}
)) : ""
user_data = var.create && var.platform == "bottlerocket" && (var.enable_bootstrap_user_data || var.user_data_template_path != "" || var.bootstrap_extra_args != "") ? local.user_data : ""
}
linux = {
user_data = try(data.cloudinit_config.linux_eks_managed_node_group[0].rendered, local.int_linux_default_user_data)
user_data = var.create ? try(data.cloudinit_config.linux_eks_managed_node_group[0].rendered, local.user_data) : ""
}
windows = {
user_data = var.create && var.platform == "windows" && (var.enable_bootstrap_user_data || var.user_data_template_path != "" || var.pre_bootstrap_user_data != "") ? base64encode(templatefile(
coalesce(var.user_data_template_path, "${path.module}/../../templates/windows_user_data.tpl"),
{
# https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-custom-ami
enable_bootstrap_user_data = var.enable_bootstrap_user_data
# Required to bootstrap node
cluster_name = var.cluster_name
cluster_endpoint = var.cluster_endpoint
cluster_auth_base64 = var.cluster_auth_base64
# Optional - is appended if using EKS managed node group without custom AMI
# cluster_service_ipv4_cidr = var.cluster_service_ipv4_cidr # Not supported yet: https://github.com/awslabs/amazon-eks-ami/issues/805
bootstrap_extra_args = var.bootstrap_extra_args
pre_bootstrap_user_data = var.pre_bootstrap_user_data
post_bootstrap_user_data = var.post_bootstrap_user_data
}
)) : ""
user_data = var.create && var.platform == "windows" && (var.enable_bootstrap_user_data || var.user_data_template_path != "" || var.pre_bootstrap_user_data != "") ? local.user_data : ""
}
}
}
# https://github.com/aws/containers-roadmap/issues/596#issuecomment-675097667
# An important note is that user data must in MIME multi-part archive format,
# Managed nodegroup data must in MIME multi-part archive format,
# as by default, EKS will merge the bootstrapping command required for nodes to join the
# cluster with your user data. If you use a custom AMI in your launch template,
# this merging will NOT happen and you are responsible for nodes joining the cluster.
@@ -74,7 +58,44 @@ data "cloudinit_config" "linux_eks_managed_node_group" {
# Prepend to existing user data supplied by AWS EKS
part {
content_type = "text/x-shellscript"
content = var.pre_bootstrap_user_data
content_type = "text/x-shellscript"
}
}
# Scenarios:
#
# 1. Do nothing - provide nothing
# 2. Prepend stuff on EKS MNG (before EKS MNG adds its bit at the end)
# 3. Own all of the stuff on self-MNG or EKS MNG w/ custom AMI
locals {
nodeadm_cloudinit = var.enable_bootstrap_user_data ? concat(
var.cloudinit_pre_nodeadm,
[{
content_type = "application/node.eks.aws"
content = base64decode(local.user_data)
}],
var.cloudinit_post_nodeadm
) : var.cloudinit_pre_nodeadm
}
data "cloudinit_config" "al2023_eks_managed_node_group" {
count = var.create && var.platform == "al2023" && length(local.nodeadm_cloudinit) > 0 ? 1 : 0
base64_encode = true
gzip = false
boundary = "MIMEBOUNDARY"
dynamic "part" {
# Using the index is fine in this context since any change in user data will be a replacement
for_each = { for i, v in local.nodeadm_cloudinit : i => v }
content {
content = part.value.content
content_type = try(part.value.content_type, null)
filename = try(part.value.filename, null)
merge_type = try(part.value.merge_type, null)
}
}
}

View File

@@ -69,3 +69,25 @@ variable "user_data_template_path" {
type = string
default = ""
}
variable "cloudinit_pre_nodeadm" {
description = "Array of cloud-init document parts that are created before the nodeadm document part"
type = list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
}))
default = []
}
variable "cloudinit_post_nodeadm" {
description = "Array of cloud-init document parts that are created after the nodeadm document part"
type = list(object({
content = string
content_type = optional(string)
filename = optional(string)
merge_type = optional(string)
}))
default = []
}