Skip to content

tfstack/terraform-aws-eks-basic

Repository files navigation

terraform-aws-eks-basic

⚠️ Note: This module has been revamped and currently supports EC2 managed node groups only. Fargate and AutoMode support are not available in this version.

A Terraform module for creating and managing Amazon EKS (Elastic Kubernetes Service) clusters with EC2 managed node groups.

Features

  • EC2 Managed Node Groups: Full support with customizable launch templates and auto-scaling
  • Dual-Stack Support: IPv4 and IPv6 cluster support (IPv6 service CIDR auto-assigned by AWS)
  • Modern EKS Access Entries: Native EKS authentication via access entries (no aws-auth ConfigMap)
  • IRSA Support: OIDC provider setup for IAM Roles for Service Accounts
  • EKS Addons: Flexible addon configuration (CoreDNS, VPC CNI, Kube-proxy, Pod Identity Agent, EBS CSI Driver)
  • EKS Capabilities: Support for ACK, KRO, and ArgoCD capabilities
  • AWS Load Balancer Controller: Optional IAM role creation for AWS Load Balancer Controller (IRSA)
  • Security: KMS encryption, IMDSv2 enforcement, security groups
  • CloudWatch Log Group: Optional log group for EKS control plane logs; set cloudwatch_log_group_force_destroy = true to allow the log group to be deleted on terraform destroy (default is to protect it).

Prerequisites

Name Version
terraform >= 1.6.0
aws >= 6.0
kubernetes ~> 2.30
helm ~> 2.13
tls ~> 4.0

Usage

Basic Example

module "eks" {
  source = "tfstack/eks-basic/aws"

  name               = "my-eks-cluster"
  kubernetes_version = "1.35"
  vpc_id             = "vpc-12345678"
  subnet_ids         = ["subnet-12345678", "subnet-87654321"]

  endpoint_public_access = true

  # Configure access entries for cluster access
  access_entries = {
    admin = {
      principal_arn = "arn:aws:iam::123456789012:role/admin-role"
      type          = "STANDARD"
      policy_associations = {
        admin = {
          policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy"
          access_scope = {
            type = "cluster"
          }
        }
      }
    }
  }

  # Configure EKS addons
  addons = {
    coredns = {
      addon_version = "v1.13.2-eksbuild.1"
    }
    kube-proxy = {
      addon_version = "v1.35.0-eksbuild.2"
    }
    vpc-cni = {
      before_compute = true
      addon_version  = "v1.21.1-eksbuild.3"
    }
    eks-pod-identity-agent = {
      before_compute = true
      addon_version  = "v1.3.10-eksbuild.2"
    }
  }

  # Configure managed node groups
  eks_managed_node_groups = {
    default = {
      name           = "node-group-1"
      ami_type       = "AL2023_x86_64_STANDARD"
      instance_types = ["t3.medium"]
      min_size       = 1
      max_size       = 3
      desired_size   = 2
      disk_size      = 20
    }
  }

  tags = {
    Environment = "production"
    ManagedBy   = "terraform"
  }
}

Examples

Requirements

Name Version
terraform >= 1.6.0
aws >= 6.0
helm >= 2.13
kubernetes >= 2.30
tls >= 4.0

Providers

Name Version
aws 6.28.0
time 0.13.1
tls 4.1.0

Modules

No modules.

Resources

Name Type
aws_cloudwatch_log_group.this_allow_destroy resource
aws_cloudwatch_log_group.this_prevent_destroy resource
aws_eks_access_entry.this resource
aws_eks_access_policy_association.this resource
aws_eks_addon.before_compute resource
aws_eks_addon.this resource
aws_eks_capability.this resource
aws_eks_cluster.this resource
aws_eks_node_group.this resource
aws_iam_instance_profile.eks_nodes resource
aws_iam_openid_connect_provider.oidc_provider resource
aws_iam_policy.cluster_encryption resource
aws_iam_role.addon resource
aws_iam_role.aws_lb_controller resource
aws_iam_role.capability resource
aws_iam_role.eks_nodes resource
aws_iam_role.this resource
aws_iam_role_policy_attachment.aws_lb_controller resource
aws_iam_role_policy_attachment.capability resource
aws_iam_role_policy_attachment.cluster_encryption resource
aws_iam_role_policy_attachment.ebs_csi_driver resource
aws_iam_role_policy_attachment.eks_nodes resource
aws_iam_role_policy_attachment.this resource
aws_kms_alias.this resource
aws_kms_key.this resource
aws_launch_template.node_group resource
aws_security_group.cluster resource
aws_security_group.node resource
aws_security_group_rule.cluster resource
aws_security_group_rule.node_cidr resource
aws_security_group_rule.node_ipv6_egress resource
aws_security_group_rule.node_self resource
aws_security_group_rule.node_sg resource
time_sleep.this resource
aws_caller_identity.current data source
aws_eks_cluster_auth.this data source
aws_iam_policy_document.addon_assume_role data source
aws_iam_policy_document.aws_lb_controller_assume_role data source
aws_iam_policy_document.capability_assume_role data source
aws_iam_policy_document.eks_cluster_assume_role data source
aws_iam_policy_document.eks_nodes_assume_role data source
aws_iam_policy_document.kms_key data source
aws_iam_policy_document.this data source
aws_partition.current data source
aws_region.current data source
tls_certificate.this data source

Inputs

Name Description Type Default Required
access_entries Map of access entries to add to the cluster
map(object({
# Access entry
kubernetes_groups = optional(list(string))
principal_arn = string
type = optional(string, "STANDARD")
user_name = optional(string)
tags = optional(map(string), {})
# Access policy association
policy_associations = optional(map(object({
policy_arn = string
access_scope = object({
namespaces = optional(list(string))
type = string
})
})), {})
}))
{} no
addons Map of EKS addons to enable
map(object({
addon_version = optional(string)
before_compute = optional(bool, false)
configuration_values = optional(string)
resolve_conflicts_on_create = optional(string, "OVERWRITE")
resolve_conflicts_on_update = optional(string, "OVERWRITE")
service_account_role_arn = optional(string)
}))
{} no
capabilities Map of EKS capabilities to enable. Valid keys: ack, kro, argocd
map(object({
role_arn = optional(string)
iam_policy_arns = optional(map(string), {})
configuration = optional(string)
delete_propagation_policy = optional(string, "RETAIN")
}))
{} no
cloudwatch_log_group_class Specifies the log class of the log group. Valid values are: STANDARD or INFREQUENT_ACCESS string null no
cloudwatch_log_group_force_destroy When true, allow the CloudWatch log group to be deleted on terraform destroy. When false, protect it with lifecycle { prevent_destroy = true }. bool false no
cloudwatch_log_group_kms_key_id The ARN of the KMS Key to use when encrypting log data string null no
cloudwatch_log_group_retention_in_days Number of days to retain log events in the CloudWatch log group number 14 no
cloudwatch_log_group_tags Additional tags to apply to the CloudWatch log group map(string) {} no
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
cluster_encryption_config_key_arn ARN of the KMS key to use for encrypting Kubernetes secrets string null no
cluster_encryption_config_resources List of strings with resources to be encrypted. Valid values: secrets list(string)
[
"secrets"
]
no
cluster_ip_family IP family for the EKS cluster. Valid values: ipv4, ipv6 string "ipv4" no
create_cloudwatch_log_group Whether to create a CloudWatch log group for EKS cluster logs bool true no
create_kms_key Controls if a KMS key for cluster encryption should be created bool true no
eks_managed_node_groups Map of EKS managed node group configurations
map(object({
name = optional(string)
ami_type = optional(string, "AL2023_x86_64_STANDARD")
instance_types = optional(list(string), ["t3.medium"])
min_size = optional(number, 1)
max_size = optional(number, 3)
desired_size = optional(number, 2)
disk_size = optional(number, 20)
subnet_ids = optional(list(string))
enable_bootstrap_user_data = optional(bool, true)
metadata_options = optional(object({
http_endpoint = optional(string, "enabled")
http_tokens = optional(string, "required")
http_put_response_hop_limit = optional(number, 1)
}))
labels = optional(map(string), {})
tags = optional(map(string), {})
}))
{} no
enable_aws_load_balancer_controller Whether to create IAM role for AWS Load Balancer Controller (IRSA) bool false no
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
enabled_cluster_log_types List of control plane logging types to enable list(string)
[
"api",
"audit",
"authenticator"
]
no
endpoint_public_access Whether the Amazon EKS public API server endpoint is enabled bool true no
kubernetes_version Kubernetes version to use for the EKS cluster string n/a yes
name Name of the EKS cluster string n/a yes
public_access_cidrs List of CIDR blocks that can access the Amazon EKS public API server endpoint list(string)
[
"0.0.0.0/0"
]
no
region AWS region for CloudWatch log group string "ap-southeast-2" no
service_ipv4_cidr IPv4 CIDR block for Kubernetes services. Required for all clusters. Must not overlap with VPC CIDR. If not provided, EKS will auto-assign. string null no
subnet_ids Subnet IDs for EKS cluster control plane (should include both public and private) list(string) n/a yes
tags Map of tags to apply to all resources map(string) {} no
vpc_id VPC ID where the cluster is deployed string n/a yes

Outputs

Name Description
access_entries Map of access entries created and their attributes
access_policy_associations Map of eks cluster access policy associations created and their attributes
aws_load_balancer_controller_role_arn IAM role ARN for AWS Load Balancer Controller (when enabled)
cloudwatch_log_group_arn Arn of cloudwatch log group created
cloudwatch_log_group_name Name of cloudwatch log group created
cluster_addons Map of attribute maps for all EKS cluster addons enabled
cluster_arn The Amazon Resource Name (ARN) of the cluster
cluster_auth_token Token to authenticate with the EKS cluster
cluster_ca_certificate Decoded certificate data required to communicate with the cluster
cluster_certificate_authority_data Base64 encoded certificate data required to communicate with the cluster
cluster_endpoint Endpoint for your Kubernetes API server
cluster_iam_role_arn Cluster IAM role ARN
cluster_iam_role_name Cluster IAM role name
cluster_ip_family The IP family used by the cluster (e.g. ipv4 or ipv6)
cluster_name The name of the EKS cluster
cluster_oidc_issuer_url The URL on the EKS cluster for the OpenID Connect identity provider
cluster_platform_version Platform version for the cluster
cluster_primary_security_group_id Cluster security group that was created by Amazon EKS for the cluster
cluster_security_group_id ID of the cluster security group
cluster_service_cidr The IPv4 CIDR block where Kubernetes pod and service IP addresses are assigned from
cluster_service_ipv6_cidr The IPv6 CIDR block where Kubernetes pod and service IP addresses are assigned from (when ip_family is ipv6)
cluster_version The Kubernetes version for the cluster
eks_managed_node_groups Map of attribute maps for all EKS managed node groups created
kms_key_arn The Amazon Resource Name (ARN) of the key
kms_key_id The globally unique identifier for the key
launch_templates Map of launch templates created for node groups
node_iam_role_arn Node IAM role ARN
node_iam_role_name Node IAM role name
node_security_group_id ID of the node shared security group
oidc_provider The OpenID Connect identity provider (issuer URL without leading https://)
oidc_provider_arn The ARN of the OIDC Provider

Connecting to the Cluster

After the cluster is created, configure kubectl:

aws eks update-kubeconfig --name <cluster_name> --region <aws_region>

Verify connection:

kubectl get nodes

Testing

The module includes comprehensive tests using Terraform's test framework. Run tests with:

terraform test

Module Structure

terraform-aws-eks-basic/
├── main.tf              # Core EKS cluster, node groups, addons, OIDC provider
├── access-entries.tf    # EKS access entries for authentication
├── capabilities.tf      # EKS Capabilities (ACK, KRO, ArgoCD)
├── capabilities-iam.tf  # IAM roles for EKS Capabilities
├── addons-iam.tf        # IAM roles for addons (EBS CSI, etc)
├── locals.tf            # Local values and computed configurations
├── cluster-auth.tf      # Cluster authentication data source
├── variables.tf         # Input variables
├── outputs.tf           # Output values
├── versions.tf          # Provider version constraints
├── README.md            # This file
└── examples/
    ├── basic/           # Basic usage example
    ├── ebs-web-app/     # Example with VPC and node groups
    └── eks-capabilities/ # Platform engineering with capabilities

License

MIT License - see LICENSE file for details.

About

Simple EKS cluster Terraform module

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •