https://github.com/native-cube/terraform-aws-eks
https://github.com/native-cube/terraform-aws-eks
Last synced: 18 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/native-cube/terraform-aws-eks
- Owner: native-cube
- Created: 2026-06-15T13:22:18.000Z (24 days ago)
- Default Branch: main
- Last Pushed: 2026-06-15T14:14:14.000Z (24 days ago)
- Last Synced: 2026-06-15T15:24:28.761Z (24 days ago)
- Language: HCL
- Size: 35.2 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Agents: AGENTS.md
Awesome Lists containing this project
README
# Terraform AWS EKS Module
Simple Terraform module for creating an Amazon EKS cluster with:
- EKS control plane IAM role
- Managed node group IAM role
- One or more EKS managed node groups
- Core EKS add-ons: `coredns`, `kube-proxy`, and `vpc-cni`
- Optional EKS-side Karpenter readiness without installing Karpenter itself
- Useful connection and composition outputs
The module expects you to provide existing subnet IDs. In most deployments these should be private subnets with outbound internet access through NAT.
## Usage
```hcl
module "eks" {
source = "./eks"
name = "dev"
cluster_name = "dev-eks"
subnet_ids = ["subnet-0123456789abcdef0", "subnet-0fedcba9876543210"]
node_groups = {
default = {
instance_types = ["t3.medium"]
min_size = 1
desired_size = 2
max_size = 3
}
}
tags = {
Environment = "dev"
}
}
```
Then configure `kubectl`:
```bash
aws eks update-kubeconfig --name dev-eks
```
## Examples
- `examples/minimal` - smallest practical module call using defaults for node groups, add-ons, API access, and logging.
- `examples/basic` - simple explicit managed node group configuration.
- `examples/advanced` - restricted API access, full control-plane logging, multiple node groups, expanded add-on configuration, optional IAM-backed add-ons, and optional node subnet overrides.
- `examples/karpenter-ready` - EKS-side Karpenter readiness with discovery tags, a Karpenter node role, and node access entry while leaving the Karpenter controller, Helm release, interruption queue, NodePool, and EC2NodeClass to a separate module.
## Karpenter Readiness
Enable the `karpenter` object when this module should prepare the cluster for Karpenter-managed capacity:
```hcl
module "eks" {
source = "./eks"
name = "dev"
subnet_ids = ["subnet-0123456789abcdef0", "subnet-0fedcba9876543210"]
karpenter = {
enabled = true
create_node_iam_role = true
create_access_entry = true
}
}
```
When enabled, the module can create the worker-node IAM role used by Karpenter-launched EC2 instances, authorize that role with an EKS `EC2_LINUX` access entry, and tag selected subnets plus the EKS-created cluster security group with `karpenter.sh/discovery = `.
This module deliberately does not install the Karpenter controller, create its controller IAM role, create an interruption queue, or manage `NodePool` and `EC2NodeClass` resources. Use the `karpenter_*` outputs as inputs to that separate layer.
## Module Documentation
## Requirements
| Name | Version |
| ---- | ------- |
| [terraform](#requirement\_terraform) | >= 1.5.0 |
| [aws](#requirement\_aws) | >= 6.0 |
## Providers
| Name | Version |
| ---- | ------- |
| [aws](#provider\_aws) | >= 6.0 |
## Resources
| Name | Type |
| ---- | ---- |
| [aws_cloudwatch_log_group.cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource |
| [aws_ec2_tag.karpenter_cluster_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_tag) | resource |
| [aws_ec2_tag.karpenter_subnets](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_tag) | resource |
| [aws_eks_access_entry.karpenter_node](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_access_entry) | resource |
| [aws_eks_addon.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_addon) | resource |
| [aws_eks_cluster.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster) | resource |
| [aws_eks_node_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource |
| [aws_iam_role.cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.karpenter_node](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.node](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy_attachment.cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.karpenter_node](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.node](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
## Inputs
| Name | Description | Type | Default | Required |
| ---- | ----------- | ---- | ------- | :------: |
| [access\_config](#input\_access\_config) | Optional EKS access configuration for cluster authentication mode and creator admin permissions. |
object({
authentication_mode = optional(string)
bootstrap_cluster_creator_admin_permissions = optional(bool)
}) | `null` | no |
| [addons](#input\_addons) | EKS add-ons to install after the managed node groups are created. | map(object({
configuration_values = optional(string)
pod_identity_associations = optional(list(object({
role_arn = string
service_account = string
})), [])
resolve_conflicts_on_create = optional(string, "OVERWRITE")
resolve_conflicts_on_update = optional(string, "OVERWRITE")
service_account_role_arn = optional(string)
version = optional(string)
})) | {
"coredns": {},
"kube-proxy": {},
"vpc-cni": {}
} | no |
| [cloudwatch\_log\_group\_kms\_key\_id](#input\_cloudwatch\_log\_group\_kms\_key\_id) | Optional KMS key ID or ARN for encrypting the EKS control plane CloudWatch log group. | `string` | `null` | no |
| [cloudwatch\_log\_retention\_days](#input\_cloudwatch\_log\_retention\_days) | Retention in days for the EKS control plane CloudWatch log group. | `number` | `30` | no |
| [cluster\_encryption\_config](#input\_cluster\_encryption\_config) | Optional EKS encryption configuration for Kubernetes secrets using an existing KMS key. | object({
provider_key_arn = string
resources = optional(list(string), ["secrets"])
}) | `null` | no |
| [cluster\_name](#input\_cluster\_name) | Optional EKS cluster name. When null, name is used as the cluster name. | `string` | `null` | no |
| [cluster\_security\_group\_ids](#input\_cluster\_security\_group\_ids) | Additional security group IDs to associate with the EKS control plane. | `list(string)` | `[]` | no |
| [deletion\_protection](#input\_deletion\_protection) | Whether to enable deletion protection for the EKS cluster. Leave null to use the AWS/provider default. | `bool` | `null` | no |
| [enabled\_cluster\_log\_types](#input\_enabled\_cluster\_log\_types) | EKS control plane log types to enable. | `list(string)` | [
"api",
"audit",
"authenticator"
]
| no |
| [endpoint\_private\_access](#input\_endpoint\_private\_access) | Whether the Kubernetes API server endpoint is reachable from within the VPC. | `bool` | `true` | no |
| [endpoint\_public\_access](#input\_endpoint\_public\_access) | Whether the Kubernetes API server endpoint is reachable from the public internet. | `bool` | `true` | no |
| [karpenter](#input\_karpenter) | Optional EKS-side readiness settings for Karpenter. This module prepares AWS/EKS primitives only; install Karpenter, controller IAM, interruption handling, NodePools, and EC2NodeClasses separately. | object({
create_access_entry = optional(bool, true)
create_node_iam_role = optional(bool, true)
enabled = optional(bool, false)
node_iam_role_arn = optional(string)
node_iam_role_name = optional(string)
subnet_ids = optional(list(string), [])
tag_cluster_security_group = optional(bool, true)
tag_subnets = optional(bool, true)
}) | `{}` | no |
| [kubernetes\_version](#input\_kubernetes\_version) | Kubernetes version for the EKS cluster and managed node groups. Leave null to use the current AWS default. | `string` | `null` | no |
| [name](#input\_name) | Name prefix for module-created resources. Used as the EKS cluster name when cluster\_name is null. | `string` | n/a | yes |
| [node\_groups](#input\_node\_groups) | Managed node groups to create. | map(object({
ami_type = optional(string)
capacity_type = optional(string, "ON_DEMAND")
desired_size = optional(number, 2)
disk_size = optional(number, 20)
instance_types = optional(list(string), ["t3.medium"])
labels = optional(map(string), {})
max_size = optional(number, 3)
min_size = optional(number, 1)
subnet_ids = optional(list(string), [])
update_max_unavailable = optional(number, 1)
node_repair_config = optional(object({
enabled = optional(bool)
max_parallel_nodes_repaired_count = optional(number)
max_parallel_nodes_repaired_percentage = optional(number)
max_unhealthy_node_threshold_count = optional(number)
max_unhealthy_node_threshold_percentage = optional(number)
overrides = optional(list(object({
min_repair_wait_time_mins = number
node_monitoring_condition = string
node_unhealthy_reason = string
repair_action = string
})), [])
}))
taints = optional(list(object({
effect = string
key = string
value = optional(string, "")
})), [])
})) | {
"default": {}
} | no |
| [public\_access\_cidrs](#input\_public\_access\_cidrs) | CIDR blocks that can access the public Kubernetes API endpoint. | `list(string)` | [
"0.0.0.0/0"
]
| no |
| [service\_ipv4\_cidr](#input\_service\_ipv4\_cidr) | Optional Kubernetes service IPv4 CIDR. Set only when you need a non-default service CIDR. | `string` | `null` | no |
| [subnet\_ids](#input\_subnet\_ids) | Subnet IDs for the EKS control plane and default node groups. Use at least two subnets in different Availability Zones. | `list(string)` | n/a | yes |
| [tags](#input\_tags) | Tags to apply to created resources. | `map(string)` | `{}` | no |
## Outputs
| Name | Description |
| ---- | ----------- |
| [addon\_arns](#output\_addon\_arns) | EKS add-on ARNs by add-on name. |
| [cluster\_arn](#output\_cluster\_arn) | EKS cluster ARN. |
| [cluster\_certificate\_authority\_data](#output\_cluster\_certificate\_authority\_data) | Base64-encoded cluster certificate authority data. |
| [cluster\_endpoint](#output\_cluster\_endpoint) | Kubernetes API server endpoint. |
| [cluster\_iam\_role\_arn](#output\_cluster\_iam\_role\_arn) | IAM role ARN used by the EKS control plane. |
| [cluster\_log\_group\_name](#output\_cluster\_log\_group\_name) | CloudWatch log group for EKS control plane logs, if cluster logs are enabled. |
| [cluster\_name](#output\_cluster\_name) | EKS cluster name. |
| [cluster\_oidc\_issuer\_url](#output\_cluster\_oidc\_issuer\_url) | OIDC issuer URL for the EKS cluster. |
| [cluster\_security\_group\_id](#output\_cluster\_security\_group\_id) | Security group created by EKS for the cluster. |
| [karpenter\_discovery\_tag\_key](#output\_karpenter\_discovery\_tag\_key) | Tag key used by Karpenter discovery selectors when Karpenter readiness is enabled. |
| [karpenter\_discovery\_tag\_value](#output\_karpenter\_discovery\_tag\_value) | Tag value used by Karpenter discovery selectors when Karpenter readiness is enabled. |
| [karpenter\_node\_iam\_role\_arn](#output\_karpenter\_node\_iam\_role\_arn) | IAM role ARN for Karpenter-launched worker nodes when Karpenter readiness is enabled. |
| [karpenter\_node\_iam\_role\_name](#output\_karpenter\_node\_iam\_role\_name) | IAM role name for Karpenter EC2NodeClass role configuration when Karpenter readiness is enabled. |
| [node\_group\_arns](#output\_node\_group\_arns) | Managed node group ARNs by node group key. |
| [node\_iam\_role\_arn](#output\_node\_iam\_role\_arn) | IAM role ARN used by managed node groups. |
| [update\_kubeconfig\_command](#output\_update\_kubeconfig\_command) | AWS CLI command to configure kubectl for this cluster. |
## Git Hooks
Enable the repository hooks after cloning or initializing Git:
```bash
git config core.hooksPath .githooks
```
The pre-commit hook checks Terraform formatting and verifies that generated Terraform docs in this README are up to date.
Regenerate the README module documentation manually with:
```bash
scripts/terraform-docs.sh
```
## Tests
Native Terraform tests live in `tests/` and use mocked AWS provider resources, so they can run without AWS credentials or creating infrastructure:
```bash
terraform test
```
Pull requests run the same tests through `.github/workflows/terraform-pr.yml`, along with formatting, generated-docs, validation, and example checks.
## Local Development
Use the Makefile for common local checks:
```bash
make fmt
make docs
make check
```
## Notes
- The module does not create VPC, subnet, route table, NAT gateway, or security baseline resources.
- For production use, restrict `public_access_cidrs` instead of leaving the default `0.0.0.0/0`.
- Node group subnets default to `subnet_ids`, but each node group can override them with its own `subnet_ids`.