Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ No modules.
| [aws_eks_node_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource |
| [aws_eks_pod_identity_association.addon](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_pod_identity_association) | resource |
| [aws_eks_pod_identity_association.aws_lb_controller](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_pod_identity_association) | resource |
| [aws_eks_pod_identity_association.cluster_autoscaler](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_pod_identity_association) | resource |
| [aws_eks_pod_identity_association.dynamodb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_pod_identity_association) | resource |
| [aws_eks_pod_identity_association.ebs_csi_driver](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_pod_identity_association) | resource |
| [aws_eks_pod_identity_association.external_dns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_pod_identity_association) | resource |
Expand All @@ -341,6 +342,7 @@ No modules.
| [aws_iam_role.addon](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.aws_lb_controller](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.capability](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.cluster_autoscaler](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.dynamodb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.ebs_csi_driver](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.eks_automode_nodes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
Expand All @@ -353,6 +355,7 @@ No modules.
| [aws_iam_role.sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy.argocd_codeconnections](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
| [aws_iam_role_policy.cluster_autoscaler](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
| [aws_iam_role_policy.dynamodb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
| [aws_iam_role_policy.external_dns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
| [aws_iam_role_policy.kinesis](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
Expand Down Expand Up @@ -392,6 +395,9 @@ No modules.
| [aws_iam_policy_document.aws_lb_controller_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.aws_lb_controller_assume_role_pod_identity](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.capability_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.cluster_autoscaler](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.cluster_autoscaler_assume_role_irsa](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.cluster_autoscaler_assume_role_pod_identity](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.dynamodb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.dynamodb_assume_role_irsa](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.dynamodb_assume_role_pod_identity](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
Expand Down Expand Up @@ -441,6 +447,9 @@ No modules.
| <a name="input_cloudwatch_log_group_retention_in_days"></a> [cloudwatch\_log\_group\_retention\_in\_days](#input\_cloudwatch\_log\_group\_retention\_in\_days) | Number of days to retain log events in the CloudWatch log group | `number` | `14` | no |
| <a name="input_cloudwatch_log_group_tags"></a> [cloudwatch\_log\_group\_tags](#input\_cloudwatch\_log\_group\_tags) | Additional tags to apply to the CloudWatch log group | `map(string)` | `{}` | no |
| <a name="input_cluster_authentication_mode"></a> [cluster\_authentication\_mode](#input\_cluster\_authentication\_mode) | Authentication mode for the EKS cluster. Valid values: CONFIG\_MAP, API, API\_AND\_CONFIG\_MAP. Defaults to API\_AND\_CONFIG\_MAP when capabilities are enabled, otherwise CONFIG\_MAP. | `string` | `"API_AND_CONFIG_MAP"` | no |
| <a name="input_cluster_autoscaler_identity_type"></a> [cluster\_autoscaler\_identity\_type](#input\_cluster\_autoscaler\_identity\_type) | Identity type for Cluster Autoscaler. Use 'pod\_identity' to create Pod Identity association; requires eks-pod-identity-agent addon. | `string` | `"irsa"` | no |
| <a name="input_cluster_autoscaler_namespace"></a> [cluster\_autoscaler\_namespace](#input\_cluster\_autoscaler\_namespace) | Kubernetes namespace for Cluster Autoscaler service account. Used for IRSA OIDC condition and when cluster\_autoscaler\_identity\_type = 'pod\_identity'. | `string` | `"kube-system"` | no |
| <a name="input_cluster_autoscaler_service_account"></a> [cluster\_autoscaler\_service\_account](#input\_cluster\_autoscaler\_service\_account) | Kubernetes service account name for Cluster Autoscaler. Used for IRSA OIDC condition and when cluster\_autoscaler\_identity\_type = 'pod\_identity'. | `string` | `"cluster-autoscaler"` | no |
| <a name="input_cluster_encryption_config_key_arn"></a> [cluster\_encryption\_config\_key\_arn](#input\_cluster\_encryption\_config\_key\_arn) | ARN of the KMS key to use for encrypting Kubernetes secrets | `string` | `null` | no |
| <a name="input_cluster_encryption_config_resources"></a> [cluster\_encryption\_config\_resources](#input\_cluster\_encryption\_config\_resources) | List of strings with resources to be encrypted. Valid values: secrets | `list(string)` | <pre>[<br/> "secrets"<br/>]</pre> | no |
| <a name="input_cluster_ip_family"></a> [cluster\_ip\_family](#input\_cluster\_ip\_family) | IP family for the EKS cluster. Valid values: ipv4, ipv6 | `string` | `"ipv4"` | no |
Expand All @@ -456,6 +465,7 @@ No modules.
| <a name="input_eks_managed_node_groups"></a> [eks\_managed\_node\_groups](#input\_eks\_managed\_node\_groups) | Map of EKS managed node group configurations | <pre>map(object({<br/> name = optional(string)<br/> ami_type = optional(string, "AL2023_x86_64_STANDARD")<br/> instance_types = optional(list(string), ["t3.medium"])<br/> min_size = optional(number, 1)<br/> max_size = optional(number, 3)<br/> desired_size = optional(number, 2)<br/> disk_size = optional(number, 20)<br/> subnet_ids = optional(list(string))<br/> enable_bootstrap_user_data = optional(bool, true)<br/> metadata_options = optional(object({<br/> http_endpoint = optional(string, "enabled")<br/> http_tokens = optional(string, "required")<br/> http_put_response_hop_limit = optional(number, 1)<br/> }))<br/> labels = optional(map(string), {})<br/> tags = optional(map(string), {})<br/> }))</pre> | `{}` | no |
| <a name="input_enable_automode"></a> [enable\_automode](#input\_enable\_automode) | Enable EKS Auto Mode. Mutually exclusive with eks\_managed\_node\_groups. | `bool` | `false` | no |
| <a name="input_enable_aws_load_balancer_controller"></a> [enable\_aws\_load\_balancer\_controller](#input\_enable\_aws\_load\_balancer\_controller) | Whether to create IAM role for AWS Load Balancer Controller (IRSA) | `bool` | `false` | no |
| <a name="input_enable_cluster_autoscaler_iam"></a> [enable\_cluster\_autoscaler\_iam](#input\_enable\_cluster\_autoscaler\_iam) | Whether to create IAM role for Cluster Autoscaler (IRSA or Pod Identity per cluster\_autoscaler\_identity\_type). For EC2 managed node groups only; not supported with enable\_automode. When true, adds k8s.io/cluster-autoscaler/* tags to managed node groups for ASG autodiscovery. | `bool` | `false` | no |
| <a name="input_enable_cluster_creator_admin_permissions"></a> [enable\_cluster\_creator\_admin\_permissions](#input\_enable\_cluster\_creator\_admin\_permissions) | Indicates whether or not to add the cluster creator (the identity used by Terraform) as an administrator via access entry | `bool` | `false` | no |
| <a name="input_enable_dynamodb_access"></a> [enable\_dynamodb\_access](#input\_enable\_dynamodb\_access) | Whether to create IAM roles for DynamoDB access (IRSA or Pod Identity per dynamodb\_identity\_type). One role per dynamodb\_access entry. | `bool` | `false` | no |
| <a name="input_enable_ebs_csi_driver"></a> [enable\_ebs\_csi\_driver](#input\_enable\_ebs\_csi\_driver) | Whether to create IAM role for EBS CSI driver (IRSA or Pod Identity per ebs\_csi\_driver\_identity\_type) | `bool` | `false` | no |
Expand Down Expand Up @@ -507,6 +517,7 @@ No modules.
| <a name="output_cluster_addons"></a> [cluster\_addons](#output\_cluster\_addons) | Map of attribute maps for all EKS cluster addons enabled |
| <a name="output_cluster_arn"></a> [cluster\_arn](#output\_cluster\_arn) | The Amazon Resource Name (ARN) of the cluster |
| <a name="output_cluster_auth_token"></a> [cluster\_auth\_token](#output\_cluster\_auth\_token) | Token to authenticate with the EKS cluster |
| <a name="output_cluster_autoscaler_role_arn"></a> [cluster\_autoscaler\_role\_arn](#output\_cluster\_autoscaler\_role\_arn) | IAM role ARN for Cluster Autoscaler (when enable\_cluster\_autoscaler\_iam). For IRSA, annotate the cluster-autoscaler ServiceAccount with this ARN. |
| <a name="output_cluster_ca_certificate"></a> [cluster\_ca\_certificate](#output\_cluster\_ca\_certificate) | Decoded certificate data required to communicate with the cluster |
| <a name="output_cluster_capabilities"></a> [cluster\_capabilities](#output\_cluster\_capabilities) | Map of EKS capability resources (ACK, KRO, Argo CD) keyed by capability name |
| <a name="output_cluster_capability_role_arns"></a> [cluster\_capability\_role\_arns](#output\_cluster\_capability\_role\_arns) | Map of IAM role ARNs for EKS capabilities created by the module (keyed by capability name). Use for ACK controller config or external reference. |
Expand All @@ -519,7 +530,7 @@ No modules.
| <a name="output_cluster_name"></a> [cluster\_name](#output\_cluster\_name) | The name of the EKS cluster |
| <a name="output_cluster_oidc_issuer_url"></a> [cluster\_oidc\_issuer\_url](#output\_cluster\_oidc\_issuer\_url) | The URL on the EKS cluster for the OpenID Connect identity provider |
| <a name="output_cluster_platform_version"></a> [cluster\_platform\_version](#output\_cluster\_platform\_version) | Platform version for the cluster |
| <a name="output_cluster_pod_identity_associations"></a> [cluster\_pod\_identity\_associations](#output\_cluster\_pod\_identity\_associations) | Map of EKS Pod Identity associations (addon, ALB controller, External DNS, EBS CSI driver, Secrets Manager, S3) when using Pod Identity |
| <a name="output_cluster_pod_identity_associations"></a> [cluster\_pod\_identity\_associations](#output\_cluster\_pod\_identity\_associations) | Map of EKS Pod Identity associations (addon, ALB controller, External DNS, EBS CSI driver, Cluster Autoscaler, Secrets Manager, S3) when using Pod Identity |
| <a name="output_cluster_primary_security_group_id"></a> [cluster\_primary\_security\_group\_id](#output\_cluster\_primary\_security\_group\_id) | Cluster security group that was created by Amazon EKS for the cluster |
| <a name="output_cluster_security_group_id"></a> [cluster\_security\_group\_id](#output\_cluster\_security\_group\_id) | ID of the cluster security group |
| <a name="output_cluster_service_cidr"></a> [cluster\_service\_cidr](#output\_cluster\_service\_cidr) | The IPv4 CIDR block where Kubernetes pod and service IP addresses are assigned from |
Expand Down
129 changes: 129 additions & 0 deletions cluster-autoscaler-iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@

################################################################################
# Cluster Autoscaler IAM (IRSA or EKS Pod Identity)
# For EC2 managed node groups only — not compatible with enable_automode or
# Fargate-only clusters. Requires eks-pod-identity-agent addon when using pod_identity.
################################################################################

# IAM assume role policy document for Cluster Autoscaler (IRSA)
data "aws_iam_policy_document" "cluster_autoscaler_assume_role_irsa" {
count = var.enable_cluster_autoscaler_iam ? 1 : 0

statement {
effect = "Allow"

principals {
type = "Federated"
identifiers = [aws_iam_openid_connect_provider.oidc_provider[0].arn]
}

actions = ["sts:AssumeRoleWithWebIdentity"]

condition {
test = "StringEquals"
variable = "${replace(aws_eks_cluster.this.identity[0].oidc[0].issuer, "https://", "")}:sub"
values = ["system:serviceaccount:${var.cluster_autoscaler_namespace}:${var.cluster_autoscaler_service_account}"]
}

condition {
test = "StringEquals"
variable = "${replace(aws_eks_cluster.this.identity[0].oidc[0].issuer, "https://", "")}:aud"
values = ["sts.amazonaws.com"]
}
}
}

# IAM assume role policy document for Cluster Autoscaler (EKS Pod Identity)
data "aws_iam_policy_document" "cluster_autoscaler_assume_role_pod_identity" {
count = var.enable_cluster_autoscaler_iam ? 1 : 0

statement {
effect = "Allow"

principals {
type = "Service"
identifiers = ["pods.eks.amazonaws.com"]
}

actions = [
"sts:AssumeRole",
"sts:TagSession"
]
}
}

resource "aws_iam_role" "cluster_autoscaler" {
count = var.enable_cluster_autoscaler_iam ? 1 : 0

name = "${var.name}-cluster-autoscaler-role"
assume_role_policy = var.cluster_autoscaler_identity_type == "pod_identity" ? data.aws_iam_policy_document.cluster_autoscaler_assume_role_pod_identity[0].json : data.aws_iam_policy_document.cluster_autoscaler_assume_role_irsa[0].json

tags = var.tags

depends_on = [
aws_iam_openid_connect_provider.oidc_provider
]

lifecycle {
precondition {
condition = !var.enable_cluster_autoscaler_iam || (!var.enable_automode && length(var.eks_managed_node_groups) > 0)
error_message = "enable_cluster_autoscaler_iam requires at least one eks_managed_node_groups entry and is not supported when enable_automode is true."
}
}
}

# Permissions per kubernetes/autoscaler AWS provider README (autodiscovery + launch templates).
# Mutating autoscaling calls are restricted to ASGs tagged with eks:cluster-name matching this cluster.
data "aws_iam_policy_document" "cluster_autoscaler" {
count = var.enable_cluster_autoscaler_iam ? 1 : 0

statement {
sid = "AutoscalingEc2EksDescribe"
effect = "Allow"
actions = [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances",
"autoscaling:DescribeLaunchConfigurations",
"autoscaling:DescribeScalingActivities",
"ec2:DescribeImages",
"ec2:DescribeInstanceTypes",
"ec2:DescribeLaunchTemplateVersions",
"ec2:GetInstanceTypesFromInstanceRequirements",
"eks:DescribeNodegroup",
]
resources = ["*"]
}

statement {
sid = "AutoscalingMutateClusterScoped"
effect = "Allow"
actions = [
"autoscaling:SetDesiredCapacity",
"autoscaling:TerminateInstanceInAutoScalingGroup",
]
resources = ["*"]

condition {
test = "StringEquals"
variable = "aws:ResourceTag/eks:cluster-name"
values = [aws_eks_cluster.this.name]
}
}
}

resource "aws_iam_role_policy" "cluster_autoscaler" {
count = var.enable_cluster_autoscaler_iam ? 1 : 0

name = "${var.name}-cluster-autoscaler"
role = aws_iam_role.cluster_autoscaler[0].id
policy = data.aws_iam_policy_document.cluster_autoscaler[0].json
}

resource "aws_eks_pod_identity_association" "cluster_autoscaler" {
count = var.enable_cluster_autoscaler_iam && var.cluster_autoscaler_identity_type == "pod_identity" ? 1 : 0

cluster_name = aws_eks_cluster.this.name
namespace = var.cluster_autoscaler_namespace
service_account = var.cluster_autoscaler_service_account
role_arn = aws_iam_role.cluster_autoscaler[0].arn
}
10 changes: 10 additions & 0 deletions examples/basic/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ output "cluster_version" {
value = module.eks.cluster_version
}

output "karpenter_node_role_name" {
description = "IAM role name for Karpenter-provisioned nodes (must match EC2NodeClass spec.role in kube-infra)"
value = module.eks.karpenter_node_role_name
}

output "karpenter_interruption_queue_name" {
description = "SQS queue name for Karpenter settings.interruptionQueue"
value = module.eks.karpenter_interruption_queue_name
}

output "oidc_provider_arn" {
description = "ARN of the EKS OIDC provider"
value = module.eks.oidc_provider_arn
Expand Down
Loading
Loading