feat!: Add support for Outposts, remove node security group, add support for addon preserve and most_recent configurations (#2250)

Co-authored-by: Anton Babenko <anton@antonbabenko.com>
Resolves undefined
This commit is contained in:
Bryant Biggs
2022-12-05 16:26:23 -05:00
committed by GitHub
parent efbe952632
commit b2e97ca3dc
66 changed files with 2749 additions and 1776 deletions

View File

@@ -1,5 +1,4 @@
data "aws_partition" "current" {}
data "aws_caller_identity" "current" {}
################################################################################
@@ -30,75 +29,51 @@ module "user_data" {
################################################################################
locals {
# There are 4 scenarios here that have to be considered for `use_custom_launch_template`:
# 1. `var.create_launch_template = false && var.launch_template_name == ""` => EKS MNG will use its own default LT
# 2. `var.create_launch_template = false && var.launch_template_name == "something"` => User provided custom LT will be used
# 3. `var.create_launch_template = true && var.launch_template_name == ""` => Custom LT will be used, module will provide a default name
# 4. `var.create_launch_template = true && var.launch_template_name == "something"` => Custom LT will be used, LT name is provided by user
use_custom_launch_template = var.create_launch_template || var.launch_template_name != ""
launch_template_name_int = coalesce(var.launch_template_name, "${var.name}-eks-node-group")
security_group_ids = compact(concat([try(aws_security_group.this[0].id, ""), var.cluster_primary_security_group_id], var.vpc_security_group_ids))
launch_template_name = coalesce(var.launch_template_name, "${var.name}-eks-node-group")
security_group_ids = compact(concat([var.cluster_primary_security_group_id], var.vpc_security_group_ids))
}
resource "aws_launch_template" "this" {
count = var.create && var.create_launch_template ? 1 : 0
name = var.launch_template_use_name_prefix ? null : local.launch_template_name_int
name_prefix = var.launch_template_use_name_prefix ? "${local.launch_template_name_int}-" : null
description = var.launch_template_description
ebs_optimized = var.ebs_optimized
image_id = var.ami_id
# # Set on node group instead
# instance_type = var.launch_template_instance_type
key_name = var.key_name
user_data = module.user_data.user_data
vpc_security_group_ids = length(var.network_interfaces) > 0 ? [] : local.security_group_ids
default_version = var.launch_template_default_version
update_default_version = var.update_launch_template_default_version
disable_api_termination = var.disable_api_termination
# Set on EKS managed node group, will fail if set here
# https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-basics
# instance_initiated_shutdown_behavior = var.instance_initiated_shutdown_behavior
kernel_id = var.kernel_id
ram_disk_id = var.ram_disk_id
count = var.create && var.create_launch_template && var.use_custom_launch_template ? 1 : 0
dynamic "block_device_mappings" {
for_each = var.block_device_mappings
content {
device_name = block_device_mappings.value.device_name
no_device = lookup(block_device_mappings.value, "no_device", null)
virtual_name = lookup(block_device_mappings.value, "virtual_name", null)
device_name = try(block_device_mappings.value.device_name, null)
dynamic "ebs" {
for_each = flatten([lookup(block_device_mappings.value, "ebs", [])])
for_each = try([block_device_mappings.value.ebs], [])
content {
delete_on_termination = lookup(ebs.value, "delete_on_termination", null)
encrypted = lookup(ebs.value, "encrypted", null)
kms_key_id = lookup(ebs.value, "kms_key_id", null)
iops = lookup(ebs.value, "iops", null)
throughput = lookup(ebs.value, "throughput", null)
snapshot_id = lookup(ebs.value, "snapshot_id", null)
volume_size = lookup(ebs.value, "volume_size", null)
volume_type = lookup(ebs.value, "volume_type", null)
delete_on_termination = try(ebs.value.delete_on_termination, null)
encrypted = try(ebs.value.encrypted, null)
iops = try(ebs.value.iops, null)
kms_key_id = try(ebs.value.kms_key_id, null)
snapshot_id = try(ebs.value.snapshot_id, null)
throughput = try(ebs.value.throughput, null)
volume_size = try(ebs.value.volume_size, null)
volume_type = try(ebs.value.volume_type, null)
}
}
no_device = try(block_device_mappings.value.no_device, null)
virtual_name = try(block_device_mappings.value.virtual_name, null)
}
}
dynamic "capacity_reservation_specification" {
for_each = length(var.capacity_reservation_specification) > 0 ? [var.capacity_reservation_specification] : []
content {
capacity_reservation_preference = lookup(capacity_reservation_specification.value, "capacity_reservation_preference", null)
capacity_reservation_preference = try(capacity_reservation_specification.value.capacity_reservation_preference, null)
dynamic "capacity_reservation_target" {
for_each = try([capacity_reservation_specification.value.capacity_reservation_target], [])
content {
capacity_reservation_id = lookup(capacity_reservation_target.value, "capacity_reservation_id", null)
capacity_reservation_id = try(capacity_reservation_target.value.capacity_reservation_id, null)
capacity_reservation_resource_group_arn = try(capacity_reservation_target.value.capacity_reservation_resource_group_arn, null)
}
}
}
@@ -106,21 +81,29 @@ resource "aws_launch_template" "this" {
dynamic "cpu_options" {
for_each = length(var.cpu_options) > 0 ? [var.cpu_options] : []
content {
core_count = cpu_options.value.core_count
threads_per_core = cpu_options.value.threads_per_core
core_count = try(cpu_options.value.core_count, null)
threads_per_core = try(cpu_options.value.threads_per_core, null)
}
}
dynamic "credit_specification" {
for_each = length(var.credit_specification) > 0 ? [var.credit_specification] : []
content {
cpu_credits = credit_specification.value.cpu_credits
cpu_credits = try(credit_specification.value.cpu_credits, null)
}
}
default_version = var.launch_template_default_version
description = var.launch_template_description
disable_api_termination = var.disable_api_termination
ebs_optimized = var.ebs_optimized
dynamic "elastic_gpu_specifications" {
for_each = length(var.elastic_gpu_specifications) > 0 ? [var.elastic_gpu_specifications] : []
for_each = var.elastic_gpu_specifications
content {
type = elastic_gpu_specifications.value.type
}
@@ -128,6 +111,7 @@ resource "aws_launch_template" "this" {
dynamic "elastic_inference_accelerator" {
for_each = length(var.elastic_inference_accelerator) > 0 ? [var.elastic_inference_accelerator] : []
content {
type = elastic_inference_accelerator.value.type
}
@@ -135,6 +119,7 @@ resource "aws_launch_template" "this" {
dynamic "enclave_options" {
for_each = length(var.enclave_options) > 0 ? [var.enclave_options] : []
content {
enabled = enclave_options.value.enabled
}
@@ -143,7 +128,8 @@ resource "aws_launch_template" "this" {
# Set on EKS managed node group, will fail if set here
# https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-basics
# dynamic "hibernation_options" {
# for_each = var.hibernation_options != null ? [var.hibernation_options] : []
# for_each = length(var.hibernation_options) > 0 ? [var.hibernation_options] : []
# content {
# configured = hibernation_options.value.configured
# }
@@ -159,104 +145,154 @@ resource "aws_launch_template" "this" {
# }
# }
image_id = var.ami_id
# Set on EKS managed node group, will fail if set here
# https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-basics
# instance_initiated_shutdown_behavior = var.instance_initiated_shutdown_behavior
dynamic "instance_market_options" {
for_each = length(var.instance_market_options) > 0 ? [var.instance_market_options] : []
content {
market_type = instance_market_options.value.market_type
market_type = try(instance_market_options.value.market_type, null)
dynamic "spot_options" {
for_each = length(lookup(instance_market_options.value, "spot_options", {})) > 0 ? [instance_market_options.value.spot_options] : []
for_each = try([instance_market_options.value.spot_options], [])
content {
block_duration_minutes = lookup(spot_options.value, "block_duration_minutes", null)
instance_interruption_behavior = lookup(spot_options.value, "instance_interruption_behavior", null)
max_price = lookup(spot_options.value, "max_price", null)
spot_instance_type = lookup(spot_options.value, "spot_instance_type", null)
valid_until = lookup(spot_options.value, "valid_until", null)
block_duration_minutes = try(spot_options.value.block_duration_minutes, null)
instance_interruption_behavior = try(spot_options.value.instance_interruption_behavior, null)
max_price = try(spot_options.value.max_price, null)
spot_instance_type = try(spot_options.value.spot_instance_type, null)
valid_until = try(spot_options.value.valid_until, null)
}
}
}
}
# # Set on node group instead
# instance_type = var.launch_template_instance_type
kernel_id = var.kernel_id
key_name = var.key_name
dynamic "license_specification" {
for_each = length(var.license_specifications) > 0 ? [var.license_specifications] : []
for_each = length(var.license_specifications) > 0 ? var.license_specifications : {}
content {
license_configuration_arn = license_specifications.value.license_configuration_arn
}
}
dynamic "maintenance_options" {
for_each = length(var.maintenance_options) > 0 ? [var.maintenance_options] : []
content {
auto_recovery = try(maintenance_options.value.auto_recovery, null)
}
}
dynamic "metadata_options" {
for_each = length(var.metadata_options) > 0 ? [var.metadata_options] : []
content {
http_endpoint = lookup(metadata_options.value, "http_endpoint", null)
http_tokens = lookup(metadata_options.value, "http_tokens", null)
http_put_response_hop_limit = lookup(metadata_options.value, "http_put_response_hop_limit", null)
http_protocol_ipv6 = lookup(metadata_options.value, "http_protocol_ipv6", null)
instance_metadata_tags = lookup(metadata_options.value, "instance_metadata_tags", null)
http_endpoint = try(metadata_options.value.http_endpoint, null)
http_protocol_ipv6 = try(metadata_options.value.http_protocol_ipv6, null)
http_put_response_hop_limit = try(metadata_options.value.http_put_response_hop_limit, null)
http_tokens = try(metadata_options.value.http_tokens, null)
instance_metadata_tags = try(metadata_options.value.instance_metadata_tags, null)
}
}
dynamic "monitoring" {
for_each = var.enable_monitoring != null ? [1] : []
for_each = var.enable_monitoring ? [1] : []
content {
enabled = var.enable_monitoring
}
}
name = var.launch_template_use_name_prefix ? null : local.launch_template_name
name_prefix = var.launch_template_use_name_prefix ? "${local.launch_template_name}-" : null
dynamic "network_interfaces" {
for_each = var.network_interfaces
content {
associate_carrier_ip_address = lookup(network_interfaces.value, "associate_carrier_ip_address", null)
associate_public_ip_address = lookup(network_interfaces.value, "associate_public_ip_address", null)
delete_on_termination = lookup(network_interfaces.value, "delete_on_termination", null)
description = lookup(network_interfaces.value, "description", null)
device_index = lookup(network_interfaces.value, "device_index", null)
interface_type = lookup(network_interfaces.value, "interface_type", null)
associate_carrier_ip_address = try(network_interfaces.value.associate_carrier_ip_address, null)
associate_public_ip_address = try(network_interfaces.value.associate_public_ip_address, null)
delete_on_termination = try(network_interfaces.value.delete_on_termination, null)
description = try(network_interfaces.value.description, null)
device_index = try(network_interfaces.value.device_index, null)
interface_type = try(network_interfaces.value.interface_type, null)
ipv4_address_count = try(network_interfaces.value.ipv4_address_count, null)
ipv4_addresses = try(network_interfaces.value.ipv4_addresses, [])
ipv4_address_count = lookup(network_interfaces.value, "ipv4_address_count", null)
ipv4_prefix_count = try(network_interfaces.value.ipv4_prefix_count, null)
ipv4_prefixes = try(network_interfaces.value.ipv4_prefixes, null)
ipv6_address_count = try(network_interfaces.value.ipv6_address_count, null)
ipv6_addresses = try(network_interfaces.value.ipv6_addresses, [])
ipv6_address_count = lookup(network_interfaces.value, "ipv6_address_count", null)
network_interface_id = lookup(network_interfaces.value, "network_interface_id", null)
private_ip_address = lookup(network_interfaces.value, "private_ip_address", null)
security_groups = compact(concat(try(network_interfaces.value.security_groups, []), local.security_group_ids))
ipv6_prefix_count = try(network_interfaces.value.ipv6_prefix_count, null)
ipv6_prefixes = try(network_interfaces.value.ipv6_prefixes, [])
network_card_index = try(network_interfaces.value.network_card_index, null)
network_interface_id = try(network_interfaces.value.network_interface_id, null)
private_ip_address = try(network_interfaces.value.private_ip_address, null)
# Ref: https://github.com/hashicorp/terraform-provider-aws/issues/4570
security_groups = compact(concat(try(network_interfaces.value.security_groups, []), local.security_group_ids))
# Set on EKS managed node group, will fail if set here
# https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html#launch-template-basics
# subnet_id = lookup(network_interfaces.value, "subnet_id", null)
# subnet_id = try(network_interfaces.value.subnet_id, null)
}
}
dynamic "placement" {
for_each = length(var.placement) > 0 ? [var.placement] : []
content {
affinity = lookup(placement.value, "affinity", null)
availability_zone = lookup(placement.value, "availability_zone", null)
group_name = lookup(placement.value, "group_name", null)
host_id = lookup(placement.value, "host_id", null)
spread_domain = lookup(placement.value, "spread_domain", null)
tenancy = lookup(placement.value, "tenancy", null)
partition_number = lookup(placement.value, "partition_number", null)
affinity = try(placement.value.affinity, null)
availability_zone = try(placement.value.availability_zone, null)
group_name = try(placement.value.group_name, null)
host_id = try(placement.value.host_id, null)
host_resource_group_arn = try(placement.value.host_resource_group_arn, null)
partition_number = try(placement.value.partition_number, null)
spread_domain = try(placement.value.spread_domain, null)
tenancy = try(placement.value.tenancy, null)
}
}
dynamic "private_dns_name_options" {
for_each = length(var.private_dns_name_options) > 0 ? [var.private_dns_name_options] : []
content {
enable_resource_name_dns_aaaa_record = try(private_dns_name_options.value.enable_resource_name_dns_aaaa_record, null)
enable_resource_name_dns_a_record = try(private_dns_name_options.value.enable_resource_name_dns_a_record, null)
hostname_type = try(private_dns_name_options.value.hostname_type, null)
}
}
ram_disk_id = var.ram_disk_id
dynamic "tag_specifications" {
for_each = toset(["instance", "volume", "network-interface"])
content {
resource_type = tag_specifications.key
tags = merge(var.tags, { Name = var.name }, var.launch_template_tags)
}
}
lifecycle {
create_before_destroy = true
}
update_default_version = var.update_launch_template_default_version
user_data = module.user_data.user_data
vpc_security_group_ids = length(var.network_interfaces) > 0 ? [] : local.security_group_ids
# Prevent premature access of security group roles and policies by pods that
tags = var.tags
# Prevent premature access of policies by pods that
# require permissions on create/destroy that depend on nodes
depends_on = [
aws_security_group_rule.this,
aws_iam_role_policy_attachment.this,
]
tags = var.tags
lifecycle {
create_before_destroy = true
}
}
################################################################################
@@ -264,7 +300,7 @@ resource "aws_launch_template" "this" {
################################################################################
locals {
launch_template_name = try(aws_launch_template.this[0].name, var.launch_template_name, null)
launch_template_id = var.create && var.create_launch_template ? aws_launch_template.this[0].id : var.launch_template_id
# Change order to allow users to set version priority before using defaults
launch_template_version = coalesce(var.launch_template_version, try(aws_launch_template.this[0].default_version, "$Default"))
}
@@ -293,21 +329,23 @@ resource "aws_eks_node_group" "this" {
version = var.ami_id != "" ? null : var.cluster_version
capacity_type = var.capacity_type
disk_size = local.use_custom_launch_template ? null : var.disk_size # if using LT, set disk size on LT or else it will error here
disk_size = var.use_custom_launch_template ? null : var.disk_size # if using a custom LT, set disk size on custom LT or else it will error here
force_update_version = var.force_update_version
instance_types = var.instance_types
labels = var.labels
dynamic "launch_template" {
for_each = local.use_custom_launch_template ? [1] : []
for_each = var.use_custom_launch_template ? [1] : []
content {
name = local.launch_template_name
id = local.launch_template_id
version = local.launch_template_version
}
}
dynamic "remote_access" {
for_each = length(var.remote_access) > 0 ? [var.remote_access] : []
content {
ec2_ssh_key = try(remote_access.value.ec2_ssh_key, null)
source_security_group_ids = try(remote_access.value.source_security_group_ids, [])
@@ -316,15 +354,17 @@ resource "aws_eks_node_group" "this" {
dynamic "taint" {
for_each = var.taints
content {
key = taint.value.key
value = lookup(taint.value, "value")
value = try(taint.value.value, null)
effect = taint.value.effect
}
}
dynamic "update_config" {
for_each = length(var.update_config) > 0 ? [var.update_config] : []
content {
max_unavailable_percentage = try(update_config.value.max_unavailable_percentage, null)
max_unavailable = try(update_config.value.max_unavailable, null)
@@ -350,68 +390,14 @@ resource "aws_eks_node_group" "this" {
)
}
################################################################################
# Security Group
################################################################################
locals {
security_group_name = coalesce(var.security_group_name, "${var.name}-eks-node-group")
create_security_group = var.create && var.create_security_group
}
resource "aws_security_group" "this" {
count = local.create_security_group ? 1 : 0
name = var.security_group_use_name_prefix ? null : local.security_group_name
name_prefix = var.security_group_use_name_prefix ? "${local.security_group_name}-" : null
description = var.security_group_description
vpc_id = var.vpc_id
tags = merge(
var.tags,
{ "Name" = local.security_group_name },
var.security_group_tags
)
# https://github.com/hashicorp/terraform-provider-aws/issues/2445
# https://github.com/hashicorp/terraform-provider-aws/issues/9692
lifecycle {
create_before_destroy = true
}
}
resource "aws_security_group_rule" "this" {
for_each = { for k, v in var.security_group_rules : k => v if local.create_security_group }
# Required
security_group_id = aws_security_group.this[0].id
protocol = each.value.protocol
from_port = each.value.from_port
to_port = each.value.to_port
type = each.value.type
# Optional
description = try(each.value.description, null)
cidr_blocks = try(each.value.cidr_blocks, null)
ipv6_cidr_blocks = try(each.value.ipv6_cidr_blocks, null)
prefix_list_ids = try(each.value.prefix_list_ids, [])
self = try(each.value.self, null)
source_security_group_id = try(
each.value.source_security_group_id,
try(each.value.source_cluster_security_group, false) ? var.cluster_security_group_id : null
)
}
################################################################################
# IAM Role
################################################################################
locals {
iam_role_name = coalesce(var.iam_role_name, "${var.name}-eks-node-group")
iam_role_name = coalesce(var.iam_role_name, "${var.name}-eks-node-group")
iam_role_policy_prefix = "arn:${data.aws_partition.current.partition}:iam::aws:policy"
cni_policy = var.cluster_ip_family == "ipv6" ? "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:policy/AmazonEKS_CNI_IPv6_Policy" : "${local.iam_role_policy_prefix}/AmazonEKS_CNI_Policy"
cni_policy = var.cluster_ip_family == "ipv6" ? "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:policy/AmazonEKS_CNI_IPv6_Policy" : "${local.iam_role_policy_prefix}/AmazonEKS_CNI_Policy"
}
data "aws_iam_policy_document" "assume_role_policy" {
@@ -445,11 +431,18 @@ resource "aws_iam_role" "this" {
# Policies attached ref https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group
resource "aws_iam_role_policy_attachment" "this" {
for_each = var.create && var.create_iam_role ? toset(compact(distinct(concat([
for_each = { for k, v in toset(compact([
"${local.iam_role_policy_prefix}/AmazonEKSWorkerNodePolicy",
"${local.iam_role_policy_prefix}/AmazonEC2ContainerRegistryReadOnly",
var.iam_role_attach_cni_policy ? local.cni_policy : "",
], var.iam_role_additional_policies)))) : toset([])
])) : k => v if var.create && var.create_iam_role }
policy_arn = each.value
role = aws_iam_role.this[0].name
}
resource "aws_iam_role_policy_attachment" "additional" {
for_each = { for k, v in var.iam_role_additional_policies : k => v if var.create && var.create_iam_role }
policy_arn = each.value
role = aws_iam_role.this[0].name